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:
authorYimingWu <xp8110@outlook.com>2019-05-28 10:39:42 +0300
committerYimingWu <xp8110@outlook.com>2019-05-28 10:39:42 +0300
commitf37533fc44cfb8a7eec919df0dae38998de10e2f (patch)
tree264074656a88f96bdc3a4dbf53340277d45dc86a /source/blender
parenta640228d92273154acc644d525b095b5318c248b (diff)
parent1008d9c73567780ec22bea6a0b27f57e60ea403d (diff)
Merge branch 'master' into soc-2019-npr
Diffstat (limited to 'source/blender')
-rw-r--r--source/blender/blenkernel/BKE_appdir.h3
-rw-r--r--source/blender/blenkernel/BKE_blender_version.h2
-rw-r--r--source/blender/blenkernel/BKE_collection.h3
-rw-r--r--source/blender/blenkernel/BKE_curve.h7
-rw-r--r--source/blender/blenkernel/BKE_displist.h6
-rw-r--r--source/blender/blenkernel/BKE_editmesh.h1
-rw-r--r--source/blender/blenkernel/BKE_global.h1
-rw-r--r--source/blender/blenkernel/BKE_library.h2
-rw-r--r--source/blender/blenkernel/BKE_mask.h2
-rw-r--r--source/blender/blenkernel/BKE_mesh.h17
-rw-r--r--source/blender/blenkernel/BKE_object.h12
-rw-r--r--source/blender/blenkernel/BKE_screen.h4
-rw-r--r--source/blender/blenkernel/BKE_sequencer.h10
-rw-r--r--source/blender/blenkernel/BKE_studiolight.h1
-rw-r--r--source/blender/blenkernel/intern/DerivedMesh.c8
-rw-r--r--source/blender/blenkernel/intern/anim_sys.c16
-rw-r--r--source/blender/blenkernel/intern/appdir.c15
-rw-r--r--source/blender/blenkernel/intern/blendfile.c10
-rw-r--r--source/blender/blenkernel/intern/brush.c39
-rw-r--r--source/blender/blenkernel/intern/camera.c2
-rw-r--r--source/blender/blenkernel/intern/collection.c126
-rw-r--r--source/blender/blenkernel/intern/context.c52
-rw-r--r--source/blender/blenkernel/intern/curve.c27
-rw-r--r--source/blender/blenkernel/intern/displist.c29
-rw-r--r--source/blender/blenkernel/intern/editmesh.c10
-rw-r--r--source/blender/blenkernel/intern/effect.c2
-rw-r--r--source/blender/blenkernel/intern/image.c24
-rw-r--r--source/blender/blenkernel/intern/library.c97
-rw-r--r--source/blender/blenkernel/intern/library_query.c2
-rw-r--r--source/blender/blenkernel/intern/library_remap.c12
-rw-r--r--source/blender/blenkernel/intern/mask.c17
-rw-r--r--source/blender/blenkernel/intern/mask_evaluate.c20
-rw-r--r--source/blender/blenkernel/intern/material.c2
-rw-r--r--source/blender/blenkernel/intern/mesh_convert.c79
-rw-r--r--source/blender/blenkernel/intern/mesh_evaluate.c8
-rw-r--r--source/blender/blenkernel/intern/modifier.c4
-rw-r--r--source/blender/blenkernel/intern/object.c6
-rw-r--r--source/blender/blenkernel/intern/object_update.c2
-rw-r--r--source/blender/blenkernel/intern/paint.c5
-rw-r--r--source/blender/blenkernel/intern/particle.c7
-rw-r--r--source/blender/blenkernel/intern/particle_system.c10
-rw-r--r--source/blender/blenkernel/intern/scene.c2
-rw-r--r--source/blender/blenkernel/intern/screen.c2
-rw-r--r--source/blender/blenkernel/intern/seqcache.c56
-rw-r--r--source/blender/blenkernel/intern/sequencer.c66
-rw-r--r--source/blender/blenkernel/intern/studiolight.c81
-rw-r--r--source/blender/blenkernel/intern/undo_system.c6
-rw-r--r--source/blender/blenlib/BLI_buffer.h2
-rw-r--r--source/blender/blenlib/BLI_callbacks.h1
-rw-r--r--source/blender/blenlib/BLI_memblock.h13
-rw-r--r--source/blender/blenlib/BLI_rect.h4
-rw-r--r--source/blender/blenlib/intern/BLI_memarena.c5
-rw-r--r--source/blender/blenlib/intern/BLI_memblock.c92
-rw-r--r--source/blender/blenlib/intern/BLI_memiter.c9
-rw-r--r--source/blender/blenlib/intern/path_util.c5
-rw-r--r--source/blender/blenlib/intern/rct.c19
-rw-r--r--source/blender/blenlib/intern/system.c5
-rw-r--r--source/blender/blenlib/intern/task.c29
-rw-r--r--source/blender/blenloader/intern/readfile.c47
-rw-r--r--source/blender/blenloader/intern/versioning_260.c1
-rw-r--r--source/blender/blenloader/intern/versioning_280.c73
-rw-r--r--source/blender/blenloader/intern/versioning_cycles.c2
-rw-r--r--source/blender/blenloader/intern/versioning_defaults.c56
-rw-r--r--source/blender/blenloader/intern/versioning_userdef.c10
-rw-r--r--source/blender/bmesh/intern/bmesh_operators.h7
-rw-r--r--source/blender/bmesh/tools/bmesh_bevel.c24
-rw-r--r--source/blender/collada/AnimationClipExporter.h4
-rw-r--r--source/blender/collada/AnimationExporter.cpp105
-rw-r--r--source/blender/collada/AnimationExporter.h32
-rw-r--r--source/blender/collada/ArmatureExporter.cpp116
-rw-r--r--source/blender/collada/ArmatureExporter.h10
-rw-r--r--source/blender/collada/BCAnimationSampler.cpp22
-rw-r--r--source/blender/collada/BCAnimationSampler.h10
-rw-r--r--source/blender/collada/BCSampleData.cpp108
-rw-r--r--source/blender/collada/BCSampleData.h41
-rw-r--r--source/blender/collada/BlenderContext.cpp83
-rw-r--r--source/blender/collada/BlenderContext.h92
-rw-r--r--source/blender/collada/CameraExporter.cpp5
-rw-r--r--source/blender/collada/CameraExporter.h4
-rw-r--r--source/blender/collada/ControllerExporter.cpp44
-rw-r--r--source/blender/collada/ControllerExporter.h9
-rw-r--r--source/blender/collada/DocumentExporter.cpp21
-rw-r--r--source/blender/collada/DocumentExporter.h4
-rw-r--r--source/blender/collada/DocumentImporter.cpp1
-rw-r--r--source/blender/collada/EffectExporter.cpp5
-rw-r--r--source/blender/collada/EffectExporter.h4
-rw-r--r--source/blender/collada/ExportSettings.h207
-rw-r--r--source/blender/collada/GeometryExporter.cpp39
-rw-r--r--source/blender/collada/GeometryExporter.h6
-rw-r--r--source/blender/collada/ImageExporter.cpp6
-rw-r--r--source/blender/collada/ImageExporter.h4
-rw-r--r--source/blender/collada/LightExporter.cpp4
-rw-r--r--source/blender/collada/LightExporter.h4
-rw-r--r--source/blender/collada/MaterialExporter.cpp6
-rw-r--r--source/blender/collada/MaterialExporter.h4
-rw-r--r--source/blender/collada/SceneExporter.cpp47
-rw-r--r--source/blender/collada/SceneExporter.h9
-rw-r--r--source/blender/collada/TransformWriter.cpp93
-rw-r--r--source/blender/collada/TransformWriter.h16
-rw-r--r--source/blender/collada/collada_utils.cpp196
-rw-r--r--source/blender/collada/collada_utils.h65
-rw-r--r--source/blender/compositor/operations/COM_ScaleOperation.cpp8
-rw-r--r--source/blender/depsgraph/CMakeLists.txt2
-rw-r--r--source/blender/depsgraph/DEG_depsgraph_build.h11
-rw-r--r--source/blender/depsgraph/DEG_depsgraph_query.h3
-rw-r--r--source/blender/depsgraph/intern/builder/deg_builder_map.cc39
-rw-r--r--source/blender/depsgraph/intern/builder/deg_builder_map.h47
-rw-r--r--source/blender/depsgraph/intern/builder/deg_builder_nodes.cc40
-rw-r--r--source/blender/depsgraph/intern/builder/deg_builder_nodes.h6
-rw-r--r--source/blender/depsgraph/intern/builder/deg_builder_nodes_scene.cc63
-rw-r--r--source/blender/depsgraph/intern/builder/deg_builder_nodes_view_layer.cc6
-rw-r--r--source/blender/depsgraph/intern/builder/deg_builder_relations.cc30
-rw-r--r--source/blender/depsgraph/intern/builder/deg_builder_relations.h6
-rw-r--r--source/blender/depsgraph/intern/builder/deg_builder_relations_scene.cc62
-rw-r--r--source/blender/depsgraph/intern/builder/deg_builder_relations_view_layer.cc12
-rw-r--r--source/blender/depsgraph/intern/depsgraph.cc3
-rw-r--r--source/blender/depsgraph/intern/depsgraph.h6
-rw-r--r--source/blender/depsgraph/intern/depsgraph_build.cc86
-rw-r--r--source/blender/depsgraph/intern/depsgraph_tag.cc19
-rw-r--r--source/blender/depsgraph/intern/eval/deg_eval_copy_on_write.cc57
-rw-r--r--source/blender/depsgraph/intern/eval/deg_eval_flush.cc4
-rw-r--r--source/blender/draw/engines/basic/basic_engine.c9
-rw-r--r--source/blender/draw/engines/eevee/eevee_data.c1
-rw-r--r--source/blender/draw/engines/eevee/eevee_depth_of_field.c9
-rw-r--r--source/blender/draw/engines/eevee/eevee_effects.c43
-rw-r--r--source/blender/draw/engines/eevee/eevee_engine.c46
-rw-r--r--source/blender/draw/engines/eevee/eevee_lightcache.c15
-rw-r--r--source/blender/draw/engines/eevee/eevee_lightprobes.c168
-rw-r--r--source/blender/draw/engines/eevee/eevee_lights.c110
-rw-r--r--source/blender/draw/engines/eevee/eevee_lookdev.c30
-rw-r--r--source/blender/draw/engines/eevee/eevee_materials.c25
-rw-r--r--source/blender/draw/engines/eevee/eevee_motion_blur.c2
-rw-r--r--source/blender/draw/engines/eevee/eevee_private.h36
-rw-r--r--source/blender/draw/engines/eevee/eevee_render.c66
-rw-r--r--source/blender/draw/engines/eevee/eevee_screen_raytrace.c2
-rw-r--r--source/blender/draw/engines/eevee/eevee_shaders.c15
-rw-r--r--source/blender/draw/engines/eevee/eevee_temporal_sampling.c54
-rw-r--r--source/blender/draw/engines/eevee/eevee_volumes.c8
-rw-r--r--source/blender/draw/engines/eevee/shaders/default_world_frag.glsl3
-rw-r--r--source/blender/draw/engines/eevee/shaders/lit_surface_vert.glsl9
-rw-r--r--source/blender/draw/engines/eevee/shaders/prepass_vert.glsl10
-rw-r--r--source/blender/draw/engines/external/external_engine.c17
-rw-r--r--source/blender/draw/engines/gpencil/gpencil_engine.h4
-rw-r--r--source/blender/draw/engines/gpencil/gpencil_render.c39
-rw-r--r--source/blender/draw/engines/gpencil/gpencil_shader_fx.c13
-rw-r--r--source/blender/draw/engines/workbench/shaders/workbench_effect_fxaa_frag.glsl3
-rw-r--r--source/blender/draw/engines/workbench/shaders/workbench_volume_frag.glsl4
-rw-r--r--source/blender/draw/engines/workbench/workbench_data.c10
-rw-r--r--source/blender/draw/engines/workbench/workbench_deferred.c2
-rw-r--r--source/blender/draw/engines/workbench/workbench_effect_aa.c1
-rw-r--r--source/blender/draw/engines/workbench/workbench_effect_dof.c10
-rw-r--r--source/blender/draw/engines/workbench/workbench_effect_taa.c54
-rw-r--r--source/blender/draw/engines/workbench/workbench_forward.c2
-rw-r--r--source/blender/draw/engines/workbench/workbench_materials.c3
-rw-r--r--source/blender/draw/engines/workbench/workbench_private.h16
-rw-r--r--source/blender/draw/engines/workbench/workbench_render.c21
-rw-r--r--source/blender/draw/engines/workbench/workbench_studiolight.c9
-rw-r--r--source/blender/draw/engines/workbench/workbench_volume.c2
-rw-r--r--source/blender/draw/intern/DRW_render.h115
-rw-r--r--source/blender/draw/intern/draw_common.c75
-rw-r--r--source/blender/draw/intern/draw_common.h5
-rw-r--r--source/blender/draw/intern/draw_instance_data.c6
-rw-r--r--source/blender/draw/intern/draw_manager.c187
-rw-r--r--source/blender/draw/intern/draw_manager.h96
-rw-r--r--source/blender/draw/intern/draw_manager_data.c536
-rw-r--r--source/blender/draw/intern/draw_manager_exec.c702
-rw-r--r--source/blender/draw/modes/edit_curve_mode.c14
-rw-r--r--source/blender/draw/modes/edit_lattice_mode.c8
-rw-r--r--source/blender/draw/modes/edit_mesh_mode.c450
-rw-r--r--source/blender/draw/modes/edit_metaball_mode.c15
-rw-r--r--source/blender/draw/modes/object_mode.c85
-rw-r--r--source/blender/draw/modes/overlay_mode.c18
-rw-r--r--source/blender/draw/modes/paint_texture_mode.c52
-rw-r--r--source/blender/draw/modes/paint_vertex_mode.c47
-rw-r--r--source/blender/draw/modes/shaders/common_view_lib.glsl21
-rw-r--r--source/blender/draw/modes/shaders/edit_curve_overlay_handle_vert.glsl2
-rw-r--r--source/blender/draw/modes/shaders/edit_curve_overlay_loosevert_vert.glsl2
-rw-r--r--source/blender/draw/modes/shaders/edit_curve_overlay_normals_vert.glsl2
-rw-r--r--source/blender/draw/modes/shaders/edit_lattice_overlay_loosevert_vert.glsl2
-rw-r--r--source/blender/draw/modes/shaders/edit_mesh_overlay_common_lib.glsl19
-rw-r--r--source/blender/draw/modes/shaders/edit_mesh_overlay_facefill_vert.glsl2
-rw-r--r--source/blender/draw/modes/shaders/edit_mesh_overlay_mesh_analysis_vert.glsl2
-rw-r--r--source/blender/draw/modes/shaders/edit_mesh_overlay_vert.glsl2
-rw-r--r--source/blender/draw/modes/shaders/edit_normals_vert.glsl2
-rw-r--r--source/blender/editors/animation/anim_markers.c2
-rw-r--r--source/blender/editors/animation/time_scrub_ui.c46
-rw-r--r--source/blender/editors/curve/editcurve.c406
-rw-r--r--source/blender/editors/curve/editfont.c4
-rw-r--r--source/blender/editors/datafiles/CMakeLists.txt4
-rw-r--r--source/blender/editors/gpencil/gpencil_fill.c3
-rw-r--r--source/blender/editors/include/ED_anim_api.h4
-rw-r--r--source/blender/editors/include/ED_mask.h4
-rw-r--r--source/blender/editors/include/ED_mesh.h24
-rw-r--r--source/blender/editors/include/ED_select_buffer_utils.h43
-rw-r--r--source/blender/editors/include/ED_time_scrub_ui.h22
-rw-r--r--source/blender/editors/include/ED_view3d.h16
-rw-r--r--source/blender/editors/include/UI_icons.h10
-rw-r--r--source/blender/editors/include/UI_interface.h35
-rw-r--r--source/blender/editors/include/UI_resources.h2
-rw-r--r--source/blender/editors/include/UI_view2d.h2
-rw-r--r--source/blender/editors/interface/interface.c19
-rw-r--r--source/blender/editors/interface/interface_context_menu.c30
-rw-r--r--source/blender/editors/interface/interface_eyedropper_datablock.c2
-rw-r--r--source/blender/editors/interface/interface_handlers.c27
-rw-r--r--source/blender/editors/interface/interface_icons.c6
-rw-r--r--source/blender/editors/interface/interface_intern.h1
-rw-r--r--source/blender/editors/interface/interface_layout.c147
-rw-r--r--source/blender/editors/interface/interface_panel.c82
-rw-r--r--source/blender/editors/interface/interface_region_tooltip.c3
-rw-r--r--source/blender/editors/interface/interface_templates.c10
-rw-r--r--source/blender/editors/interface/interface_widgets.c12
-rw-r--r--source/blender/editors/interface/resources.c4
-rw-r--r--source/blender/editors/interface/view2d.c2
-rw-r--r--source/blender/editors/interface/view2d_draw.c10
-rw-r--r--source/blender/editors/io/io_cache.c2
-rw-r--r--source/blender/editors/io/io_collada.c170
-rw-r--r--source/blender/editors/mask/mask_add.c66
-rw-r--r--source/blender/editors/mask/mask_draw.c10
-rw-r--r--source/blender/editors/mask/mask_ops.c111
-rw-r--r--source/blender/editors/mask/mask_select.c12
-rw-r--r--source/blender/editors/mesh/editface.c68
-rw-r--r--source/blender/editors/mesh/editmesh_bisect.c6
-rw-r--r--source/blender/editors/mesh/editmesh_extrude_spin_gizmo.c3
-rw-r--r--source/blender/editors/mesh/editmesh_knife.c5
-rw-r--r--source/blender/editors/mesh/editmesh_path.c83
-rw-r--r--source/blender/editors/mesh/editmesh_select.c273
-rw-r--r--source/blender/editors/mesh/editmesh_tools.c23
-rw-r--r--source/blender/editors/mesh/meshtools.c9
-rw-r--r--source/blender/editors/object/object_add.c36
-rw-r--r--source/blender/editors/object/object_bake_api.c8
-rw-r--r--source/blender/editors/object/object_modifier.c2
-rw-r--r--source/blender/editors/object/object_relations.c2
-rw-r--r--source/blender/editors/object/object_transform.c5
-rw-r--r--source/blender/editors/render/render_opengl.c12
-rw-r--r--source/blender/editors/render/render_shading.c6
-rw-r--r--source/blender/editors/screen/area.c8
-rw-r--r--source/blender/editors/screen/screen_context.c59
-rw-r--r--source/blender/editors/screen/screen_edit.c6
-rw-r--r--source/blender/editors/screen/screen_user_menu.c40
-rw-r--r--source/blender/editors/sculpt_paint/paint_image_proj.c1
-rw-r--r--source/blender/editors/sculpt_paint/paint_utils.c3
-rw-r--r--source/blender/editors/sculpt_paint/paint_vertex_weight_ops.c16
-rw-r--r--source/blender/editors/sound/sound_ops.c2
-rw-r--r--source/blender/editors/space_action/action_data.c6
-rw-r--r--source/blender/editors/space_action/space_action.c4
-rw-r--r--source/blender/editors/space_clip/clip_buttons.c3
-rw-r--r--source/blender/editors/space_clip/clip_intern.h2
-rw-r--r--source/blender/editors/space_clip/clip_ops.c2
-rw-r--r--source/blender/editors/space_clip/space_clip.c17
-rw-r--r--source/blender/editors/space_clip/tracking_ops.c3
-rw-r--r--source/blender/editors/space_graph/graph_edit.c11
-rw-r--r--source/blender/editors/space_graph/space_graph.c6
-rw-r--r--source/blender/editors/space_image/image_buttons.c502
-rw-r--r--source/blender/editors/space_image/image_ops.c7
-rw-r--r--source/blender/editors/space_image/space_image.c3
-rw-r--r--source/blender/editors/space_nla/space_nla.c4
-rw-r--r--source/blender/editors/space_node/drawnode.c5
-rw-r--r--source/blender/editors/space_node/node_add.c2
-rw-r--r--source/blender/editors/space_node/node_select.c12
-rw-r--r--source/blender/editors/space_outliner/outliner_draw.c6
-rw-r--r--source/blender/editors/space_outliner/outliner_edit.c5
-rw-r--r--source/blender/editors/space_outliner/outliner_select.c30
-rw-r--r--source/blender/editors/space_outliner/outliner_tree.c2
-rw-r--r--source/blender/editors/space_outliner/space_outliner.c10
-rw-r--r--source/blender/editors/space_sequencer/sequencer_add.c8
-rw-r--r--source/blender/editors/space_sequencer/sequencer_draw.c10
-rw-r--r--source/blender/editors/space_sequencer/sequencer_edit.c8
-rw-r--r--source/blender/editors/space_sequencer/sequencer_modifier.c8
-rw-r--r--source/blender/editors/space_sequencer/sequencer_view.c2
-rw-r--r--source/blender/editors/space_sequencer/space_sequencer.c1
-rw-r--r--source/blender/editors/space_text/text_ops.c4
-rw-r--r--source/blender/editors/space_userpref/userpref_ops.c2
-rw-r--r--source/blender/editors/space_view3d/view3d_draw.c167
-rw-r--r--source/blender/editors/space_view3d/view3d_draw_legacy.c157
-rw-r--r--source/blender/editors/space_view3d/view3d_gizmo_navigate.c5
-rw-r--r--source/blender/editors/space_view3d/view3d_select.c583
-rw-r--r--source/blender/editors/space_view3d/view3d_view.c2
-rw-r--r--source/blender/editors/transform/transform.c1
-rw-r--r--source/blender/editors/transform/transform_generics.c7
-rw-r--r--source/blender/editors/transform/transform_gizmo_3d.c30
-rw-r--r--source/blender/editors/transform/transform_gizmo_extrude_3d.c3
-rw-r--r--source/blender/editors/transform/transform_ops.c58
-rw-r--r--source/blender/editors/undo/ed_undo.c2
-rw-r--r--source/blender/editors/util/CMakeLists.txt2
-rw-r--r--source/blender/editors/util/select_buffer_utils.c303
-rw-r--r--source/blender/editors/uvedit/uvedit_draw.c5
-rw-r--r--source/blender/freestyle/intern/blender_interface/BlenderFileLoader.cpp2
-rw-r--r--source/blender/freestyle/intern/blender_interface/BlenderStrokeRenderer.cpp1
-rw-r--r--source/blender/gpu/GPU_batch.h10
-rw-r--r--source/blender/gpu/GPU_shader_interface.h6
-rw-r--r--source/blender/gpu/GPU_viewport.h2
-rw-r--r--source/blender/gpu/intern/gpu_batch.c133
-rw-r--r--source/blender/gpu/intern/gpu_draw.c2
-rw-r--r--source/blender/gpu/intern/gpu_material.c7
-rw-r--r--source/blender/gpu/intern/gpu_select.c12
-rw-r--r--source/blender/gpu/intern/gpu_shader_interface.c2
-rw-r--r--source/blender/gpu/intern/gpu_viewport.c6
-rw-r--r--source/blender/gpu/shaders/gpu_shader_cfg_world_clip_lib.glsl27
-rw-r--r--source/blender/imbuf/IMB_imbuf.h9
-rw-r--r--source/blender/imbuf/IMB_imbuf_types.h8
-rw-r--r--source/blender/imbuf/intern/colormanagement.c61
-rw-r--r--source/blender/imbuf/intern/divers.c137
-rw-r--r--source/blender/imbuf/intern/oiio/openimageio_api.cpp1
-rw-r--r--source/blender/imbuf/intern/readimage.c18
-rw-r--r--source/blender/makesdna/DNA_genfile.h11
-rw-r--r--source/blender/makesdna/DNA_image_types.h4
-rw-r--r--source/blender/makesdna/DNA_node_types.h4
-rw-r--r--source/blender/makesdna/DNA_object_types.h2
-rw-r--r--source/blender/makesdna/DNA_scene_types.h20
-rw-r--r--source/blender/makesdna/DNA_sdna_types.h13
-rw-r--r--source/blender/makesdna/DNA_userdef_types.h2
-rw-r--r--source/blender/makesdna/DNA_view3d_types.h5
-rw-r--r--source/blender/makesdna/intern/dna_genfile.c273
-rw-r--r--source/blender/makesdna/intern/dna_rename_defs.h1
-rw-r--r--source/blender/makesdna/intern/dna_utils.c2
-rw-r--r--source/blender/makesdna/intern/makesdna.c123
-rw-r--r--source/blender/makesrna/RNA_access.h11
-rw-r--r--source/blender/makesrna/RNA_define.h1
-rw-r--r--source/blender/makesrna/intern/makesrna.c6
-rw-r--r--source/blender/makesrna/intern/rna_ID.c37
-rw-r--r--source/blender/makesrna/intern/rna_access.c12
-rw-r--r--source/blender/makesrna/intern/rna_action.c8
-rw-r--r--source/blender/makesrna/intern/rna_animation.c18
-rw-r--r--source/blender/makesrna/intern/rna_armature.c42
-rw-r--r--source/blender/makesrna/intern/rna_cloth.c6
-rw-r--r--source/blender/makesrna/intern/rna_color.c9
-rw-r--r--source/blender/makesrna/intern/rna_constraint.c24
-rw-r--r--source/blender/makesrna/intern/rna_context.c19
-rw-r--r--source/blender/makesrna/intern/rna_curve.c18
-rw-r--r--source/blender/makesrna/intern/rna_define.c14
-rw-r--r--source/blender/makesrna/intern/rna_depsgraph.c16
-rw-r--r--source/blender/makesrna/intern/rna_fcurve.c127
-rw-r--r--source/blender/makesrna/intern/rna_gpencil.c20
-rw-r--r--source/blender/makesrna/intern/rna_gpencil_modifier.c8
-rw-r--r--source/blender/makesrna/intern/rna_image.c44
-rw-r--r--source/blender/makesrna/intern/rna_internal.h20
-rw-r--r--source/blender/makesrna/intern/rna_internal_types.h6
-rw-r--r--source/blender/makesrna/intern/rna_key.c6
-rw-r--r--source/blender/makesrna/intern/rna_layer.c13
-rw-r--r--source/blender/makesrna/intern/rna_linestyle.c6
-rw-r--r--source/blender/makesrna/intern/rna_main_api.c21
-rw-r--r--source/blender/makesrna/intern/rna_mask.c24
-rw-r--r--source/blender/makesrna/intern/rna_material.c12
-rw-r--r--source/blender/makesrna/intern/rna_mesh_utils.h2
-rw-r--r--source/blender/makesrna/intern/rna_modifier.c20
-rw-r--r--source/blender/makesrna/intern/rna_nodetree.c30
-rw-r--r--source/blender/makesrna/intern/rna_object.c32
-rw-r--r--source/blender/makesrna/intern/rna_object_api.c28
-rw-r--r--source/blender/makesrna/intern/rna_palette.c6
-rw-r--r--source/blender/makesrna/intern/rna_particle.c17
-rw-r--r--source/blender/makesrna/intern/rna_pose.c30
-rw-r--r--source/blender/makesrna/intern/rna_rna.c2
-rw-r--r--source/blender/makesrna/intern/rna_scene.c60
-rw-r--r--source/blender/makesrna/intern/rna_sequencer.c284
-rw-r--r--source/blender/makesrna/intern/rna_shader_fx.c2
-rw-r--r--source/blender/makesrna/intern/rna_space.c64
-rw-r--r--source/blender/makesrna/intern/rna_space_api.c2
-rw-r--r--source/blender/makesrna/intern/rna_tracking.c18
-rw-r--r--source/blender/makesrna/intern/rna_ui.c34
-rw-r--r--source/blender/makesrna/intern/rna_ui_api.c26
-rw-r--r--source/blender/makesrna/intern/rna_userdef.c97
-rw-r--r--source/blender/makesrna/intern/rna_wm.c39
-rw-r--r--source/blender/makesrna/intern/rna_wm_gizmo.c6
-rw-r--r--source/blender/modifiers/intern/MOD_weighted_normal.c2
-rw-r--r--source/blender/nodes/shader/nodes/node_shader_bsdf_principled.c8
-rw-r--r--source/blender/nodes/shader/nodes/node_shader_tex_image.c6
-rw-r--r--source/blender/physics/intern/implicit_blender.c7
-rw-r--r--source/blender/python/intern/bpy_app_handlers.c1
-rw-r--r--source/blender/python/intern/bpy_rna.c2
-rw-r--r--source/blender/python/mathutils/mathutils_Matrix.c29
-rw-r--r--source/blender/render/intern/include/render_types.h8
-rw-r--r--source/blender/render/intern/source/external_engine.c25
-rw-r--r--source/blender/render/intern/source/imagetexture.c6
-rw-r--r--source/blender/render/intern/source/initrender.c11
-rw-r--r--source/blender/render/intern/source/pipeline.c60
-rw-r--r--source/blender/render/intern/source/render_result.c6
-rw-r--r--source/blender/windowmanager/CMakeLists.txt1
-rw-r--r--source/blender/windowmanager/WM_api.h8
-rw-r--r--source/blender/windowmanager/WM_keymap.h2
-rw-r--r--source/blender/windowmanager/WM_types.h16
-rw-r--r--source/blender/windowmanager/gizmo/WM_gizmo_api.h19
-rw-r--r--source/blender/windowmanager/gizmo/WM_gizmo_types.h9
-rw-r--r--source/blender/windowmanager/gizmo/intern/wm_gizmo_group.c252
-rw-r--r--source/blender/windowmanager/gizmo/intern/wm_gizmo_group_type.c4
-rw-r--r--source/blender/windowmanager/gizmo/intern/wm_gizmo_intern.h15
-rw-r--r--source/blender/windowmanager/gizmo/intern/wm_gizmo_map.c95
-rw-r--r--source/blender/windowmanager/gizmo/wm_gizmo_fn.h3
-rw-r--r--source/blender/windowmanager/intern/wm_draw.c11
-rw-r--r--source/blender/windowmanager/intern/wm_event_system.c313
-rw-r--r--source/blender/windowmanager/intern/wm_files.c172
-rw-r--r--source/blender/windowmanager/intern/wm_files_link.c10
-rw-r--r--source/blender/windowmanager/intern/wm_gesture.c6
-rw-r--r--source/blender/windowmanager/intern/wm_keymap_utils.c40
-rw-r--r--source/blender/windowmanager/intern/wm_operators.c9
-rw-r--r--source/blender/windowmanager/intern/wm_toolsystem.c2
-rw-r--r--source/blender/windowmanager/intern/wm_utils.c71
-rw-r--r--source/blender/windowmanager/intern/wm_window.c2
-rw-r--r--source/blender/windowmanager/wm_draw.h2
-rw-r--r--source/blender/windowmanager/wm_files.h11
399 files changed, 8477 insertions, 5650 deletions
diff --git a/source/blender/blenkernel/BKE_appdir.h b/source/blender/blenkernel/BKE_appdir.h
index e956aeb769a..e55cb69a5c6 100644
--- a/source/blender/blenkernel/BKE_appdir.h
+++ b/source/blender/blenkernel/BKE_appdir.h
@@ -45,6 +45,9 @@ void BKE_appdir_program_path_init(const char *argv0);
const char *BKE_appdir_program_path(void);
const char *BKE_appdir_program_dir(void);
+/* Return OS fonts directory. */
+bool BKE_appdir_font_folder_default(char *dir);
+
/* find python executable */
bool BKE_appdir_program_python_search(char *fullpath,
const size_t fullpath_len,
diff --git a/source/blender/blenkernel/BKE_blender_version.h b/source/blender/blenkernel/BKE_blender_version.h
index 5d659d63e27..7461a1b1051 100644
--- a/source/blender/blenkernel/BKE_blender_version.h
+++ b/source/blender/blenkernel/BKE_blender_version.h
@@ -27,7 +27,7 @@
* \note Use #STRINGIFY() rather than defining with quotes.
*/
#define BLENDER_VERSION 280
-#define BLENDER_SUBVERSION 69
+#define BLENDER_SUBVERSION 72
/** Several breakages with 280, e.g. collections vs layers. */
#define BLENDER_MINVERSION 280
#define BLENDER_MINSUBVERSION 0
diff --git a/source/blender/blenkernel/BKE_collection.h b/source/blender/blenkernel/BKE_collection.h
index 0e093bb086b..502c949be9a 100644
--- a/source/blender/blenkernel/BKE_collection.h
+++ b/source/blender/blenkernel/BKE_collection.h
@@ -163,6 +163,9 @@ bool BKE_collection_find_cycle(struct Collection *new_ancestor, struct Collectio
bool BKE_collection_has_collection(struct Collection *parent, struct Collection *collection);
+void BKE_collection_parent_relations_rebuild(struct Collection *collection);
+void BKE_main_collections_parent_relations_rebuild(struct Main *bmain);
+
/* Iteration callbacks. */
typedef void (*BKE_scene_objects_Cb)(struct Object *ob, void *data);
diff --git a/source/blender/blenkernel/BKE_curve.h b/source/blender/blenkernel/BKE_curve.h
index 4356d39be36..df1e7a7baea 100644
--- a/source/blender/blenkernel/BKE_curve.h
+++ b/source/blender/blenkernel/BKE_curve.h
@@ -138,12 +138,7 @@ float *BKE_curve_surf_make_orco(struct Object *ob);
void BKE_curve_bevelList_free(struct ListBase *bev);
void BKE_curve_bevelList_make(struct Object *ob, struct ListBase *nurbs, bool for_render);
-void BKE_curve_bevel_make(struct Depsgraph *depsgraph,
- struct Scene *scene,
- struct Object *ob,
- struct ListBase *disp,
- const bool for_render,
- struct LinkNode *ob_cyclic_list);
+void BKE_curve_bevel_make(struct Object *ob, struct ListBase *disp);
void BKE_curve_forward_diff_bezier(
float q0, float q1, float q2, float q3, float *p, int it, int stride);
diff --git a/source/blender/blenkernel/BKE_displist.h b/source/blender/blenkernel/BKE_displist.h
index db57df42d02..c57639a8193 100644
--- a/source/blender/blenkernel/BKE_displist.h
+++ b/source/blender/blenkernel/BKE_displist.h
@@ -90,15 +90,13 @@ void BKE_displist_make_curveTypes(struct Depsgraph *depsgraph,
struct Scene *scene,
struct Object *ob,
const bool for_render,
- const bool for_orco,
- struct LinkNode *ob_cyclic_list);
+ const bool for_orco);
void BKE_displist_make_curveTypes_forRender(struct Depsgraph *depsgraph,
struct Scene *scene,
struct Object *ob,
struct ListBase *dispbase,
struct Mesh **r_final,
- const bool for_orco,
- struct LinkNode *ob_cyclic_list);
+ const bool for_orco);
void BKE_displist_make_mball(struct Depsgraph *depsgraph, struct Scene *scene, struct Object *ob);
void BKE_displist_make_mball_forRender(struct Depsgraph *depsgraph,
struct Scene *scene,
diff --git a/source/blender/blenkernel/BKE_editmesh.h b/source/blender/blenkernel/BKE_editmesh.h
index 91a558a9ee2..b7280c702d2 100644
--- a/source/blender/blenkernel/BKE_editmesh.h
+++ b/source/blender/blenkernel/BKE_editmesh.h
@@ -90,6 +90,7 @@ void BKE_editmesh_color_free(BMEditMesh *em);
void BKE_editmesh_color_ensure(BMEditMesh *em, const char htype);
float (*BKE_editmesh_vertexCos_get_orco(BMEditMesh *em, int *r_numVerts))[3];
void BKE_editmesh_lnorspace_update(BMEditMesh *em);
+void BKE_editmesh_ensure_autosmooth(BMEditMesh *em);
/* editderivedmesh.c */
/* should really be defined in editmesh.c, but they use 'EditDerivedBMesh' */
diff --git a/source/blender/blenkernel/BKE_global.h b/source/blender/blenkernel/BKE_global.h
index 387e7f2182b..9fe8fc3880f 100644
--- a/source/blender/blenkernel/BKE_global.h
+++ b/source/blender/blenkernel/BKE_global.h
@@ -107,7 +107,6 @@ typedef struct Global {
/** #Global.f */
enum {
G_FLAG_RENDER_VIEWPORT = (1 << 0),
- G_FLAG_BACKBUFSEL = (1 << 1),
G_FLAG_PICKSEL = (1 << 2),
/** Support simulating events (for testing). */
G_FLAG_EVENT_SIMULATE = (1 << 3),
diff --git a/source/blender/blenkernel/BKE_library.h b/source/blender/blenkernel/BKE_library.h
index 54b9fdac5b4..818fbce4f9a 100644
--- a/source/blender/blenkernel/BKE_library.h
+++ b/source/blender/blenkernel/BKE_library.h
@@ -218,6 +218,8 @@ void BKE_main_id_flag_all(struct Main *bmain, const int flag, const bool value);
void BKE_main_id_clear_newpoins(struct Main *bmain);
+void BLE_main_id_refcount_recompute(struct Main *bmain, const bool do_linked_only);
+
void BKE_main_lib_objects_recalc_all(struct Main *bmain);
/* Only for repairing files via versioning, avoid for general use. */
diff --git a/source/blender/blenkernel/BKE_mask.h b/source/blender/blenkernel/BKE_mask.h
index 042463dc7b0..bfdeadc7f60 100644
--- a/source/blender/blenkernel/BKE_mask.h
+++ b/source/blender/blenkernel/BKE_mask.h
@@ -171,8 +171,6 @@ void BKE_mask_coord_to_image(struct Image *image,
/* parenting */
-void BKE_mask_update_display(struct Mask *mask, float ctime);
-
void BKE_mask_evaluate_all_masks(struct Main *bmain, float ctime, const bool do_newframe);
void BKE_mask_evaluate(struct Mask *mask, const float ctime, const bool do_newframe);
void BKE_mask_layer_evaluate(struct MaskLayer *masklay, const float ctime, const bool do_newframe);
diff --git a/source/blender/blenkernel/BKE_mesh.h b/source/blender/blenkernel/BKE_mesh.h
index c410946f438..54fbda1fa31 100644
--- a/source/blender/blenkernel/BKE_mesh.h
+++ b/source/blender/blenkernel/BKE_mesh.h
@@ -209,11 +209,22 @@ float (*BKE_mesh_vertexCos_get(const struct Mesh *me, int *r_numVerts))[3];
void BKE_mesh_split_faces(struct Mesh *mesh, bool free_loop_normals);
/* Create new mesh from the given object at its current state.
- * The owner of this mesh is unknown, it is up to the caller to decide. */
-struct Mesh *BKE_mesh_new_from_object(struct Object *object);
+ * The owner of this mesh is unknown, it is up to the caller to decide.
+ *
+ * If preserve_all_data_layers is truth then the modifier stack is re-evaluated to ensure it
+ * preserves all possible custom data layers.
+ *
+ * NOTE: Dependency graph argument is required when preserve_all_data_layers is truth, and is
+ * ignored otherwise. */
+struct Mesh *BKE_mesh_new_from_object(struct Depsgraph *depsgraph,
+ struct Object *object,
+ bool preserve_all_data_layers);
/* This is a version of BKE_mesh_new_from_object() which stores mesh in the given main database. */
-struct Mesh *BKE_mesh_new_from_object_to_bmain(struct Main *bmain, struct Object *object);
+struct Mesh *BKE_mesh_new_from_object_to_bmain(struct Main *bmain,
+ struct Depsgraph *depsgraph,
+ struct Object *object,
+ bool preserve_all_data_layers);
struct Mesh *BKE_mesh_create_derived_for_modifier(struct Depsgraph *depsgraph,
struct Scene *scene,
diff --git a/source/blender/blenkernel/BKE_object.h b/source/blender/blenkernel/BKE_object.h
index aa4d9696527..df1ac0e4081 100644
--- a/source/blender/blenkernel/BKE_object.h
+++ b/source/blender/blenkernel/BKE_object.h
@@ -400,8 +400,16 @@ bool BKE_object_empty_image_data_is_visible_in_view3d(const struct Object *ob,
* The result is owned by the object.
*
* The mesh will be freed when object is re-evaluated or is destroyed. It is possible to force to
- * clear memory sued by this mesh by calling BKE_object_to_mesh_clear(). */
-struct Mesh *BKE_object_to_mesh(struct Object *object);
+ * clear memory sued by this mesh by calling BKE_object_to_mesh_clear().
+ *
+ * If preserve_all_data_layers is truth then the modifier stack is re-evaluated to ensure it
+ * preserves all possible custom data layers.
+ *
+ * NOTE: Dependency graph argument is required when preserve_all_data_layers is truth, and is
+ * ignored otherwise. */
+struct Mesh *BKE_object_to_mesh(struct Depsgraph *depsgraph,
+ struct Object *object,
+ bool preserve_all_data_layers);
void BKE_object_to_mesh_clear(struct Object *object);
diff --git a/source/blender/blenkernel/BKE_screen.h b/source/blender/blenkernel/BKE_screen.h
index 93c9c41e482..dcf6d6c3907 100644
--- a/source/blender/blenkernel/BKE_screen.h
+++ b/source/blender/blenkernel/BKE_screen.h
@@ -84,6 +84,9 @@ typedef struct SpaceType {
struct wmNotifier *wmn,
struct Scene *scene);
+ /* called when the mouse moves out of the area */
+ void (*deactivate)(struct ScrArea *sa);
+
/* refresh context, called after filereads, ED_area_tag_refresh() */
void (*refresh)(const struct bContext *C, struct ScrArea *sa);
@@ -205,6 +208,7 @@ typedef struct PanelType {
short region_type;
/* For popovers, 0 for default. */
int ui_units_x;
+ int order;
int flag;
diff --git a/source/blender/blenkernel/BKE_sequencer.h b/source/blender/blenkernel/BKE_sequencer.h
index 170ab657388..807c4a93654 100644
--- a/source/blender/blenkernel/BKE_sequencer.h
+++ b/source/blender/blenkernel/BKE_sequencer.h
@@ -323,7 +323,10 @@ void BKE_sequencer_cache_free_temp_cache(struct Scene *scene, short id, int cfra
void BKE_sequencer_cache_destruct(struct Scene *scene);
void BKE_sequencer_cache_cleanup_all(struct Main *bmain);
void BKE_sequencer_cache_cleanup(struct Scene *scene);
-void BKE_sequencer_cache_cleanup_sequence(struct Scene *scene, struct Sequence *seq);
+void BKE_sequencer_cache_cleanup_sequence(struct Scene *scene,
+ struct Sequence *seq,
+ struct Sequence *seq_changed,
+ int invalidate_types);
void BKE_sequencer_cache_iterate(
struct Scene *scene,
void *userdata,
@@ -391,9 +394,10 @@ struct Sequence *BKE_sequence_dupli_recursive(const struct Scene *scene_src,
int BKE_sequence_swap(struct Sequence *seq_a, struct Sequence *seq_b, const char **error_str);
bool BKE_sequence_check_depend(struct Sequence *seq, struct Sequence *cur);
-void BKE_sequence_invalidate_cache(struct Scene *scene, struct Sequence *seq);
+void BKE_sequence_invalidate_cache_raw(struct Scene *scene, struct Sequence *seq);
+void BKE_sequence_invalidate_cache_preprocessed(struct Scene *scene, struct Sequence *seq);
+void BKE_sequence_invalidate_cache_composite(struct Scene *scene, struct Sequence *seq);
void BKE_sequence_invalidate_dependent(struct Scene *scene, struct Sequence *seq);
-void BKE_sequence_invalidate_cache_for_modifier(struct Scene *scene, struct Sequence *seq);
void BKE_sequencer_update_sound_bounds_all(struct Scene *scene);
void BKE_sequencer_update_sound_bounds(struct Scene *scene, struct Sequence *seq);
diff --git a/source/blender/blenkernel/BKE_studiolight.h b/source/blender/blenkernel/BKE_studiolight.h
index 3586c08547c..d6fff528348 100644
--- a/source/blender/blenkernel/BKE_studiolight.h
+++ b/source/blender/blenkernel/BKE_studiolight.h
@@ -131,6 +131,7 @@ typedef struct StudioLight {
void BKE_studiolight_init(void);
void BKE_studiolight_free(void);
+void BKE_studiolight_default(SolidLight lights[4], float light_ambient[4]);
struct StudioLight *BKE_studiolight_find(const char *name, int flag);
struct StudioLight *BKE_studiolight_findindex(int index, int flag);
struct StudioLight *BKE_studiolight_find_default(int flag);
diff --git a/source/blender/blenkernel/intern/DerivedMesh.c b/source/blender/blenkernel/intern/DerivedMesh.c
index 959435ad486..615a68dc176 100644
--- a/source/blender/blenkernel/intern/DerivedMesh.c
+++ b/source/blender/blenkernel/intern/DerivedMesh.c
@@ -2070,7 +2070,6 @@ static void object_get_datamask(const Depsgraph *depsgraph,
bool *r_need_mapping)
{
ViewLayer *view_layer = DEG_get_evaluated_view_layer(depsgraph);
- Object *actob = view_layer->basact ? DEG_get_original_object(view_layer->basact->object) : NULL;
DEG_get_customdata_mask_for_object(depsgraph, ob, r_mask);
@@ -2078,6 +2077,13 @@ static void object_get_datamask(const Depsgraph *depsgraph,
*r_need_mapping = false;
}
+ /* Must never access original objects when dependency graph is not active: it might be already
+ * freed. */
+ if (!DEG_is_active(depsgraph)) {
+ return;
+ }
+
+ Object *actob = view_layer->basact ? DEG_get_original_object(view_layer->basact->object) : NULL;
if (DEG_get_original_object(ob) == actob) {
bool editing = BKE_paint_select_face_test(actob);
diff --git a/source/blender/blenkernel/intern/anim_sys.c b/source/blender/blenkernel/intern/anim_sys.c
index ab7e59a059b..4a939180fb0 100644
--- a/source/blender/blenkernel/intern/anim_sys.c
+++ b/source/blender/blenkernel/intern/anim_sys.c
@@ -3618,9 +3618,9 @@ static void animsys_calculate_nla(Depsgraph *depsgraph,
* Prepare data necessary to compute correct keyframe values for NLA strips
* with non-Replace mode or influence different from 1.
*
- * \param cache List used to cache contexts for reuse when keying
+ * \param cache: List used to cache contexts for reuse when keying
* multiple channels in one operation.
- * \param ptr RNA pointer to the Object with the animation.
+ * \param ptr: RNA pointer to the Object with the animation.
* \return Keyframing context, or NULL if not necessary.
*/
NlaKeyframingContext *BKE_animsys_get_nla_keyframing_context(struct ListBase *cache,
@@ -3662,12 +3662,12 @@ NlaKeyframingContext *BKE_animsys_get_nla_keyframing_context(struct ListBase *ca
/**
* Apply correction from the NLA context to the values about to be keyframed.
*
- * \param context Context to use (may be NULL).
- * \param prop_ptr Property about to be keyframed.
- * \param[in,out] values Array of property values to adjust.
- * \param count Number of values in the array.
- * \param index Index of the element about to be updated, or -1.
- * \param[out] r_force_all Set to true if all channels must be inserted. May be NULL.
+ * \param context: Context to use (may be NULL).
+ * \param prop_ptr: Property about to be keyframed.
+ * \param[in,out] values: Array of property values to adjust.
+ * \param count: Number of values in the array.
+ * \param index: Index of the element about to be updated, or -1.
+ * \param[out] r_force_all: Set to true if all channels must be inserted. May be NULL.
* \return False if correction fails due to a division by zero,
* or null r_force_all when all channels are required.
*/
diff --git a/source/blender/blenkernel/intern/appdir.c b/source/blender/blenkernel/intern/appdir.c
index c1ea57c5fcc..14a20689db0 100644
--- a/source/blender/blenkernel/intern/appdir.c
+++ b/source/blender/blenkernel/intern/appdir.c
@@ -30,6 +30,7 @@
#include "BLI_listbase.h"
#include "BLI_path_util.h"
#include "BLI_string.h"
+#include "BLI_string_utf8.h"
#include "BKE_blender_version.h"
#include "BKE_appdir.h" /* own include */
@@ -1024,3 +1025,17 @@ void BKE_tempdir_session_purge(void)
BLI_delete(btempdir_session, true, true);
}
}
+
+/* Gets a good default directory for fonts */
+bool BKE_appdir_font_folder_default(char *dir)
+{
+ bool success = false;
+#ifdef WIN32
+ wchar_t wpath[FILE_MAXDIR];
+ success = SHGetSpecialFolderPathW(0, wpath, CSIDL_FONTS, 0);
+ BLI_strncpy_wchar_as_utf8(dir, wpath, FILE_MAXDIR);
+#endif
+ /* TODO: Values for other platforms. */
+ UNUSED_VARS(dir);
+ return success;
+}
diff --git a/source/blender/blenkernel/intern/blendfile.c b/source/blender/blenkernel/intern/blendfile.c
index 570c1b9bd4c..c301588af0c 100644
--- a/source/blender/blenkernel/intern/blendfile.c
+++ b/source/blender/blenkernel/intern/blendfile.c
@@ -359,6 +359,16 @@ static void setup_app_data(bContext *C,
/* TODO(sergey): Can this be also move above? */
RE_FreeAllPersistentData();
}
+
+ if (mode == LOAD_UNDO) {
+ /* In undo/redo case, we do a whole lot of magic tricks to avoid having to re-read linked
+ * datablocks from libraries (since those are not supposed to change). Unfortunately, that
+ * means that we do not reset their user count, however we do increase that one when doing
+ * lib_link on local IDs using linked ones.
+ * There is no real way to predict amount of changes here, so we have to fully redo
+ * refcounting . */
+ BLE_main_id_refcount_recompute(bmain, true);
+ }
}
static void setup_app_blend_file_data(bContext *C,
diff --git a/source/blender/blenkernel/intern/brush.c b/source/blender/blenkernel/intern/brush.c
index e28f1fc566f..78d965564e6 100644
--- a/source/blender/blenkernel/intern/brush.c
+++ b/source/blender/blenkernel/intern/brush.c
@@ -501,9 +501,46 @@ void BKE_brush_gpencil_presets(bContext *C)
brush->gpencil_settings->gradient_s[0] = 1.0f;
brush->gpencil_settings->gradient_s[1] = 1.0f;
+ /* Soft brush */
+ brush = BKE_brush_add_gpencil(bmain, ts, "Draw Soft");
+ deft = brush; /* save default brush */
+ brush->size = 300.0f;
+ brush->gpencil_settings->flag |= (GP_BRUSH_USE_PRESSURE | GP_BRUSH_ENABLE_CURSOR);
+ brush->gpencil_settings->draw_sensitivity = 1.0f;
+
+ brush->gpencil_settings->draw_strength = 0.4f;
+ brush->gpencil_settings->flag |= GP_BRUSH_USE_STENGTH_PRESSURE;
+
+ brush->gpencil_settings->draw_random_press = 0.0f;
+ brush->gpencil_settings->draw_random_strength = 0.0f;
+
+ brush->gpencil_settings->draw_jitter = 0.0f;
+ brush->gpencil_settings->flag |= GP_BRUSH_USE_JITTER_PRESSURE;
+
+ brush->gpencil_settings->draw_angle = 0.0f;
+ brush->gpencil_settings->draw_angle_factor = 0.0f;
+
+ brush->gpencil_settings->input_samples = 10;
+ brush->gpencil_settings->active_smooth = 0.98f;
+ brush->gpencil_settings->draw_smoothfac = 0.1f;
+ brush->gpencil_settings->draw_smoothlvl = 1;
+ brush->gpencil_settings->draw_subdivide = 1;
+ brush->gpencil_settings->thick_smoothfac = 1.0f;
+ brush->gpencil_settings->thick_smoothlvl = 3;
+ brush->gpencil_settings->draw_random_sub = 0.0f;
+ brush->gpencil_settings->icon_id = GP_BRUSH_ICON_MARKER;
+ brush->gpencil_tool = GPAINT_TOOL_DRAW;
+
+ brush->smooth_stroke_radius = SMOOTH_STROKE_RADIUS;
+ brush->smooth_stroke_factor = SMOOTH_STROKE_FACTOR;
+
+ brush->gpencil_settings->gradient_f = 0.211f;
+ brush->gpencil_settings->gradient_s[0] = 1.0f;
+ brush->gpencil_settings->gradient_s[1] = 0.91f;
+
/* Fill brush */
brush = BKE_brush_add_gpencil(bmain, ts, "Fill Area");
- brush->size = 1.0f;
+ brush->size = 20.0f;
brush->gpencil_settings->flag |= GP_BRUSH_ENABLE_CURSOR;
brush->gpencil_settings->draw_sensitivity = 1.0f;
brush->gpencil_settings->fill_leak = 3;
diff --git a/source/blender/blenkernel/intern/camera.c b/source/blender/blenkernel/intern/camera.c
index a17cbb29550..a8f38c3c4ce 100644
--- a/source/blender/blenkernel/intern/camera.c
+++ b/source/blender/blenkernel/intern/camera.c
@@ -66,7 +66,7 @@ void BKE_camera_init(Camera *cam)
cam->flag |= CAM_SHOWPASSEPARTOUT;
cam->passepartalpha = 0.5f;
- cam->dof.aperture_fstop = 5.6f;
+ cam->dof.aperture_fstop = 2.8f;
cam->dof.aperture_ratio = 1.0f;
cam->dof.focus_distance = 10.0f;
diff --git a/source/blender/blenkernel/intern/collection.c b/source/blender/blenkernel/intern/collection.c
index 87f448d8d57..e8d82ade7d3 100644
--- a/source/blender/blenkernel/intern/collection.c
+++ b/source/blender/blenkernel/intern/collection.c
@@ -321,11 +321,11 @@ Collection *BKE_collection_copy(Main *bmain, Collection *parent, Collection *col
* \warning If any 'deep copy' behavior is enabled,
* this functions will clear all \a bmain id.idnew pointers.
*
- * \param do_hierarchy If true, it will recursively make shallow copies of children collections.
- * \param do_objects If true, it will also make duplicates of objects.
- * This one does nothing if \a do_hierarchy is not set.
- * \param do_obdata If true, it will also make deep duplicates of objects,
- * using behavior defined in user settings (U.dupflag).
+ * \param do_hierarchy: If true, it will recursively make shallow copies of children collections.
+ * \param do_objects: If true, it will also make duplicates of objects.
+ * This one does nothing if \a do_hierarchy is not set.
+ * \param do_obdata: If true, it will also make deep duplicates of objects,
+ * using behavior defined in user settings (#U.dupflag).
* This one does nothing if \a do_hierarchy and \a do_objects are not set.
*/
Collection *BKE_collection_duplicate(Main *bmain,
@@ -705,18 +705,27 @@ bool BKE_collection_object_add(Main *bmain, Collection *collection, Object *ob)
}
/**
- * Add object to all scene collections that reference objects is in
- * (used to copy objects)
+ * Add object to all scene collections that reference object is in
+ * (used to copy objects).
*/
void BKE_collection_object_add_from(Main *bmain, Scene *scene, Object *ob_src, Object *ob_dst)
{
+ bool is_instantiated = false;
+
FOREACH_SCENE_COLLECTION_BEGIN (scene, collection) {
- if (BKE_collection_has_object(collection, ob_src)) {
+ if (!ID_IS_LINKED(collection) && BKE_collection_has_object(collection, ob_src)) {
collection_object_add(bmain, collection, ob_dst, 0, true);
+ is_instantiated = true;
}
}
FOREACH_SCENE_COLLECTION_END;
+ if (!is_instantiated) {
+ /* In case we could not find any non-linked collections in which instantiate our ob_dst,
+ * fallback to scene's master collection... */
+ collection_object_add(bmain, BKE_collection_master(scene), ob_dst, 0, true);
+ }
+
BKE_main_collection_sync(bmain);
}
@@ -1047,6 +1056,72 @@ bool BKE_collection_child_remove(Main *bmain, Collection *parent, Collection *ch
return true;
}
+/**
+ * Rebuild parent relationships from child ones, for all children of given \a collection.
+ *
+ * \note Given collection is assumed to already have valid parents.
+ */
+void BKE_collection_parent_relations_rebuild(Collection *collection)
+{
+ for (CollectionChild *child = collection->children.first, *child_next = NULL; child;
+ child = child_next) {
+ child_next = child->next;
+
+ if (child->collection == NULL || BKE_collection_find_cycle(collection, child->collection)) {
+ BLI_freelinkN(&collection->children, child);
+ }
+ else {
+ CollectionParent *cparent = MEM_callocN(sizeof(CollectionParent), __func__);
+ cparent->collection = collection;
+ BLI_addtail(&child->collection->parents, cparent);
+ }
+ }
+}
+
+static void collection_parents_rebuild_recursive(Collection *collection)
+{
+ BKE_collection_parent_relations_rebuild(collection);
+ collection->id.tag &= ~LIB_TAG_DOIT;
+
+ for (CollectionChild *child = collection->children.first; child != NULL; child = child->next) {
+ collection_parents_rebuild_recursive(child->collection);
+ }
+}
+
+/**
+ * Rebuild parent relationships from child ones, for all collections in given \a bmain.
+ *
+ * \note Uses LIB_TAG_DOIT internally...
+ */
+void BKE_main_collections_parent_relations_rebuild(Main *bmain)
+{
+ /* Only collections not in bmain (master ones in scenes) have no parent... */
+ for (Collection *collection = bmain->collections.first; collection != NULL;
+ collection = collection->id.next) {
+ BLI_freelistN(&collection->parents);
+
+ collection->id.tag |= LIB_TAG_DOIT;
+ }
+
+ /* Scene's master collections will be 'root' parent of most of our collections, so start with
+ * them. */
+ for (Scene *scene = bmain->scenes.first; scene != NULL; scene = scene->id.next) {
+ collection_parents_rebuild_recursive(scene->master_collection);
+ }
+
+ /* We may have parent chains outside of scene's master_collection context? At least, readfile's
+ * lib_link_collection_data() seems to assume that, so do the same here. */
+ for (Collection *collection = bmain->collections.first; collection != NULL;
+ collection = collection->id.next) {
+ if (collection->id.tag & LIB_TAG_DOIT) {
+ /* Note: we do not have easy access to 'which collections is root' info in that case, which
+ * means test for cycles in collection relationships may fail here. I don't think that is an
+ * issue in practice here, but worth keeping in mind... */
+ collection_parents_rebuild_recursive(collection);
+ }
+ }
+}
+
/********************** Collection index *********************/
static Collection *collection_from_index_recursive(Collection *collection,
@@ -1175,8 +1250,43 @@ bool BKE_collection_move(Main *bmain,
}
}
+ /* Make sure we store the flag of the layer collections before we remove and re-create them.
+ * Otherwise they will get lost and everything will be copied from the new parent collection. */
+ GHash *view_layer_hash = BLI_ghash_new(BLI_ghashutil_ptrhash, BLI_ghashutil_ptrcmp, __func__);
+
+ for (Scene *scene = bmain->scenes.first; scene; scene = scene->id.next) {
+ for (ViewLayer *view_layer = scene->view_layers.first; view_layer;
+ view_layer = view_layer->next) {
+
+ LayerCollection *layer_collection = BKE_layer_collection_first_from_scene_collection(
+ view_layer, collection);
+
+ if (layer_collection == NULL) {
+ continue;
+ }
+
+ BLI_ghash_insert(view_layer_hash, view_layer, POINTER_FROM_INT(layer_collection->flag));
+ }
+ }
+
+ /* Create and remove layer collections. */
BKE_main_collection_sync(bmain);
+ /* Restore back the original layer collection flags. */
+ GHashIterator gh_iter;
+ GHASH_ITER (gh_iter, view_layer_hash) {
+ ViewLayer *view_layer = BLI_ghashIterator_getKey(&gh_iter);
+
+ LayerCollection *layer_collection = BKE_layer_collection_first_from_scene_collection(
+ view_layer, collection);
+
+ if (layer_collection) {
+ layer_collection->flag = POINTER_AS_INT(BLI_ghashIterator_getValue(&gh_iter));
+ }
+ }
+
+ BLI_ghash_free(view_layer_hash, NULL, NULL);
+
return true;
}
diff --git a/source/blender/blenkernel/intern/context.c b/source/blender/blenkernel/intern/context.c
index 9509e408fba..28b0ae23ffe 100644
--- a/source/blender/blenkernel/intern/context.c
+++ b/source/blender/blenkernel/intern/context.c
@@ -399,6 +399,39 @@ static int ctx_data_collection_get(const bContext *C, const char *member, ListBa
return 0;
}
+static int ctx_data_base_collection_get(const bContext *C, const char *member, ListBase *list)
+{
+ ListBase ctx_object_list;
+ bool ok = false;
+
+ if ((ctx_data_collection_get(C, member, &ctx_object_list) == false) ||
+ BLI_listbase_is_empty(&ctx_object_list)) {
+ BLI_listbase_clear(list);
+ return 0;
+ }
+
+ bContextDataResult result;
+ memset(&result, 0, sizeof(bContextDataResult));
+
+ Scene *scene = CTX_data_scene(C);
+ ViewLayer *view_layer = CTX_data_view_layer(C);
+
+ CollectionPointerLink *ctx_object;
+ for (ctx_object = ctx_object_list.first; ctx_object; ctx_object = ctx_object->next) {
+ Object *ob = ctx_object->ptr.data;
+ Base *base = BKE_view_layer_base_find(view_layer, ob);
+ if (base != NULL) {
+ CTX_data_list_add(&result, &scene->id, &RNA_ObjectBase, base);
+ ok = true;
+ }
+ }
+ CTX_data_type_set(&result, CTX_DATA_TYPE_COLLECTION);
+ BLI_freelistN(&ctx_object_list);
+
+ *list = result.list;
+ return ok;
+}
+
PointerRNA CTX_data_pointer_get(const bContext *C, const char *member)
{
bContextDataResult result;
@@ -1150,7 +1183,7 @@ int CTX_data_selected_editable_objects(const bContext *C, ListBase *list)
int CTX_data_selected_editable_bases(const bContext *C, ListBase *list)
{
- return ctx_data_collection_get(C, "selected_editable_bases", list);
+ return ctx_data_base_collection_get(C, "selected_editable_objects", list);
}
int CTX_data_editable_objects(const bContext *C, ListBase *list)
@@ -1160,7 +1193,7 @@ int CTX_data_editable_objects(const bContext *C, ListBase *list)
int CTX_data_editable_bases(const bContext *C, ListBase *list)
{
- return ctx_data_collection_get(C, "editable_bases", list);
+ return ctx_data_base_collection_get(C, "editable_objects", list);
}
int CTX_data_selected_objects(const bContext *C, ListBase *list)
@@ -1170,7 +1203,7 @@ int CTX_data_selected_objects(const bContext *C, ListBase *list)
int CTX_data_selected_bases(const bContext *C, ListBase *list)
{
- return ctx_data_collection_get(C, "selected_bases", list);
+ return ctx_data_base_collection_get(C, "selected_objects", list);
}
int CTX_data_visible_objects(const bContext *C, ListBase *list)
@@ -1180,7 +1213,7 @@ int CTX_data_visible_objects(const bContext *C, ListBase *list)
int CTX_data_visible_bases(const bContext *C, ListBase *list)
{
- return ctx_data_collection_get(C, "visible_bases", list);
+ return ctx_data_base_collection_get(C, "visible_objects", list);
}
int CTX_data_selectable_objects(const bContext *C, ListBase *list)
@@ -1190,7 +1223,7 @@ int CTX_data_selectable_objects(const bContext *C, ListBase *list)
int CTX_data_selectable_bases(const bContext *C, ListBase *list)
{
- return ctx_data_collection_get(C, "selectable_bases", list);
+ return ctx_data_base_collection_get(C, "selectable_objects", list);
}
struct Object *CTX_data_active_object(const bContext *C)
@@ -1200,7 +1233,14 @@ struct Object *CTX_data_active_object(const bContext *C)
struct Base *CTX_data_active_base(const bContext *C)
{
- return ctx_data_pointer_get(C, "active_base");
+ Object *ob = ctx_data_pointer_get(C, "active_object");
+
+ if (ob == NULL) {
+ return NULL;
+ }
+
+ ViewLayer *view_layer = CTX_data_view_layer(C);
+ return BKE_view_layer_base_find(view_layer, ob);
}
struct Object *CTX_data_edit_object(const bContext *C)
diff --git a/source/blender/blenkernel/intern/curve.c b/source/blender/blenkernel/intern/curve.c
index 2775cf9691f..5945fa4bf33 100644
--- a/source/blender/blenkernel/intern/curve.c
+++ b/source/blender/blenkernel/intern/curve.c
@@ -1739,12 +1739,7 @@ static void forward_diff_bezier_cotangent(const float p0[3],
/* ***************** BEVEL ****************** */
-void BKE_curve_bevel_make(Depsgraph *depsgraph,
- Scene *scene,
- Object *ob,
- ListBase *disp,
- const bool for_render,
- LinkNode *ob_cyclic_list)
+void BKE_curve_bevel_make(Object *ob, ListBase *disp)
{
DispList *dl, *dlnew;
Curve *bevcu, *cu;
@@ -1768,25 +1763,7 @@ void BKE_curve_bevel_make(Depsgraph *depsgraph,
facx = cu->bevobj->scale[0];
facy = cu->bevobj->scale[1];
- if (for_render) {
- if (BLI_linklist_index(ob_cyclic_list, cu->bevobj) == -1) {
- BKE_displist_make_curveTypes_forRender(depsgraph,
- scene,
- cu->bevobj,
- &bevdisp,
- NULL,
- false,
- &(LinkNode){
- .link = ob,
- .next = ob_cyclic_list,
- });
- dl = bevdisp.first;
- }
- else {
- dl = NULL;
- }
- }
- else if (cu->bevobj->runtime.curve_cache) {
+ if (cu->bevobj->runtime.curve_cache) {
dl = cu->bevobj->runtime.curve_cache->disp.first;
}
else {
diff --git a/source/blender/blenkernel/intern/displist.c b/source/blender/blenkernel/intern/displist.c
index cc1c73b1e68..c8d6f7ae313 100644
--- a/source/blender/blenkernel/intern/displist.c
+++ b/source/blender/blenkernel/intern/displist.c
@@ -723,7 +723,7 @@ static float displist_calc_taper(Depsgraph *depsgraph, Scene *scene, Object *tap
dl = taperobj->runtime.curve_cache ? taperobj->runtime.curve_cache->disp.first : NULL;
if (dl == NULL) {
- BKE_displist_make_curveTypes(depsgraph, scene, taperobj, false, false, NULL);
+ BKE_displist_make_curveTypes(depsgraph, scene, taperobj, false, false);
dl = taperobj->runtime.curve_cache->disp.first;
}
if (dl) {
@@ -1527,7 +1527,6 @@ static void do_makeDispListCurveTypes(Depsgraph *depsgraph,
ListBase *dispbase,
const bool for_render,
const bool for_orco,
- LinkNode *ob_cyclic_list,
Mesh **r_final)
{
Curve *cu = ob->data;
@@ -1571,7 +1570,7 @@ static void do_makeDispListCurveTypes(Depsgraph *depsgraph,
BKE_curve_bevelList_make(ob, &nubase, for_render);
/* If curve has no bevel will return nothing */
- BKE_curve_bevel_make(depsgraph, scene, ob, &dlbev, for_render, ob_cyclic_list);
+ BKE_curve_bevel_make(ob, &dlbev);
/* no bevel or extrude, and no width correction? */
if (!dlbev.first && cu->width == 1.0f) {
@@ -1786,12 +1785,8 @@ static void do_makeDispListCurveTypes(Depsgraph *depsgraph,
}
}
-void BKE_displist_make_curveTypes(Depsgraph *depsgraph,
- Scene *scene,
- Object *ob,
- const bool for_render,
- const bool for_orco,
- LinkNode *ob_cyclic_list)
+void BKE_displist_make_curveTypes(
+ Depsgraph *depsgraph, Scene *scene, Object *ob, const bool for_render, const bool for_orco)
{
ListBase *dispbase;
@@ -1810,14 +1805,8 @@ void BKE_displist_make_curveTypes(Depsgraph *depsgraph,
dispbase = &(ob->runtime.curve_cache->disp);
- do_makeDispListCurveTypes(depsgraph,
- scene,
- ob,
- dispbase,
- for_render,
- for_orco,
- ob_cyclic_list,
- &ob->runtime.mesh_eval);
+ do_makeDispListCurveTypes(
+ depsgraph, scene, ob, dispbase, for_render, for_orco, &ob->runtime.mesh_eval);
boundbox_displist_object(ob);
}
@@ -1827,15 +1816,13 @@ void BKE_displist_make_curveTypes_forRender(Depsgraph *depsgraph,
Object *ob,
ListBase *dispbase,
Mesh **r_final,
- const bool for_orco,
- LinkNode *ob_cyclic_list)
+ const bool for_orco)
{
if (ob->runtime.curve_cache == NULL) {
ob->runtime.curve_cache = MEM_callocN(sizeof(CurveCache), "CurveCache for Curve");
}
- do_makeDispListCurveTypes(
- depsgraph, scene, ob, dispbase, true, for_orco, ob_cyclic_list, r_final);
+ do_makeDispListCurveTypes(depsgraph, scene, ob, dispbase, true, for_orco, r_final);
}
void BKE_displist_minmax(ListBase *dispbase, float min[3], float max[3])
diff --git a/source/blender/blenkernel/intern/editmesh.c b/source/blender/blenkernel/intern/editmesh.c
index 130f4ae88f1..b8234ccc5bb 100644
--- a/source/blender/blenkernel/intern/editmesh.c
+++ b/source/blender/blenkernel/intern/editmesh.c
@@ -248,3 +248,13 @@ void BKE_editmesh_lnorspace_update(BMEditMesh *em)
BM_lnorspace_update(bm);
}
+
+/* If autosmooth not already set, set it */
+void BKE_editmesh_ensure_autosmooth(BMEditMesh *em)
+{
+ Mesh *me = em->ob->data;
+ if (!(me->flag & ME_AUTOSMOOTH)) {
+ me->flag |= ME_AUTOSMOOTH;
+ BKE_editmesh_lnorspace_update(em);
+ }
+}
diff --git a/source/blender/blenkernel/intern/effect.c b/source/blender/blenkernel/intern/effect.c
index 51715c3a223..7cbd5b6b050 100644
--- a/source/blender/blenkernel/intern/effect.c
+++ b/source/blender/blenkernel/intern/effect.c
@@ -172,7 +172,7 @@ static void precalculate_effector(struct Depsgraph *depsgraph, EffectorCache *ef
if (cu->flag & CU_PATH) {
if (eff->ob->runtime.curve_cache == NULL || eff->ob->runtime.curve_cache->path == NULL ||
eff->ob->runtime.curve_cache->path->data == NULL) {
- BKE_displist_make_curveTypes(depsgraph, eff->scene, eff->ob, false, false, NULL);
+ BKE_displist_make_curveTypes(depsgraph, eff->scene, eff->ob, false, false);
}
if (eff->ob->runtime.curve_cache->path && eff->ob->runtime.curve_cache->path->data) {
diff --git a/source/blender/blenkernel/intern/image.c b/source/blender/blenkernel/intern/image.c
index d59ead25396..9960994400f 100644
--- a/source/blender/blenkernel/intern/image.c
+++ b/source/blender/blenkernel/intern/image.c
@@ -502,6 +502,12 @@ static void image_init_color_management(Image *ima)
if (ibuf->flags & IB_alphamode_premul) {
ima->alpha_mode = IMA_ALPHA_PREMUL;
}
+ else if (ibuf->flags & IB_alphamode_channel_packed) {
+ ima->alpha_mode = IMA_ALPHA_CHANNEL_PACKED;
+ }
+ else if (ibuf->flags & IB_alphamode_ignore) {
+ ima->alpha_mode = IMA_ALPHA_IGNORE;
+ }
else {
ima->alpha_mode = IMA_ALPHA_STRAIGHT;
}
@@ -3592,16 +3598,18 @@ static void image_initialize_after_load(Image *ima, ImBuf *UNUSED(ibuf))
static int imbuf_alpha_flags_for_image(Image *ima)
{
- int flag = 0;
-
- if (ima->flag & IMA_IGNORE_ALPHA) {
- flag |= IB_ignore_alpha;
- }
- else if (ima->alpha_mode == IMA_ALPHA_PREMUL) {
- flag |= IB_alphamode_premul;
+ switch (ima->alpha_mode) {
+ case IMA_ALPHA_STRAIGHT:
+ return 0;
+ case IMA_ALPHA_PREMUL:
+ return IB_alphamode_premul;
+ case IMA_ALPHA_CHANNEL_PACKED:
+ return IB_alphamode_channel_packed;
+ case IMA_ALPHA_IGNORE:
+ return IB_alphamode_ignore;
}
- return flag;
+ return 0;
}
/* the number of files will vary according to the stereo format */
diff --git a/source/blender/blenkernel/intern/library.c b/source/blender/blenkernel/intern/library.c
index 7fb6f78def1..27203158a4f 100644
--- a/source/blender/blenkernel/intern/library.c
+++ b/source/blender/blenkernel/intern/library.c
@@ -873,7 +873,7 @@ bool id_single_user(bContext *C, ID *id, PointerRNA *ptr, PropertyRNA *prop)
/* assign copy */
RNA_id_pointer_create(newid, &idptr);
- RNA_property_pointer_set(NULL, ptr, prop, idptr);
+ RNA_property_pointer_set(ptr, prop, idptr, NULL);
RNA_property_update(C, ptr, prop);
/* tag grease pencil datablock and disable onion */
@@ -1788,6 +1788,59 @@ void BKE_main_id_clear_newpoins(Main *bmain)
FOREACH_MAIN_ID_END;
}
+static int id_refcount_recompute_callback(void *user_data,
+ struct ID *UNUSED(id_self),
+ struct ID **id_pointer,
+ int cb_flag)
+{
+ const bool do_linked_only = (bool)POINTER_AS_INT(user_data);
+
+ if (*id_pointer == NULL) {
+ return IDWALK_RET_NOP;
+ }
+ if (do_linked_only && !ID_IS_LINKED(*id_pointer)) {
+ return IDWALK_RET_NOP;
+ }
+
+ if (cb_flag & IDWALK_CB_USER) {
+ /* Do not touch to direct/indirect linked status here... */
+ id_us_plus_no_lib(*id_pointer);
+ }
+ if (cb_flag & IDWALK_CB_USER_ONE) {
+ id_us_ensure_real(*id_pointer);
+ }
+
+ return IDWALK_RET_NOP;
+}
+
+void BLE_main_id_refcount_recompute(struct Main *bmain, const bool do_linked_only)
+{
+ ID *id;
+
+ FOREACH_MAIN_ID_BEGIN (bmain, id) {
+ if (!ID_IS_LINKED(id) && do_linked_only) {
+ continue;
+ }
+ id->us = ID_FAKE_USERS(id);
+ /* Note that we keep EXTRAUSER tag here, since some UI users may define it too... */
+ if (id->tag & LIB_TAG_EXTRAUSER) {
+ id->tag &= ~(LIB_TAG_EXTRAUSER | LIB_TAG_EXTRAUSER_SET);
+ id_us_ensure_real(id);
+ }
+ }
+ FOREACH_MAIN_ID_END;
+
+ /* Go over whole Main database to re-generate proper usercounts... */
+ FOREACH_MAIN_ID_BEGIN (bmain, id) {
+ BKE_library_foreach_ID_link(bmain,
+ id,
+ id_refcount_recompute_callback,
+ POINTER_FROM_INT((int)do_linked_only),
+ IDWALK_READONLY);
+ }
+ FOREACH_MAIN_ID_END;
+}
+
static void library_make_local_copying_check(ID *id,
GSet *loop_tags,
MainIDRelations *id_relations,
@@ -1813,7 +1866,8 @@ static void library_make_local_copying_check(ID *id,
}
/* Shapekeys are considered 'private' to their owner ID here, and never tagged
- * (since they cannot be linked), * so we have to switch effective parent to their owner. */
+ * (since they cannot be linked), * so we have to switch effective parent to their owner.
+ */
if (GS(par_id->name) == ID_KE) {
par_id = ((Key *)par_id)->from;
}
@@ -1855,17 +1909,17 @@ static void library_make_local_copying_check(ID *id,
*
* \param bmain: Almost certainly global main.
* \param lib: If not NULL, only make local datablocks from this library.
- * \param untagged_only: If true, only make local datablocks not tagged with LIB_TAG_PRE_EXISTING.
- * \param set_fake: If true, set fake user on all localized data-blocks
+ * \param untagged_only: If true, only make local datablocks not tagged with
+ * LIB_TAG_PRE_EXISTING. \param set_fake: If true, set fake user on all localized data-blocks
* (except group and objects ones).
*/
/* Note: Old (2.77) version was simply making (tagging) data-blocks as local,
* without actually making any check whether they were also indirectly used or not...
*
- * Current version uses regular id_make_local callback, with advanced pre-processing step to detect
- * all cases of IDs currently indirectly used, but which will be used by local data only once this
- * function is finished. This allows to avoid any unneeded duplication of IDs, and hence all time
- * lost afterwards to remove orphaned linked data-blocks...
+ * Current version uses regular id_make_local callback, with advanced pre-processing step to
+ * detect all cases of IDs currently indirectly used, but which will be used by local data only
+ * once this function is finished. This allows to avoid any unneeded duplication of IDs, and
+ * hence all time lost afterwards to remove orphaned linked data-blocks...
*/
void BKE_library_make_local(Main *bmain,
const Library *lib,
@@ -1976,16 +2030,17 @@ void BKE_library_make_local(Main *bmain,
ID *id = it->link;
if (id->tag & LIB_TAG_DOIT) {
- /* We know all users of this object are local or will be made fully local, even if currently
- * there are some indirect usages. So instead of making a copy that we'll likely get rid of
- * later, directly make that data block local.
+ /* We know all users of this object are local or will be made fully local, even if
+ * currently there are some indirect usages. So instead of making a copy that we'll likely
+ * get rid of later, directly make that data block local.
* Saves a tremendous amount of time with complex scenes... */
id_clear_lib_data_ex(bmain, id, true);
BKE_id_expand_local(bmain, id);
id->tag &= ~LIB_TAG_DOIT;
}
else {
- /* In this specific case, we do want to make ID local even if it has no local usage yet... */
+ /* In this specific case, we do want to make ID local even if it has no local usage yet...
+ */
if (GS(id->name) == ID_OB) {
/* Special case for objects because we don't want proxy pointers to be
* cleared yet. This will happen down the road in this function.
@@ -2039,8 +2094,9 @@ void BKE_library_make_local(Main *bmain,
BLI_ghash_insert(old_to_new_ids, id, id->newid);
}
- /* Special hack for groups... Thing is, since we can't instantiate them here, we need to ensure
- * they remain 'alive' (only instantiation is a real group 'user'... *sigh* See T49722. */
+ /* Special hack for groups... Thing is, since we can't instantiate them here, we need to
+ * ensure they remain 'alive' (only instantiation is a real group 'user'... *sigh* See
+ * T49722. */
if (GS(id->name) == ID_GR && (id->tag & LIB_TAG_INDIRECT) != 0) {
id_us_ensure_real(id->newid);
}
@@ -2108,11 +2164,11 @@ void BKE_library_make_local(Main *bmain,
#endif
/* This is probably more of a hack than something we should do here, but...
- * Issue is, the whole copying + remapping done in complex cases above may leave pose-channels of
- * armatures in complete invalid state (more precisely, the bone pointers of the pose-channels -
- * very crappy cross-data-blocks relationship), se we tag it to be fully recomputed,
- * but this does not seems to be enough in some cases, and evaluation code ends up trying to
- * evaluate a not-yet-updated armature object's deformations.
+ * Issue is, the whole copying + remapping done in complex cases above may leave pose-channels
+ * of armatures in complete invalid state (more precisely, the bone pointers of the
+ * pose-channels - very crappy cross-data-blocks relationship), se we tag it to be fully
+ * recomputed, but this does not seems to be enough in some cases, and evaluation code ends up
+ * trying to evaluate a not-yet-updated armature object's deformations.
* Try "make all local" in 04_01_H.lighting.blend from Agent327 without this, e.g. */
for (Object *ob = bmain->objects.first; ob; ob = ob->id.next) {
if (ob->data != NULL && ob->type == OB_ARMATURE && ob->pose != NULL &&
@@ -2289,7 +2345,8 @@ void BKE_id_tag_clear_atomic(ID *id, int tag)
* Main intended use is for debug asserts in places we cannot easily get rid of G_Main... */
bool BKE_id_is_in_global_main(ID *id)
{
- /* We do not want to fail when id is NULL here, even though this is a bit strange behavior... */
+ /* We do not want to fail when id is NULL here, even though this is a bit strange behavior...
+ */
return (id == NULL || BLI_findindex(which_libbase(G_MAIN, GS(id->name)), id) != -1);
}
diff --git a/source/blender/blenkernel/intern/library_query.c b/source/blender/blenkernel/intern/library_query.c
index a95069a2af9..085051f633c 100644
--- a/source/blender/blenkernel/intern/library_query.c
+++ b/source/blender/blenkernel/intern/library_query.c
@@ -591,7 +591,7 @@ static void library_foreach_ID_link(Main *bmain,
CALLBACK_INVOKE(object->parent, IDWALK_CB_NEVER_SELF);
CALLBACK_INVOKE(object->track, IDWALK_CB_NEVER_SELF);
/* object->proxy is refcounted, but not object->proxy_group... *sigh* */
- CALLBACK_INVOKE(object->proxy, IDWALK_CB_NEVER_SELF);
+ CALLBACK_INVOKE(object->proxy, IDWALK_CB_USER | IDWALK_CB_NEVER_SELF);
CALLBACK_INVOKE(object->proxy_group, IDWALK_CB_NOP);
/* Special case!
diff --git a/source/blender/blenkernel/intern/library_remap.c b/source/blender/blenkernel/intern/library_remap.c
index 4e5eac7924b..802f13ea69f 100644
--- a/source/blender/blenkernel/intern/library_remap.c
+++ b/source/blender/blenkernel/intern/library_remap.c
@@ -287,6 +287,13 @@ static int foreach_libblock_remap_callback(void *user_data, ID *id_self, ID **id
if (!is_indirect || is_obj_proxy) {
id_remap_data->status |= ID_REMAP_IS_LINKED_DIRECT;
}
+ /* We need to remap proxy_from pointer of remapped proxy... sigh. */
+ if (is_obj_proxy && new_id != NULL) {
+ Object *ob = (Object *)id;
+ if (ob->proxy == (Object *)new_id) {
+ ob->proxy->proxy_from = ob;
+ }
+ }
}
}
@@ -368,6 +375,11 @@ static void libblock_remap_data_postprocess_collection_update(Main *bmain,
* I'd consider optimizing that whole collection remapping process a TODO for later. */
BKE_collections_child_remove_nulls(bmain, NULL /*old_collection*/);
}
+ else {
+ /* Temp safe fix, but a "tad" brute force... We should probably be able to use parents from
+ * old_collection instead? */
+ BKE_main_collections_parent_relations_rebuild(bmain);
+ }
BKE_main_collection_sync_remap(bmain);
}
diff --git a/source/blender/blenkernel/intern/mask.c b/source/blender/blenkernel/intern/mask.c
index 9a9b3757ef2..bb93d068bef 100644
--- a/source/blender/blenkernel/intern/mask.c
+++ b/source/blender/blenkernel/intern/mask.c
@@ -225,6 +225,16 @@ MaskLayer *BKE_mask_layer_copy(const MaskLayer *masklay)
MaskSpline *spline_new = BKE_mask_spline_copy(spline);
BLI_addtail(&masklay_new->splines, spline_new);
+
+ if (spline == masklay->act_spline) {
+ masklay_new->act_spline = spline_new;
+ }
+
+ if (masklay->act_point >= spline->points &&
+ masklay->act_point < spline->points + spline->tot_point) {
+ const size_t point_index = masklay->act_point - spline->points;
+ masklay_new->act_point = spline_new->points + point_index;
+ }
}
/* correct animation */
@@ -1459,13 +1469,6 @@ void BKE_mask_evaluate(Mask *mask, const float ctime, const bool do_newframe)
}
}
-/* the purpose of this function is to ensure spline->points_deform is never out of date.
- * for now re-evaluate all. eventually this might work differently */
-void BKE_mask_update_display(Mask *mask, float ctime)
-{
- BKE_mask_evaluate(mask, ctime, false);
-}
-
void BKE_mask_evaluate_all_masks(Main *bmain, float ctime, const bool do_newframe)
{
Mask *mask;
diff --git a/source/blender/blenkernel/intern/mask_evaluate.c b/source/blender/blenkernel/intern/mask_evaluate.c
index 4e6ca878b7a..f4f93fcb698 100644
--- a/source/blender/blenkernel/intern/mask_evaluate.c
+++ b/source/blender/blenkernel/intern/mask_evaluate.c
@@ -954,10 +954,30 @@ void BKE_mask_eval_animation(struct Depsgraph *depsgraph, Mask *mask)
void BKE_mask_eval_update(struct Depsgraph *depsgraph, Mask *mask)
{
+ const bool is_depsgraph_active = DEG_is_active(depsgraph);
float ctime = DEG_get_ctime(depsgraph);
DEG_debug_print_eval(depsgraph, __func__, mask->id.name, mask);
for (MaskLayer *mask_layer = mask->masklayers.first; mask_layer != NULL;
mask_layer = mask_layer->next) {
BKE_mask_layer_evaluate_deform(mask_layer, ctime);
}
+
+ if (is_depsgraph_active) {
+ Mask *mask_orig = (Mask *)DEG_get_original_id(&mask->id);
+ for (MaskLayer *masklay_orig = mask_orig->masklayers.first,
+ *masklay_eval = mask->masklayers.first;
+ masklay_orig != NULL;
+ masklay_orig = masklay_orig->next, masklay_eval = masklay_eval->next) {
+ for (MaskSpline *spline_orig = masklay_orig->splines.first,
+ *spline_eval = masklay_eval->splines.first;
+ spline_orig != NULL;
+ spline_orig = spline_orig->next, spline_eval = spline_eval->next) {
+ for (int i = 0; i < spline_eval->tot_point; i++) {
+ MaskSplinePoint *point_eval = &spline_eval->points[i];
+ MaskSplinePoint *point_orig = &spline_orig->points[i];
+ point_orig->bezt = point_eval->bezt;
+ }
+ }
+ }
+ }
}
diff --git a/source/blender/blenkernel/intern/material.c b/source/blender/blenkernel/intern/material.c
index 75b9e355df9..1e5a2d53bfa 100644
--- a/source/blender/blenkernel/intern/material.c
+++ b/source/blender/blenkernel/intern/material.c
@@ -133,7 +133,7 @@ void BKE_material_init(Material *ma)
ma->a = 1.0f;
ma->spec = 0.5;
- ma->roughness = 0.25f;
+ ma->roughness = 0.4f;
ma->pr_type = MA_SPHERE;
diff --git a/source/blender/blenkernel/intern/mesh_convert.c b/source/blender/blenkernel/intern/mesh_convert.c
index dca5248c0fa..fce80272738 100644
--- a/source/blender/blenkernel/intern/mesh_convert.c
+++ b/source/blender/blenkernel/intern/mesh_convert.c
@@ -1005,8 +1005,7 @@ static void curve_to_mesh_eval_ensure(Object *object)
&remapped_object,
&remapped_object.runtime.curve_cache->disp,
&remapped_object.runtime.mesh_eval,
- false,
- NULL);
+ false);
BKE_object_free_curve_cache(&bevel_object);
BKE_object_free_curve_cache(&taper_object);
@@ -1083,17 +1082,11 @@ static Mesh *mesh_new_from_mball_object(Object *object)
return mesh_result;
}
-static Mesh *mesh_new_from_mesh_object(Object *object)
+static Mesh *mesh_new_from_mesh(Object *object, Mesh *mesh)
{
- Mesh *mesh_input = object->data;
- /* If we are in edit mode, use evaluated mesh from edit structure, matching to what
- * viewport is using for visualization. */
- if (mesh_input->edit_mesh != NULL && mesh_input->edit_mesh->mesh_eval_final) {
- mesh_input = mesh_input->edit_mesh->mesh_eval_final;
- }
Mesh *mesh_result = NULL;
BKE_id_copy_ex(NULL,
- &mesh_input->id,
+ &mesh->id,
(ID **)&mesh_result,
LIB_ID_CREATE_NO_MAIN | LIB_ID_CREATE_NO_USER_REFCOUNT);
/* NOTE: Materials should already be copied. */
@@ -1102,7 +1095,52 @@ static Mesh *mesh_new_from_mesh_object(Object *object)
return mesh_result;
}
-Mesh *BKE_mesh_new_from_object(Object *object)
+static Mesh *mesh_new_from_mesh_object_with_layers(Depsgraph *depsgraph, Object *object)
+{
+ if (DEG_is_original_id(&object->id)) {
+ return mesh_new_from_mesh(object, (Mesh *)object->data);
+ }
+
+ if (depsgraph == NULL) {
+ return NULL;
+ }
+
+ Object object_for_eval = *object;
+ if (object_for_eval.runtime.mesh_orig != NULL) {
+ object_for_eval.data = object_for_eval.runtime.mesh_orig;
+ }
+
+ Scene *scene = DEG_get_evaluated_scene(depsgraph);
+ CustomData_MeshMasks mask = CD_MASK_MESH;
+ Mesh *result;
+
+ if (DEG_get_mode(depsgraph) == DAG_EVAL_RENDER) {
+ result = mesh_create_eval_final_render(depsgraph, scene, &object_for_eval, &mask);
+ }
+ else {
+ result = mesh_create_eval_final_view(depsgraph, scene, &object_for_eval, &mask);
+ }
+
+ return result;
+}
+
+static Mesh *mesh_new_from_mesh_object(Depsgraph *depsgraph,
+ Object *object,
+ bool preserve_all_data_layers)
+{
+ if (preserve_all_data_layers) {
+ return mesh_new_from_mesh_object_with_layers(depsgraph, object);
+ }
+ Mesh *mesh_input = object->data;
+ /* If we are in edit mode, use evaluated mesh from edit structure, matching to what
+ * viewport is using for visualization. */
+ if (mesh_input->edit_mesh != NULL && mesh_input->edit_mesh->mesh_eval_final) {
+ mesh_input = mesh_input->edit_mesh->mesh_eval_final;
+ }
+ return mesh_new_from_mesh(object, mesh_input);
+}
+
+Mesh *BKE_mesh_new_from_object(Depsgraph *depsgraph, Object *object, bool preserve_all_data_layers)
{
Mesh *new_mesh = NULL;
switch (object->type) {
@@ -1115,7 +1153,7 @@ Mesh *BKE_mesh_new_from_object(Object *object)
new_mesh = mesh_new_from_mball_object(object);
break;
case OB_MESH:
- new_mesh = mesh_new_from_mesh_object(object);
+ new_mesh = mesh_new_from_mesh_object(depsgraph, object, preserve_all_data_layers);
break;
default:
/* Object does not have geometry data. */
@@ -1141,13 +1179,24 @@ static int foreach_libblock_make_original_and_usercount_callback(void *user_data
return IDWALK_RET_NOP;
}
*id_p = DEG_get_original_id(*id_p);
- id_us_plus(*id_p);
+
+ if (cb_flag & IDWALK_CB_USER) {
+ id_us_plus(*id_p);
+ }
+ else if (cb_flag & IDWALK_CB_USER_ONE) {
+ /* Note: in that context, that one should not be needed (since there should be at least already
+ * one USER_ONE user of that ID), but better be consistent. */
+ id_us_ensure_real(*id_p);
+ }
return IDWALK_RET_NOP;
}
-Mesh *BKE_mesh_new_from_object_to_bmain(Main *bmain, Object *object)
+Mesh *BKE_mesh_new_from_object_to_bmain(Main *bmain,
+ Depsgraph *depsgraph,
+ Object *object,
+ bool preserve_all_data_layers)
{
- Mesh *mesh = BKE_mesh_new_from_object(object);
+ Mesh *mesh = BKE_mesh_new_from_object(depsgraph, object, preserve_all_data_layers);
/* Make sure mesh only points original datablocks, also increase users of materials and other
* possibly referenced data-blocks.
diff --git a/source/blender/blenkernel/intern/mesh_evaluate.c b/source/blender/blenkernel/intern/mesh_evaluate.c
index d889fca3a3a..f0fd1203cae 100644
--- a/source/blender/blenkernel/intern/mesh_evaluate.c
+++ b/source/blender/blenkernel/intern/mesh_evaluate.c
@@ -2141,8 +2141,8 @@ static void mesh_set_custom_normals(Mesh *mesh, float (*r_custom_nors)[3], const
* Higher level functions hiding most of the code needed around call to
* #BKE_mesh_normals_loop_custom_set().
*
- * \param r_custom_loopnors is not const, since code will replace zero_v3 normals there
- * with automatically computed vectors.
+ * \param r_custom_loopnors: is not const, since code will replace zero_v3 normals there
+ * with automatically computed vectors.
*/
void BKE_mesh_set_custom_normals(Mesh *mesh, float (*r_custom_loopnors)[3])
{
@@ -2153,8 +2153,8 @@ void BKE_mesh_set_custom_normals(Mesh *mesh, float (*r_custom_loopnors)[3])
* Higher level functions hiding most of the code needed around call to
* #BKE_mesh_normals_loop_custom_from_vertices_set().
*
- * \param r_custom_loopnors is not const, since code will replace zero_v3 normals there
- * with automatically computed vectors.
+ * \param r_custom_loopnors: is not const, since code will replace zero_v3 normals there
+ * with automatically computed vectors.
*/
void BKE_mesh_set_custom_normals_from_vertices(Mesh *mesh, float (*r_custom_vertnors)[3])
{
diff --git a/source/blender/blenkernel/intern/modifier.c b/source/blender/blenkernel/intern/modifier.c
index 9bc9865631f..43a5e1d6592 100644
--- a/source/blender/blenkernel/intern/modifier.c
+++ b/source/blender/blenkernel/intern/modifier.c
@@ -934,8 +934,8 @@ void modwrap_deformVertsEM(ModifierData *md,
* Note that modifiers in stack always get fully evaluated COW ID pointers,
* never original ones. Makes things simpler.
*
- * \param get_cage_mesh Return evaluated mesh with only deforming modifiers applied
- * (i.e. mesh topology remains the same as original one, a.k.a. 'cage' mesh).
+ * \param get_cage_mesh: Return evaluated mesh with only deforming modifiers applied
+ * (i.e. mesh topology remains the same as original one, a.k.a. 'cage' mesh).
*/
Mesh *BKE_modifier_get_evaluated_mesh_from_evaluated_object(Object *ob_eval,
const bool get_cage_mesh)
diff --git a/source/blender/blenkernel/intern/object.c b/source/blender/blenkernel/intern/object.c
index 95be7f8f51f..fcb1066b633 100644
--- a/source/blender/blenkernel/intern/object.c
+++ b/source/blender/blenkernel/intern/object.c
@@ -1468,7 +1468,7 @@ Object *BKE_object_copy(Main *bmain, const Object *ob)
/** Perform deep-copy of object and its 'children' data-blocks (obdata, materials, actions, etc.).
*
- * \param dupflag Controls which sub-data are also duplicated
+ * \param dupflag: Controls which sub-data are also duplicated
* (see #eDupli_ID_Flags in DNA_userdef_types.h).
*
* \note This function does not do any remapping to new IDs, caller must do it
@@ -4499,11 +4499,11 @@ void BKE_object_update_select_id(struct Main *bmain)
}
}
-Mesh *BKE_object_to_mesh(Object *object)
+Mesh *BKE_object_to_mesh(Depsgraph *depsgraph, Object *object, bool preserve_all_data_layers)
{
BKE_object_to_mesh_clear(object);
- Mesh *mesh = BKE_mesh_new_from_object(object);
+ Mesh *mesh = BKE_mesh_new_from_object(depsgraph, object, preserve_all_data_layers);
object->runtime.object_as_temp_mesh = mesh;
return mesh;
}
diff --git a/source/blender/blenkernel/intern/object_update.c b/source/blender/blenkernel/intern/object_update.c
index 77941e7d607..6dee936ca76 100644
--- a/source/blender/blenkernel/intern/object_update.c
+++ b/source/blender/blenkernel/intern/object_update.c
@@ -204,7 +204,7 @@ void BKE_object_handle_data_update(Depsgraph *depsgraph, Scene *scene, Object *o
case OB_SURF:
case OB_FONT: {
bool for_render = (DEG_get_mode(depsgraph) == DAG_EVAL_RENDER);
- BKE_displist_make_curveTypes(depsgraph, scene, ob, for_render, false, NULL);
+ BKE_displist_make_curveTypes(depsgraph, scene, ob, for_render, false);
break;
}
diff --git a/source/blender/blenkernel/intern/paint.c b/source/blender/blenkernel/intern/paint.c
index bd06e2fe7e0..5849d691b03 100644
--- a/source/blender/blenkernel/intern/paint.c
+++ b/source/blender/blenkernel/intern/paint.c
@@ -102,8 +102,11 @@ void BKE_paint_invalidate_overlay_tex(Scene *scene, ViewLayer *view_layer, const
void BKE_paint_invalidate_cursor_overlay(Scene *scene, ViewLayer *view_layer, CurveMapping *curve)
{
Paint *p = BKE_paint_get_active(scene, view_layer);
- Brush *br = p->brush;
+ if (p == NULL) {
+ return;
+ }
+ Brush *br = p->brush;
if (br && br->curve == curve) {
overlay_flags |= PAINT_OVERLAY_INVALID_CURVE;
}
diff --git a/source/blender/blenkernel/intern/particle.c b/source/blender/blenkernel/intern/particle.c
index c6cc72ba989..13649eaf096 100644
--- a/source/blender/blenkernel/intern/particle.c
+++ b/source/blender/blenkernel/intern/particle.c
@@ -387,8 +387,11 @@ void psys_find_group_weights(ParticleSettings *part)
/* Find object pointers based on index. If the collection is linked from
* another library linking may not have the object pointers available on
* file load, so we have to retrieve them later. See T49273. */
- const ListBase instance_collection_objects = BKE_collection_object_cache_get(
- part->instance_collection);
+ ListBase instance_collection_objects = {NULL, NULL};
+
+ if (part->instance_collection) {
+ instance_collection_objects = BKE_collection_object_cache_get(part->instance_collection);
+ }
for (ParticleDupliWeight *dw = part->instance_weights.first; dw; dw = dw->next) {
if (dw->ob == NULL) {
diff --git a/source/blender/blenkernel/intern/particle_system.c b/source/blender/blenkernel/intern/particle_system.c
index cba15aed55f..27722aab2d9 100644
--- a/source/blender/blenkernel/intern/particle_system.c
+++ b/source/blender/blenkernel/intern/particle_system.c
@@ -471,14 +471,6 @@ void psys_thread_context_init(ParticleThreadContext *ctx, ParticleSimulationData
ctx->ma = give_current_material(sim->ob, sim->psys->part->omat);
}
-#define MAX_PARTICLES_PER_TASK \
- 256 /* XXX arbitrary - maybe use at least number of points instead for better balancing? */
-
-BLI_INLINE int ceil_ii(int a, int b)
-{
- return (a + b - 1) / b;
-}
-
void psys_tasks_create(ParticleThreadContext *ctx,
int startpart,
int endpart,
@@ -486,7 +478,7 @@ void psys_tasks_create(ParticleThreadContext *ctx,
int *r_numtasks)
{
ParticleTask *tasks;
- int numtasks = ceil_ii((endpart - startpart), MAX_PARTICLES_PER_TASK);
+ int numtasks = min_ii(BLI_system_thread_count() * 4, endpart - startpart);
float particles_per_task = (float)(endpart - startpart) / (float)numtasks, p, pnext;
int i;
diff --git a/source/blender/blenkernel/intern/scene.c b/source/blender/blenkernel/intern/scene.c
index 3d864a9fa00..87979e5d5dd 100644
--- a/source/blender/blenkernel/intern/scene.c
+++ b/source/blender/blenkernel/intern/scene.c
@@ -916,7 +916,7 @@ void BKE_scene_init(Scene *sce)
sce->eevee.gi_cubemap_draw_size = 0.3f;
sce->eevee.gi_irradiance_draw_size = 0.1f;
sce->eevee.gi_irradiance_smoothing = 0.1f;
- sce->eevee.gi_filter_quality = 1.0f;
+ sce->eevee.gi_filter_quality = 3.0f;
sce->eevee.taa_samples = 16;
sce->eevee.taa_render_samples = 64;
diff --git a/source/blender/blenkernel/intern/screen.c b/source/blender/blenkernel/intern/screen.c
index bc9ec6b28e6..3ff8b6ff18c 100644
--- a/source/blender/blenkernel/intern/screen.c
+++ b/source/blender/blenkernel/intern/screen.c
@@ -843,7 +843,7 @@ void BKE_screen_view3d_shading_init(View3DShading *shading)
shading->light = V3D_LIGHTING_STUDIO;
shading->shadow_intensity = 0.5f;
shading->xray_alpha = 0.5f;
- shading->xray_alpha_wire = 0.5f;
+ shading->xray_alpha_wire = 0.0f;
shading->cavity_valley_factor = 1.0f;
shading->cavity_ridge_factor = 1.0f;
shading->cavity_type = V3D_SHADING_CAVITY_CURVATURE;
diff --git a/source/blender/blenkernel/intern/seqcache.c b/source/blender/blenkernel/intern/seqcache.c
index 1c0aa63f590..6f5b5f90d37 100644
--- a/source/blender/blenkernel/intern/seqcache.c
+++ b/source/blender/blenkernel/intern/seqcache.c
@@ -90,7 +90,6 @@ typedef struct SeqCacheKey {
struct SeqCacheKey *link_next; /* Used for linking intermediate items to final frame */
struct Sequence *seq;
SeqRenderData context;
- float cfra;
float nfra;
float cost;
bool is_temp_cache;
@@ -232,14 +231,17 @@ static SeqCacheKey *seq_cache_choose_key(Scene *scene, SeqCacheKey *lkey, SeqCac
SeqCacheKey *finalkey = NULL;
if (rkey && lkey) {
- if (lkey->cfra > rkey->cfra) {
+ int lkey_cfra = lkey->seq->start + lkey->nfra;
+ int rkey_cfra = rkey->seq->start + rkey->nfra;
+
+ if (lkey_cfra > rkey_cfra) {
SeqCacheKey *swapkey = lkey;
lkey = rkey;
rkey = swapkey;
}
- int l_diff = scene->r.cfra - lkey->cfra;
- int r_diff = rkey->cfra - scene->r.cfra;
+ int l_diff = scene->r.cfra - lkey_cfra;
+ int r_diff = rkey_cfra - scene->r.cfra;
if (l_diff > r_diff) {
finalkey = lkey;
@@ -319,7 +321,7 @@ static SeqCacheKey *seq_cache_get_item_for_removal(Scene *scene)
if (key->cost <= scene->ed->recycle_max_cost) {
cheap_count++;
if (lkey) {
- if (key->cfra < lkey->cfra) {
+ if (key->seq->start + key->nfra < lkey->seq->start + lkey->nfra) {
lkey = key;
}
}
@@ -327,7 +329,7 @@ static SeqCacheKey *seq_cache_get_item_for_removal(Scene *scene)
lkey = key;
}
if (rkey) {
- if (key->cfra > rkey->cfra) {
+ if (key->seq->start + key->nfra > rkey->seq->start + rkey->nfra) {
rkey = key;
}
}
@@ -425,7 +427,7 @@ void BKE_sequencer_cache_free_temp_cache(Scene *scene, short id, int cfra)
SeqCacheKey *key = BLI_ghashIterator_getKey(&gh_iter);
BLI_ghashIterator_step(&gh_iter);
- if (key->is_temp_cache && key->creator_id == id && key->cfra != cfra) {
+ if (key->is_temp_cache && key->creator_id == id && key->seq->start + key->nfra != cfra) {
BLI_ghash_remove(cache->hash, key, seq_cache_keyfree, seq_cache_valfree);
}
}
@@ -474,7 +476,10 @@ void BKE_sequencer_cache_cleanup(Scene *scene)
seq_cache_unlock(scene);
}
-void BKE_sequencer_cache_cleanup_sequence(Scene *scene, Sequence *seq)
+void BKE_sequencer_cache_cleanup_sequence(Scene *scene,
+ Sequence *seq,
+ Sequence *seq_changed,
+ int invalidate_types)
{
SeqCache *cache = seq_cache_get_from_scene(scene);
if (!cache) {
@@ -483,14 +488,40 @@ void BKE_sequencer_cache_cleanup_sequence(Scene *scene, Sequence *seq)
seq_cache_lock(scene);
+ int range_start = seq_changed->startdisp;
+ int range_end = seq_changed->enddisp;
+
+ if (seq->startdisp > range_start) {
+ range_start = seq->startdisp;
+ }
+
+ if (seq->enddisp < range_end) {
+ range_end = seq->enddisp;
+ }
+
+ int invalidate_composite = invalidate_types & SEQ_CACHE_STORE_FINAL_OUT;
+ int invalidate_source = invalidate_types & (SEQ_CACHE_STORE_RAW | SEQ_CACHE_STORE_PREPROCESSED |
+ SEQ_CACHE_STORE_COMPOSITE);
+
GHashIterator gh_iter;
BLI_ghashIterator_init(&gh_iter, cache->hash);
while (!BLI_ghashIterator_done(&gh_iter)) {
SeqCacheKey *key = BLI_ghashIterator_getKey(&gh_iter);
BLI_ghashIterator_step(&gh_iter);
- if (key->seq == seq) {
- /* Relink keys, so we don't end up with orphaned keys */
+ int key_cfra = key->seq->start + key->nfra;
+
+ /* clean all final and composite in intersection of seq and seq_changed */
+ if (key->type & invalidate_composite && key_cfra >= range_start && key_cfra <= range_end) {
+ if (key->link_next || key->link_prev) {
+ seq_cache_relink_keys(key->link_next, key->link_prev);
+ }
+
+ BLI_ghash_remove(cache->hash, key, seq_cache_keyfree, seq_cache_valfree);
+ }
+
+ if (key->type & invalidate_source && key->seq == seq && key_cfra >= seq_changed->startdisp &&
+ key_cfra <= seq_changed->enddisp) {
if (key->link_next || key->link_prev) {
seq_cache_relink_keys(key->link_next, key->link_prev);
}
@@ -592,7 +623,6 @@ void BKE_sequencer_cache_put(
key->cache_owner = cache;
key->seq = seq;
key->context = *context;
- key->cfra = cfra;
key->nfra = cfra - seq->start;
key->type = type;
key->cost = cost;
@@ -634,7 +664,7 @@ void BKE_sequencer_cache_put(
void BKE_sequencer_cache_iterate(
struct Scene *scene,
void *userdata,
- bool callback(void *userdata, struct Sequence *seq, int cfra, int cache_type, float cost))
+ bool callback(void *userdata, struct Sequence *seq, int nfra, int cache_type, float cost))
{
SeqCache *cache = seq_cache_get_from_scene(scene);
if (!cache) {
@@ -650,7 +680,7 @@ void BKE_sequencer_cache_iterate(
SeqCacheKey *key = BLI_ghashIterator_getKey(&gh_iter);
BLI_ghashIterator_step(&gh_iter);
- interrupt = callback(userdata, key->seq, key->cfra, key->type, key->cost);
+ interrupt = callback(userdata, key->seq, key->nfra, key->type, key->cost);
}
cache->last_key = NULL;
diff --git a/source/blender/blenkernel/intern/sequencer.c b/source/blender/blenkernel/intern/sequencer.c
index 99536b979b6..827d7343aad 100644
--- a/source/blender/blenkernel/intern/sequencer.c
+++ b/source/blender/blenkernel/intern/sequencer.c
@@ -279,7 +279,7 @@ static void BKE_sequence_free_ex(Scene *scene,
*/
if (do_cache) {
if (scene) {
- BKE_sequence_invalidate_cache(scene, seq);
+ BKE_sequence_invalidate_cache_raw(scene, seq);
}
}
@@ -3546,7 +3546,7 @@ static ImBuf *seq_render_scene_strip(const SeqRenderData *context,
IB_rect,
draw_flags,
scene->r.alphamode,
- 0, /* no aa samples */
+ U.ogl_multisamples,
viewname,
context->gpu_offscreen,
err_out);
@@ -4307,7 +4307,8 @@ static void sequence_do_invalidate_dependent(Scene *scene, Sequence *seq, ListBa
}
if (BKE_sequence_check_depend(seq, cur)) {
- BKE_sequencer_cache_cleanup_sequence(scene, cur);
+ BKE_sequencer_cache_cleanup_sequence(
+ scene, cur, seq, SEQ_CACHE_STORE_COMPOSITE | SEQ_CACHE_STORE_FINAL_OUT);
}
if (cur->seqbase.first) {
@@ -4319,46 +4320,46 @@ static void sequence_do_invalidate_dependent(Scene *scene, Sequence *seq, ListBa
static void sequence_invalidate_cache(Scene *scene,
Sequence *seq,
bool invalidate_self,
- bool UNUSED(invalidate_preprocess))
+ int invalidate_types)
{
Editing *ed = scene->ed;
- /* invalidate cache for current sequence */
if (invalidate_self) {
- /* Animation structure holds some buffers inside,
- * so for proper cache invalidation we need to
- * re-open the animation.
- */
BKE_sequence_free_anim(seq);
- BKE_sequencer_cache_cleanup_sequence(scene, seq);
+ BKE_sequencer_cache_cleanup_sequence(scene, seq, seq, invalidate_types);
}
- /* if invalidation is invoked from sequence free routine, effectdata would be NULL here */
if (seq->effectdata && seq->type == SEQ_TYPE_SPEED) {
BKE_sequence_effect_speed_rebuild_map(scene, seq, true);
}
- /* invalidate cache for all dependent sequences */
-
- /* NOTE: can not use SEQ_BEGIN/SEQ_END here because that macro will change sequence's depth,
- * which makes transformation routines work incorrect
- */
sequence_do_invalidate_dependent(scene, seq, &ed->seqbase);
}
-void BKE_sequence_invalidate_cache(Scene *scene, Sequence *seq)
+void BKE_sequence_invalidate_cache_raw(Scene *scene, Sequence *seq)
{
- sequence_invalidate_cache(scene, seq, true, true);
+ sequence_invalidate_cache(scene, seq, true, SEQ_CACHE_ALL_TYPES);
}
-void BKE_sequence_invalidate_dependent(Scene *scene, Sequence *seq)
+void BKE_sequence_invalidate_cache_preprocessed(Scene *scene, Sequence *seq)
{
- sequence_invalidate_cache(scene, seq, false, true);
+ sequence_invalidate_cache(scene,
+ seq,
+ true,
+ SEQ_CACHE_STORE_PREPROCESSED | SEQ_CACHE_STORE_COMPOSITE |
+ SEQ_CACHE_STORE_FINAL_OUT);
}
-void BKE_sequence_invalidate_cache_for_modifier(Scene *scene, Sequence *seq)
+void BKE_sequence_invalidate_cache_composite(Scene *scene, Sequence *seq)
{
- sequence_invalidate_cache(scene, seq, true, false);
+ sequence_invalidate_cache(
+ scene, seq, true, SEQ_CACHE_STORE_COMPOSITE | SEQ_CACHE_STORE_FINAL_OUT);
+}
+
+void BKE_sequence_invalidate_dependent(Scene *scene, Sequence *seq)
+{
+ sequence_invalidate_cache(
+ scene, seq, false, SEQ_CACHE_STORE_COMPOSITE | SEQ_CACHE_STORE_FINAL_OUT);
}
void BKE_sequencer_free_imbuf(Scene *scene, ListBase *seqbase, bool for_render)
@@ -4932,7 +4933,7 @@ void BKE_sequencer_update_sound_bounds_all(Scene *scene)
void BKE_sequencer_update_sound_bounds(Scene *scene, Sequence *seq)
{
if (seq->type == SEQ_TYPE_SCENE) {
- if (seq->scene_sound) {
+ if (seq->scene && seq->scene_sound) {
/* We have to take into account start frame of the sequence's scene! */
int startofs = seq->startofs + seq->anim_startofs + seq->scene->r.sfra;
@@ -5352,6 +5353,15 @@ static void seq_load_apply(Main *bmain, Scene *scene, Sequence *seq, SeqLoadInfo
}
}
+static Strip *seq_strip_alloc(void)
+{
+ Strip *strip = MEM_callocN(sizeof(Strip), "strip");
+ strip->transform = MEM_callocN(sizeof(struct StripTransform), "StripTransform");
+ strip->crop = MEM_callocN(sizeof(struct StripCrop), "StripCrop");
+
+ return strip;
+}
+
Sequence *BKE_sequence_alloc(ListBase *lb, int cfra, int machine)
{
Sequence *seq;
@@ -5460,7 +5470,7 @@ Sequence *BKE_sequencer_add_image_strip(bContext *C, ListBase *seqbasep, SeqLoad
seq->blend_mode = SEQ_TYPE_ALPHAOVER;
/* basic defaults */
- seq->strip = strip = MEM_callocN(sizeof(Strip), "strip");
+ seq->strip = strip = seq_strip_alloc();
seq->len = seq_load->len ? seq_load->len : 1;
strip->us = 1;
@@ -5515,7 +5525,7 @@ Sequence *BKE_sequencer_add_sound_strip(bContext *C, ListBase *seqbasep, SeqLoad
BKE_sequence_base_unique_name_recursive(&scene->ed->seqbase, seq);
/* basic defaults */
- seq->strip = strip = MEM_callocN(sizeof(Strip), "strip");
+ seq->strip = strip = seq_strip_alloc();
/* We add a very small negative offset here, because
* ceil(132.0) == 133.0, not nice with videos, see T47135. */
seq->len = (int)ceil((double)info.length * FPS - 1e-4);
@@ -5647,7 +5657,7 @@ Sequence *BKE_sequencer_add_movie_strip(bContext *C, ListBase *seqbasep, SeqLoad
}
/* basic defaults */
- seq->strip = strip = MEM_callocN(sizeof(Strip), "strip");
+ seq->strip = strip = seq_strip_alloc();
seq->len = IMB_anim_get_duration(anim_arr[0], IMB_TC_RECORD_RUN);
strip->us = 1;
@@ -5668,12 +5678,12 @@ Sequence *BKE_sequencer_add_movie_strip(bContext *C, ListBase *seqbasep, SeqLoad
if (seq_load->flag & SEQ_LOAD_MOVIE_SOUND) {
int start_frame_back = seq_load->start_frame;
- seq_load->channel++;
+ seq_load->channel--;
seq_load->seq_sound = BKE_sequencer_add_sound_strip(C, seqbasep, seq_load);
seq_load->start_frame = start_frame_back;
- seq_load->channel--;
+ seq_load->channel++;
}
/* can be NULL */
diff --git a/source/blender/blenkernel/intern/studiolight.c b/source/blender/blenkernel/intern/studiolight.c
index e0ff5fcccca..20f2a9be53b 100644
--- a/source/blender/blenkernel/intern/studiolight.c
+++ b/source/blender/blenkernel/intern/studiolight.c
@@ -1246,6 +1246,59 @@ static void studiolight_irradiance_preview(uint *icon_buffer, StudioLight *sl)
ITER_PIXELS_END;
}
+void BKE_studiolight_default(SolidLight lights[4], float light_ambient[4])
+{
+ copy_v3_fl3(light_ambient, 0.0, 0.0, 0.0);
+
+ lights[0].flag = 1;
+ lights[0].smooth = 0.526620f;
+ lights[0].col[0] = 0.033103f;
+ lights[0].col[1] = 0.033103f;
+ lights[0].col[2] = 0.033103f;
+ lights[0].spec[0] = 0.266761f;
+ lights[0].spec[1] = 0.266761f;
+ lights[0].spec[2] = 0.266761f;
+ lights[0].vec[0] = -0.352546f;
+ lights[0].vec[1] = 0.170931f;
+ lights[0].vec[2] = -0.920051f;
+
+ lights[1].flag = 1;
+ lights[1].smooth = 0.000000f;
+ lights[1].col[0] = 0.521083f;
+ lights[1].col[1] = 0.538226f;
+ lights[1].col[2] = 0.538226f;
+ lights[1].spec[0] = 0.599030f;
+ lights[1].spec[1] = 0.599030f;
+ lights[1].spec[2] = 0.599030f;
+ lights[1].vec[0] = -0.408163f;
+ lights[1].vec[1] = 0.346939f;
+ lights[1].vec[2] = 0.844415f;
+
+ lights[2].flag = 1;
+ lights[2].smooth = 0.478261f;
+ lights[2].col[0] = 0.038403f;
+ lights[2].col[1] = 0.034357f;
+ lights[2].col[2] = 0.049530f;
+ lights[2].spec[0] = 0.106102f;
+ lights[2].spec[1] = 0.125981f;
+ lights[2].spec[2] = 0.158523f;
+ lights[2].vec[0] = 0.521739f;
+ lights[2].vec[1] = 0.826087f;
+ lights[2].vec[2] = 0.212999f;
+
+ lights[3].flag = 1;
+ lights[3].smooth = 0.200000f;
+ lights[3].col[0] = 0.090838f;
+ lights[3].col[1] = 0.082080f;
+ lights[3].col[2] = 0.072255f;
+ lights[3].spec[0] = 0.106535f;
+ lights[3].spec[1] = 0.084771f;
+ lights[3].spec[2] = 0.066080f;
+ lights[3].vec[0] = 0.624519f;
+ lights[3].vec[1] = -0.562067f;
+ lights[3].vec[2] = -0.542269f;
+}
+
/* API */
void BKE_studiolight_init(void)
{
@@ -1255,32 +1308,6 @@ void BKE_studiolight_init(void)
STUDIOLIGHT_TYPE_STUDIO);
BLI_strncpy(sl->name, "Default", FILE_MAXFILE);
- copy_v3_fl3(sl->light_ambient, 0.025000, 0.025000, 0.025000);
-
- copy_v4_fl4(sl->light[0].vec, -0.580952, 0.228571, 0.781185, 0.0);
- copy_v4_fl4(sl->light[0].col, 0.900000, 0.900000, 0.900000, 1.000000);
- copy_v4_fl4(sl->light[0].spec, 0.318547, 0.318547, 0.318547, 1.000000);
- sl->light[0].flag = 1;
- sl->light[0].smooth = 0.1;
-
- copy_v4_fl4(sl->light[1].vec, 0.788218, 0.593482, -0.162765, 0.0);
- copy_v4_fl4(sl->light[1].col, 0.267115, 0.269928, 0.358840, 1.000000);
- copy_v4_fl4(sl->light[1].spec, 0.090838, 0.090838, 0.090838, 1.000000);
- sl->light[1].flag = 1;
- sl->light[1].smooth = 0.25;
-
- copy_v4_fl4(sl->light[2].vec, 0.696472, -0.696472, -0.172785, 0.0);
- copy_v4_fl4(sl->light[2].col, 0.293216, 0.304662, 0.401968, 1.000000);
- copy_v4_fl4(sl->light[2].spec, 0.069399, 0.020331, 0.020331, 1.000000);
- sl->light[2].flag = 1;
- sl->light[2].smooth = 0.5;
-
- copy_v4_fl4(sl->light[3].vec, 0.021053, -0.989474, 0.143173, 0.0);
- copy_v4_fl4(sl->light[3].col, 0.0, 0.0, 0.0, 1.0);
- copy_v4_fl4(sl->light[3].spec, 0.072234, 0.082253, 0.162642, 1.000000);
- sl->light[3].flag = 1;
- sl->light[3].smooth = 0.7;
-
BLI_addtail(&studiolights, sl);
/* go over the preset folder and add a studiolight for every image with its path */
@@ -1307,6 +1334,8 @@ void BKE_studiolight_init(void)
/* sort studio lights on filename. */
BLI_listbase_sort(&studiolights, studiolight_cmp);
+
+ BKE_studiolight_default(sl->light, sl->light_ambient);
}
void BKE_studiolight_free(void)
diff --git a/source/blender/blenkernel/intern/undo_system.c b/source/blender/blenkernel/intern/undo_system.c
index d3e0ff56977..caf88eb0fff 100644
--- a/source/blender/blenkernel/intern/undo_system.c
+++ b/source/blender/blenkernel/intern/undo_system.c
@@ -29,6 +29,8 @@
#include "BLI_listbase.h"
#include "BLI_string.h"
+#include "BLT_translation.h"
+
#include "DNA_listBase.h"
#include "DNA_windowmanager_types.h"
@@ -337,7 +339,7 @@ static bool undosys_stack_push_main(UndoStack *ustack, const char *name, struct
void BKE_undosys_stack_init_from_main(UndoStack *ustack, struct Main *bmain)
{
UNDO_NESTED_ASSERT(false);
- undosys_stack_push_main(ustack, "original", bmain);
+ undosys_stack_push_main(ustack, IFACE_("Original"), bmain);
}
/* called after 'BKE_undosys_stack_init_from_main' */
@@ -345,7 +347,7 @@ void BKE_undosys_stack_init_from_context(UndoStack *ustack, bContext *C)
{
const UndoType *ut = BKE_undosys_type_from_context(C);
if ((ut != NULL) && (ut != BKE_UNDOSYS_TYPE_MEMFILE)) {
- BKE_undosys_step_push_with_type(ustack, C, "original mode", ut);
+ BKE_undosys_step_push_with_type(ustack, C, IFACE_("Original Mode"), ut);
}
}
diff --git a/source/blender/blenlib/BLI_buffer.h b/source/blender/blenlib/BLI_buffer.h
index 9f3644ed45a..6fe1e9bb693 100644
--- a/source/blender/blenlib/BLI_buffer.h
+++ b/source/blender/blenlib/BLI_buffer.h
@@ -21,7 +21,7 @@
* \ingroup bli
*/
-typedef struct {
+typedef struct BLI_Buffer {
void *data;
const size_t elem_size;
size_t count, alloc_count;
diff --git a/source/blender/blenlib/BLI_callbacks.h b/source/blender/blenlib/BLI_callbacks.h
index ed8af49d640..4d9fc66a806 100644
--- a/source/blender/blenlib/BLI_callbacks.h
+++ b/source/blender/blenlib/BLI_callbacks.h
@@ -52,6 +52,7 @@ typedef enum {
BLI_CB_EVT_DEPSGRAPH_UPDATE_PRE,
BLI_CB_EVT_DEPSGRAPH_UPDATE_POST,
BLI_CB_EVT_VERSION_UPDATE,
+ BLI_CB_EVT_LOAD_FACTORY_USERDEF_POST,
BLI_CB_EVT_LOAD_FACTORY_STARTUP_POST,
BLI_CB_EVT_TOT,
} eCbEvent;
diff --git a/source/blender/blenlib/BLI_memblock.h b/source/blender/blenlib/BLI_memblock.h
index 81dd2100362..c5ef26ffb91 100644
--- a/source/blender/blenlib/BLI_memblock.h
+++ b/source/blender/blenlib/BLI_memblock.h
@@ -35,16 +35,19 @@ struct BLI_memblock;
typedef struct BLI_memblock BLI_memblock;
typedef void (*MemblockValFreeFP)(void *val);
-BLI_memblock *BLI_memblock_create(uint elem_size,
- const bool clear_alloc) ATTR_MALLOC ATTR_WARN_UNUSED_RESULT;
+BLI_memblock *BLI_memblock_create(uint elem_size) ATTR_MALLOC ATTR_WARN_UNUSED_RESULT;
void *BLI_memblock_alloc(BLI_memblock *mblk) ATTR_MALLOC ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1);
void BLI_memblock_clear(BLI_memblock *mblk, MemblockValFreeFP valfreefp) ATTR_NONNULL(1);
void BLI_memblock_destroy(BLI_memblock *mblk, MemblockValFreeFP free_callback) ATTR_NONNULL(1);
typedef struct BLI_memblock_iter {
- BLI_memblock *mblk;
- int current_index;
- int elem_per_chunk;
+ void **chunk_list;
+ int cur_index;
+ int end_index;
+ int chunk_max_ofs;
+ int chunk_idx;
+ int elem_size;
+ int elem_ofs;
} BLI_memblock_iter;
void BLI_memblock_iternew(BLI_memblock *pool, BLI_memblock_iter *iter) ATTR_NONNULL();
diff --git a/source/blender/blenlib/BLI_rect.h b/source/blender/blenlib/BLI_rect.h
index f23580916b1..e3cd70f7413 100644
--- a/source/blender/blenlib/BLI_rect.h
+++ b/source/blender/blenlib/BLI_rect.h
@@ -62,6 +62,10 @@ void BLI_rcti_resize(struct rcti *rect, int x, int y);
void BLI_rctf_resize(struct rctf *rect, float x, float y);
void BLI_rcti_scale(rcti *rect, const float scale);
void BLI_rctf_scale(rctf *rect, const float scale);
+void BLI_rctf_pad_y(struct rctf *rect,
+ const float boundary_size,
+ const float pad_min,
+ const float pad_max);
void BLI_rctf_interp(struct rctf *rect,
const struct rctf *rect_a,
const struct rctf *rect_b,
diff --git a/source/blender/blenlib/intern/BLI_memarena.c b/source/blender/blenlib/intern/BLI_memarena.c
index 0f7ac92a348..b20a0eafd74 100644
--- a/source/blender/blenlib/intern/BLI_memarena.c
+++ b/source/blender/blenlib/intern/BLI_memarena.c
@@ -53,8 +53,9 @@
#if defined(__SANITIZE_ADDRESS__) || __has_feature(address_sanitizer)
# include "sanitizer/asan_interface.h"
#else
-# define ASAN_POISON_MEMORY_REGION(addr, size) UNUSED_VARS(addr, size)
-# define ASAN_UNPOISON_MEMORY_REGION(addr, size) UNUSED_VARS(addr, size)
+/* Ensure return value is used. */
+# define ASAN_POISON_MEMORY_REGION(addr, size) (void)(0 && ((size) != 0 && (addr) != NULL))
+# define ASAN_UNPOISON_MEMORY_REGION(addr, size) (void)(0 && ((size) != 0 && (addr) != NULL))
#endif
struct MemBuf {
diff --git a/source/blender/blenlib/intern/BLI_memblock.c b/source/blender/blenlib/intern/BLI_memblock.c
index 50b1e14757c..ec9b74f2b50 100644
--- a/source/blender/blenlib/intern/BLI_memblock.c
+++ b/source/blender/blenlib/intern/BLI_memblock.c
@@ -49,18 +49,19 @@ struct BLI_memblock {
int elem_next;
/** Last "touched" element. */
int elem_last;
+ /** Offset in a chunk of the next elem. */
+ int elem_next_ofs;
+ /** Max offset in a chunk. */
+ int chunk_max_ofs;
+ /** Id of the chunk used for the next allocation. */
+ int chunk_next;
/** Chunck size in bytes. */
int chunk_size;
/** Number of allocated chunck. */
int chunk_len;
- /** Clear newly allocated chuncks. */
- bool clear_alloc;
};
-/**
- * /clear_alloc will clear the memory the first time a chunck is allocated.
- */
-BLI_memblock *BLI_memblock_create(uint elem_size, const bool clear_alloc)
+BLI_memblock *BLI_memblock_create(uint elem_size)
{
BLI_assert(elem_size < BLI_MEM_BLOCK_CHUNK_SIZE);
@@ -71,22 +72,16 @@ BLI_memblock *BLI_memblock_create(uint elem_size, const bool clear_alloc)
mblk->chunk_size = BLI_MEM_BLOCK_CHUNK_SIZE;
mblk->chunk_len = CHUNK_LIST_SIZE;
mblk->chunk_list = MEM_callocN(sizeof(void *) * (uint)mblk->chunk_len, "chunk list");
- mblk->clear_alloc = clear_alloc;
+ mblk->chunk_list[0] = MEM_callocN((uint)mblk->chunk_size, "BLI_memblock chunk");
+ mblk->chunk_max_ofs = (mblk->chunk_size / mblk->elem_size) * mblk->elem_size;
+ mblk->elem_next_ofs = 0;
+ mblk->chunk_next = 0;
return mblk;
}
void BLI_memblock_destroy(BLI_memblock *mblk, MemblockValFreeFP free_callback)
{
- if (free_callback) {
- int elem_per_chunk = mblk->chunk_size / mblk->elem_size;
-
- for (int i = mblk->elem_last; i >= 0; i--) {
- int chunk_idx = i / elem_per_chunk;
- int elem_idx = i - elem_per_chunk * chunk_idx;
- void *val = (char *)(mblk->chunk_list[chunk_idx]) + mblk->elem_size * elem_idx;
- free_callback(val);
- }
- }
+ BLI_memblock_clear(mblk, free_callback);
for (int i = 0; i < mblk->chunk_len; i++) {
MEM_SAFE_FREE(mblk->chunk_list[i]);
@@ -100,7 +95,7 @@ void BLI_memblock_destroy(BLI_memblock *mblk, MemblockValFreeFP free_callback)
void BLI_memblock_clear(BLI_memblock *mblk, MemblockValFreeFP free_callback)
{
int elem_per_chunk = mblk->chunk_size / mblk->elem_size;
- int last_used_chunk = (mblk->elem_next - 1) / elem_per_chunk;
+ int last_used_chunk = mblk->elem_next / elem_per_chunk;
if (free_callback) {
for (int i = mblk->elem_last; i >= mblk->elem_next; i--) {
@@ -122,53 +117,66 @@ void BLI_memblock_clear(BLI_memblock *mblk, MemblockValFreeFP free_callback)
mblk->elem_last = mblk->elem_next - 1;
mblk->elem_next = 0;
+ mblk->elem_next_ofs = 0;
+ mblk->chunk_next = 0;
}
void *BLI_memblock_alloc(BLI_memblock *mblk)
{
- int elem_per_chunk = mblk->chunk_size / mblk->elem_size;
- int chunk_idx = mblk->elem_next / elem_per_chunk;
- int elem_idx = mblk->elem_next - elem_per_chunk * chunk_idx;
-
+ /* Bookeeping. */
if (mblk->elem_last < mblk->elem_next) {
mblk->elem_last = mblk->elem_next;
}
-
mblk->elem_next++;
- if (UNLIKELY(chunk_idx >= mblk->chunk_len)) {
- mblk->chunk_len += CHUNK_LIST_SIZE;
- mblk->chunk_list = MEM_recallocN(mblk->chunk_list, sizeof(void *) * (uint)mblk->chunk_len);
- }
+ void *ptr = (char *)(mblk->chunk_list[mblk->chunk_next]) + mblk->elem_next_ofs;
+
+ mblk->elem_next_ofs += mblk->elem_size;
+
+ if (mblk->elem_next_ofs == mblk->chunk_max_ofs) {
+ mblk->elem_next_ofs = 0;
+ mblk->chunk_next++;
- if (UNLIKELY(mblk->chunk_list[chunk_idx] == NULL)) {
- if (mblk->clear_alloc) {
- mblk->chunk_list[chunk_idx] = MEM_callocN((uint)mblk->chunk_size, "BLI_memblock chunk");
+ if (UNLIKELY(mblk->chunk_next >= mblk->chunk_len)) {
+ mblk->chunk_len += CHUNK_LIST_SIZE;
+ mblk->chunk_list = MEM_recallocN(mblk->chunk_list, sizeof(void *) * (uint)mblk->chunk_len);
}
- else {
- mblk->chunk_list[chunk_idx] = MEM_mallocN((uint)mblk->chunk_size, "BLI_memblock chunk");
+
+ if (UNLIKELY(mblk->chunk_list[mblk->chunk_next] == NULL)) {
+ mblk->chunk_list[mblk->chunk_next] = MEM_callocN((uint)mblk->chunk_size,
+ "BLI_memblock chunk");
}
}
-
- return (char *)(mblk->chunk_list[chunk_idx]) + mblk->elem_size * elem_idx;
+ return ptr;
}
void BLI_memblock_iternew(BLI_memblock *mblk, BLI_memblock_iter *iter)
{
- iter->mblk = mblk;
- iter->current_index = 0;
- iter->elem_per_chunk = mblk->chunk_size / mblk->elem_size;
+ /* Small copy of the memblock used for better cache coherence. */
+ iter->chunk_list = mblk->chunk_list;
+ iter->end_index = mblk->elem_next;
+ iter->cur_index = 0;
+ iter->chunk_idx = 0;
+ iter->elem_ofs = 0;
+ iter->elem_size = mblk->elem_size;
+ iter->chunk_max_ofs = mblk->chunk_max_ofs;
}
void *BLI_memblock_iterstep(BLI_memblock_iter *iter)
{
- if (iter->current_index >= iter->mblk->elem_next) {
+ if (iter->cur_index == iter->end_index) {
return NULL;
}
- int chunk_idx = iter->current_index / iter->elem_per_chunk;
- int elem_idx = iter->current_index - iter->elem_per_chunk * chunk_idx;
- iter->current_index++;
+ iter->cur_index++;
+
+ void *ptr = (char *)(iter->chunk_list[iter->chunk_idx]) + iter->elem_ofs;
- return (char *)(iter->mblk->chunk_list[chunk_idx]) + iter->mblk->elem_size * elem_idx;
+ iter->elem_ofs += iter->elem_size;
+
+ if (iter->elem_ofs == iter->chunk_max_ofs) {
+ iter->elem_ofs = 0;
+ iter->chunk_idx++;
+ }
+ return ptr;
}
diff --git a/source/blender/blenlib/intern/BLI_memiter.c b/source/blender/blenlib/intern/BLI_memiter.c
index c7df7d5fdd4..4027a62bbcc 100644
--- a/source/blender/blenlib/intern/BLI_memiter.c
+++ b/source/blender/blenlib/intern/BLI_memiter.c
@@ -57,8 +57,9 @@
#if defined(__SANITIZE_ADDRESS__) || __has_feature(address_sanitizer)
# include "sanitizer/asan_interface.h"
#else
-# define ASAN_POISON_MEMORY_REGION(addr, size) UNUSED_VARS(addr, size)
-# define ASAN_UNPOISON_MEMORY_REGION(addr, size) UNUSED_VARS(addr, size)
+/* Ensure return value is used. */
+# define ASAN_POISON_MEMORY_REGION(addr, size) (void)(0 && ((size) != 0 && (addr) != NULL))
+# define ASAN_UNPOISON_MEMORY_REGION(addr, size) (void)(0 && ((size) != 0 && (addr) != NULL))
#endif
typedef uintptr_t data_t;
@@ -239,6 +240,10 @@ static void memiter_free_data(BLI_memiter *mi)
BLI_memiter_chunk *chunk = mi->head;
while (chunk) {
BLI_memiter_chunk *chunk_next = chunk->next;
+
+ /* Unpoison memory because MEM_freeN might overwrite it. */
+ ASAN_UNPOISON_MEMORY_REGION(chunk, MEM_allocN_len(chunk));
+
MEM_freeN(chunk);
chunk = chunk_next;
}
diff --git a/source/blender/blenlib/intern/path_util.c b/source/blender/blenlib/intern/path_util.c
index 3bb60a20fc8..61b773f6016 100644
--- a/source/blender/blenlib/intern/path_util.c
+++ b/source/blender/blenlib/intern/path_util.c
@@ -1855,7 +1855,10 @@ const char *BLI_path_basename(const char *path)
*
* Ignores multiple slashes at any point in the path (including start/end).
*/
-bool BLI_path_name_at_index(const char *path, const int index, int *r_offset, int *r_len)
+bool BLI_path_name_at_index(const char *__restrict path,
+ const int index,
+ int *__restrict r_offset,
+ int *__restrict r_len)
{
if (index >= 0) {
int index_step = 0;
diff --git a/source/blender/blenlib/intern/rct.c b/source/blender/blenlib/intern/rct.c
index 5000b3df92b..99288abb38c 100644
--- a/source/blender/blenlib/intern/rct.c
+++ b/source/blender/blenlib/intern/rct.c
@@ -643,6 +643,25 @@ void BLI_rctf_scale(rctf *rect, const float scale)
rect->ymax = cent_y + size_y_half;
}
+void BLI_rctf_pad_y(rctf *rect,
+ const float boundary_size,
+ const float pad_min,
+ const float pad_max)
+{
+ BLI_assert(pad_max >= 0.0f);
+ BLI_assert(pad_min >= 0.0f);
+ BLI_assert(boundary_size > 0.0f);
+
+ float total_pad = pad_max + pad_min;
+ if (total_pad == 0.0f) {
+ return;
+ }
+
+ float total_extend = BLI_rctf_size_y(rect) * total_pad / (boundary_size - total_pad);
+ rect->ymax += total_extend * (pad_max / total_pad);
+ rect->ymin -= total_extend * (pad_min / total_pad);
+}
+
void BLI_rctf_interp(rctf *rect, const rctf *rect_a, const rctf *rect_b, const float fac)
{
const float ifac = 1.0f - fac;
diff --git a/source/blender/blenlib/intern/system.c b/source/blender/blenlib/intern/system.c
index 3348912f02a..88f2e2625e8 100644
--- a/source/blender/blenlib/intern/system.c
+++ b/source/blender/blenlib/intern/system.c
@@ -33,7 +33,10 @@
#if defined(WIN32)
# include <intrin.h>
# include <windows.h>
+# pragma warning(push)
+# pragma warning(disable : 4091)
# include <dbghelp.h>
+# pragma warning(pop)
#else
# include <execinfo.h>
# include <unistd.h>
@@ -122,7 +125,7 @@ void BLI_system_backtrace(FILE *fp)
for (i = 0; i < nframes; i++) {
SymFromAddr(process, (DWORD64)(stack[i]), 0, symbolinfo);
- fprintf(fp, "%u: %s - 0x%0X\n", nframes - i - 1, symbolinfo->Name, symbolinfo->Address);
+ fprintf(fp, "%u: %s - 0x%0llX\n", nframes - i - 1, symbolinfo->Name, symbolinfo->Address);
}
MEM_freeN(symbolinfo);
diff --git a/source/blender/blenlib/intern/task.c b/source/blender/blenlib/intern/task.c
index 6f9ff02ce17..85d39f2f98e 100644
--- a/source/blender/blenlib/intern/task.c
+++ b/source/blender/blenlib/intern/task.c
@@ -211,6 +211,10 @@ struct TaskScheduler {
ThreadMutex queue_mutex;
ThreadCondition queue_cond;
+ ThreadMutex startup_mutex;
+ ThreadCondition startup_cond;
+ volatile int num_thread_started;
+
volatile bool do_exit;
/* NOTE: In pthread's TLS we store the whole TaskThread structure. */
@@ -429,6 +433,14 @@ static void *task_scheduler_thread_run(void *thread_p)
pthread_setspecific(scheduler->tls_id_key, thread);
+ /* signal the main thread when all threads have started */
+ BLI_mutex_lock(&scheduler->startup_mutex);
+ scheduler->num_thread_started++;
+ if (scheduler->num_thread_started == scheduler->num_threads) {
+ BLI_condition_notify_one(&scheduler->startup_cond);
+ }
+ BLI_mutex_unlock(&scheduler->startup_mutex);
+
/* keep popping off tasks */
while (task_scheduler_thread_wait_pop(scheduler, &task)) {
TaskPool *pool = task->pool;
@@ -463,6 +475,10 @@ TaskScheduler *BLI_task_scheduler_create(int num_threads)
BLI_mutex_init(&scheduler->queue_mutex);
BLI_condition_init(&scheduler->queue_cond);
+ BLI_mutex_init(&scheduler->startup_mutex);
+ BLI_condition_init(&scheduler->startup_cond);
+ scheduler->num_thread_started = 0;
+
if (num_threads == 0) {
/* automatic number of threads will be main thread + num cores */
num_threads = BLI_system_thread_count();
@@ -504,6 +520,17 @@ TaskScheduler *BLI_task_scheduler_create(int num_threads)
}
}
+ /* Wait for all worker threads to start before returning to caller to prevent the case where
+ * threads are still starting and pthread_join is called, which causes a deadlock on pthreads4w.
+ */
+ BLI_mutex_lock(&scheduler->startup_mutex);
+ /* NOTE: Use loop here to avoid false-positive everything-is-ready caused by spontaneous thread
+ * wake up. */
+ while (scheduler->num_thread_started != num_threads) {
+ BLI_condition_wait(&scheduler->startup_cond, &scheduler->startup_mutex);
+ }
+ BLI_mutex_unlock(&scheduler->startup_mutex);
+
return scheduler;
}
@@ -551,6 +578,8 @@ void BLI_task_scheduler_free(TaskScheduler *scheduler)
/* delete mutex/condition */
BLI_mutex_end(&scheduler->queue_mutex);
BLI_condition_end(&scheduler->queue_cond);
+ BLI_mutex_end(&scheduler->startup_mutex);
+ BLI_condition_end(&scheduler->startup_cond);
MEM_freeN(scheduler);
}
diff --git a/source/blender/blenloader/intern/readfile.c b/source/blender/blenloader/intern/readfile.c
index 0d81c55b0f2..b32745e41ee 100644
--- a/source/blender/blenloader/intern/readfile.c
+++ b/source/blender/blenloader/intern/readfile.c
@@ -325,8 +325,8 @@ typedef struct OldNewMap {
int capacity_exp;
} OldNewMap;
-#define ENTRIES_CAPACITY(onm) (1 << (onm)->capacity_exp)
-#define MAP_CAPACITY(onm) (1 << ((onm)->capacity_exp + 1))
+#define ENTRIES_CAPACITY(onm) (1ll << (onm)->capacity_exp)
+#define MAP_CAPACITY(onm) (1ll << ((onm)->capacity_exp + 1))
#define SLOT_MASK(onm) (MAP_CAPACITY(onm) - 1)
#define DEFAULT_SIZE_EXP 6
#define PERTURB_SHIFT 5
@@ -4119,8 +4119,6 @@ static void direct_link_world(FileData *fd, World *wrld)
BLI_listbase_clear(&wrld->gpumaterial);
}
-/* ************ READ VFONT ***************** */
-
/** \} */
/* -------------------------------------------------------------------- */
@@ -6229,20 +6227,11 @@ static void lib_link_collection_data(FileData *fd, Library *lib, Collection *col
}
}
- for (CollectionChild *child = collection->children.first, *child_next = NULL; child;
- child = child_next) {
- child_next = child->next;
+ for (CollectionChild *child = collection->children.first; child != NULL; child = child->next) {
child->collection = newlibadr_us(fd, lib, child->collection);
-
- if (child->collection == NULL || BKE_collection_find_cycle(collection, child->collection)) {
- BLI_freelinkN(&collection->children, child);
- }
- else {
- CollectionParent *cparent = MEM_callocN(sizeof(CollectionParent), "CollectionParent");
- cparent->collection = collection;
- BLI_addtail(&child->collection->parents, cparent);
- }
}
+
+ BKE_collection_parent_relations_rebuild(collection);
}
static void lib_link_collection(FileData *fd, Main *main)
@@ -8697,8 +8686,6 @@ static void lib_link_mask(FileData *fd, Main *main)
}
}
-/* ************ READ LINE STYLE ***************** */
-
/** \} */
/* -------------------------------------------------------------------- */
@@ -8957,8 +8944,6 @@ static void direct_link_linestyle(FileData *fd, FreestyleLineStyle *linestyle)
}
}
-/* ************** GENERAL & MAIN ******************** */
-
/** \} */
/* -------------------------------------------------------------------- */
@@ -9540,6 +9525,19 @@ static void lib_link_all(FileData *fd, Main *main)
/* We could integrate that to mesh/curve/lattice lib_link, but this is really cheap process,
* so simpler to just use it directly in this single call. */
BLO_main_validate_shapekeys(main, NULL);
+
+ if (fd->memfile != NULL) {
+ /* When doing redo, we perform a tremendous amount of esoterics magic tricks to avoid having to
+ * re-read all library datablocks.
+ * Unfortunately, that means that we do not clear Collections' parents lists, which then get
+ * improperly extended in some cases by lib_link_scene() and lib_link_collection() calls above
+ * (when ome local collection is parent of linked ones).
+ * I do not really see a way to address that issue, besides brute force call below which
+ * invalidates and re-creates all parenting relationships between collections. Yet another
+ * example of why it is such a bad idea to keep that kind of double-linked relationships info
+ * 'permanently' in our data structures... */
+ BKE_main_collections_parent_relations_rebuild(main);
+ }
}
/** \} */
@@ -10812,6 +10810,15 @@ static void expand_camera(FileData *fd, Main *mainvar, Camera *ca)
{
expand_doit(fd, mainvar, ca->ipo); // XXX deprecated - old animation system
+ for (CameraBGImage *bgpic = ca->bg_images.first; bgpic; bgpic = bgpic->next) {
+ if (bgpic->source == CAM_BGIMG_SOURCE_IMAGE) {
+ expand_doit(fd, mainvar, bgpic->ima);
+ }
+ else if (bgpic->source == CAM_BGIMG_SOURCE_MOVIE) {
+ expand_doit(fd, mainvar, bgpic->ima);
+ }
+ }
+
if (ca->adt) {
expand_animdata(fd, mainvar, ca->adt);
}
diff --git a/source/blender/blenloader/intern/versioning_260.c b/source/blender/blenloader/intern/versioning_260.c
index 77ef27182f2..7b0aab99aea 100644
--- a/source/blender/blenloader/intern/versioning_260.c
+++ b/source/blender/blenloader/intern/versioning_260.c
@@ -1808,6 +1808,7 @@ void blo_do_versions_260(FileData *fd, Library *UNUSED(lib), Main *bmain)
Image *image = blo_do_versions_newlibadr(fd, tex->id.lib, tex->ima);
if (image && (image->flag & IMA_DO_PREMUL) == 0) {
+ const int IMA_IGNORE_ALPHA = (1 << 12);
image->flag |= IMA_IGNORE_ALPHA;
}
}
diff --git a/source/blender/blenloader/intern/versioning_280.c b/source/blender/blenloader/intern/versioning_280.c
index 6d5508fd7bd..71f67092fa7 100644
--- a/source/blender/blenloader/intern/versioning_280.c
+++ b/source/blender/blenloader/intern/versioning_280.c
@@ -715,6 +715,23 @@ static void do_version_constraints_copy_scale_power(ListBase *lb)
}
}
+static void do_versions_seq_alloc_transform_and_crop(ListBase *seqbase)
+{
+ for (Sequence *seq = seqbase->first; seq != NULL; seq = seq->next) {
+ if (seq->strip->transform == NULL) {
+ seq->strip->transform = MEM_callocN(sizeof(struct StripTransform), "StripTransform");
+ }
+
+ if (seq->strip->crop == NULL) {
+ seq->strip->crop = MEM_callocN(sizeof(struct StripCrop), "StripCrop");
+ }
+
+ if (seq->seqbase.first != NULL) {
+ do_versions_seq_alloc_transform_and_crop(&seq->seqbase);
+ }
+ }
+}
+
void do_versions_after_linking_280(Main *bmain)
{
bool use_collection_compat_28 = true;
@@ -2361,17 +2378,6 @@ void blo_do_versions_280(FileData *fd, Library *UNUSED(lib), Main *bmain)
for (SpaceLink *sl = sa->spacedata.first; sl; sl = sl->next) {
if (sl->spacetype == SPACE_VIEW3D) {
View3D *v3d = (View3D *)sl;
- v3d->shading.xray_alpha_wire = 0.5f;
- }
- }
- }
- }
-
- for (bScreen *screen = bmain->screens.first; screen; screen = screen->id.next) {
- for (ScrArea *sa = screen->areabase.first; sa; sa = sa->next) {
- for (SpaceLink *sl = sa->spacedata.first; sl; sl = sl->next) {
- if (sl->spacetype == SPACE_VIEW3D) {
- View3D *v3d = (View3D *)sl;
v3d->shading.flag |= V3D_SHADING_XRAY_BONE;
}
}
@@ -3476,6 +3482,51 @@ void blo_do_versions_280(FileData *fd, Library *UNUSED(lib), Main *bmain)
}
}
+ if (!MAIN_VERSION_ATLEAST(bmain, 280, 70)) {
+ /* New image alpha modes. */
+ LISTBASE_FOREACH (Image *, image, &bmain->images) {
+ const int IMA_IGNORE_ALPHA = (1 << 12);
+ if (image->flag & IMA_IGNORE_ALPHA) {
+ image->alpha_mode = IMA_ALPHA_IGNORE;
+ image->flag &= ~IMA_IGNORE_ALPHA;
+ }
+ }
+ }
+
+ if (!MAIN_VERSION_ATLEAST(bmain, 280, 71)) {
+ /* This assumes the Blender builtin config. Depending on the OCIO
+ * environment variable for versioning is weak, and these deprecated view
+ * transforms and look names don't seem to exist in other commonly used
+ * OCIO configs so .blend files created for those would be unaffected. */
+ for (Scene *scene = bmain->scenes.first; scene; scene = scene->id.next) {
+ ColorManagedViewSettings *view_settings;
+ view_settings = &scene->view_settings;
+
+ if (STREQ(view_settings->view_transform, "Default")) {
+ STRNCPY(view_settings->view_transform, "Standard");
+ }
+ else if (STREQ(view_settings->view_transform, "RRT") ||
+ STREQ(view_settings->view_transform, "Film")) {
+ STRNCPY(view_settings->view_transform, "Filmic");
+ }
+ else if (STREQ(view_settings->view_transform, "Log")) {
+ STRNCPY(view_settings->view_transform, "Filmic Log");
+ }
+
+ if (STREQ(view_settings->look, "Filmic - Base Contrast")) {
+ STRNCPY(view_settings->look, "None");
+ }
+ }
+ }
+
+ if (!MAIN_VERSION_ATLEAST(bmain, 280, 72)) {
+ for (Scene *scene = bmain->scenes.first; scene; scene = scene->id.next) {
+ if (scene->ed != NULL) {
+ do_versions_seq_alloc_transform_and_crop(&scene->ed->seqbase);
+ }
+ }
+ }
+
{
/* Versioning code until next subversion bump goes here. */
}
diff --git a/source/blender/blenloader/intern/versioning_cycles.c b/source/blender/blenloader/intern/versioning_cycles.c
index 93813df3c13..9bfbf4477ab 100644
--- a/source/blender/blenloader/intern/versioning_cycles.c
+++ b/source/blender/blenloader/intern/versioning_cycles.c
@@ -523,7 +523,7 @@ void do_versions_after_linking_cycles(Main *bmain)
}
/* No depth of field, set default settings. */
- camera->dof.aperture_fstop = 5.6f;
+ camera->dof.aperture_fstop = 2.8f;
camera->dof.aperture_blades = 0;
camera->dof.aperture_rotation = 0.0f;
camera->dof.aperture_ratio = 1.0f;
diff --git a/source/blender/blenloader/intern/versioning_defaults.c b/source/blender/blenloader/intern/versioning_defaults.c
index d13f976a759..d22620f9224 100644
--- a/source/blender/blenloader/intern/versioning_defaults.c
+++ b/source/blender/blenloader/intern/versioning_defaults.c
@@ -26,6 +26,7 @@
#include "BLI_string.h"
#include "BLI_system.h"
+#include "DNA_camera_types.h"
#include "DNA_gpencil_types.h"
#include "DNA_mesh_types.h"
#include "DNA_object_types.h"
@@ -48,6 +49,7 @@
#include "BKE_node.h"
#include "BKE_paint.h"
#include "BKE_screen.h"
+#include "BKE_studiolight.h"
#include "BKE_workspace.h"
#include "BLO_readfile.h"
@@ -94,6 +96,9 @@ void BLO_update_defaults_userpref_blend(void)
/* Leave temp directory empty, will then get appropriate value per OS. */
U.tempdir[0] = '\0';
+ /* System-specific fonts directory. */
+ BKE_appdir_font_folder_default(U.fontdir);
+
/* Only enable tooltips translation by default,
* without actually enabling translation itself, for now. */
U.transopts = USER_TR_TOOLTIPS;
@@ -110,6 +115,12 @@ void BLO_update_defaults_userpref_blend(void)
/* Default to left click select. */
BKE_keyconfig_pref_set_select_mouse(&U, 0, true);
+
+ /* Increase a little for new scrubbing area. */
+ U.v2d_min_gridsize = 45;
+
+ /* Default studio light. */
+ BKE_studiolight_default(U.light_param, U.light_ambient);
}
/**
@@ -155,9 +166,16 @@ void BLO_update_defaults_startup_blend(Main *bmain, const char *app_template)
for (bScreen *screen = bmain->screens.first; screen; screen = screen->id.next) {
for (ScrArea *sa = screen->areabase.first; sa; sa = sa->next) {
for (ARegion *ar = sa->regionbase.first; ar; ar = ar->next) {
- /* Remove all stored panels, we want to use defaults
- * (order, open/closed) as defined by UI code here! */
- BKE_area_region_panels_free(&ar->panels);
+ if (builtin_template) {
+ /* Remove all stored panels, we want to use defaults
+ * (order, open/closed) as defined by UI code here! */
+ BKE_area_region_panels_free(&ar->panels);
+ BLI_freelistN(&ar->panels_category_active);
+
+ /* Reset size so it uses consistent defaults from the region types. */
+ ar->sizex = 0;
+ ar->sizey = 0;
+ }
/* some toolbars have been saved as initialized,
* we don't want them to have odd zoom-level or scrolling set, see: T47047 */
@@ -173,9 +191,13 @@ void BLO_update_defaults_startup_blend(Main *bmain, const char *app_template)
v3d->overlay.texture_paint_mode_opacity = 1.0f;
v3d->overlay.weight_paint_mode_opacity = 1.0f;
v3d->overlay.vertex_paint_mode_opacity = 1.0f;
+ /* Use dimmed selected edges. */
+ v3d->overlay.edit_flag &= ~V3D_OVERLAY_EDIT_EDGES;
/* grease pencil settings */
v3d->vertex_opacity = 1.0f;
v3d->gp_flag |= V3D_GP_SHOW_EDIT_LINES;
+ /* Remove dither pattern in wireframe mode. */
+ v3d->shading.xray_alpha_wire = 0.0f;
/* Skip startups that use the viewport color by default. */
if (v3d->shading.background_type != V3D_SHADING_BACKGROUND_VIEWPORT) {
copy_v3_fl(v3d->shading.background_color, 0.05f);
@@ -363,8 +385,8 @@ void BLO_update_defaults_startup_blend(Main *bmain, const char *app_template)
scene->r.displaymode = R_OUTPUT_WINDOW;
if (app_template && STREQ(app_template, "Video_Editing")) {
- /* Filmic is too slow, use default until it is optimized. */
- STRNCPY(scene->view_settings.view_transform, "Default");
+ /* Filmic is too slow, use standard until it is optimized. */
+ STRNCPY(scene->view_settings.view_transform, "Standard");
STRNCPY(scene->view_settings.look, "None");
}
else {
@@ -398,6 +420,27 @@ void BLO_update_defaults_startup_blend(Main *bmain, const char *app_template)
/* Match default for new meshes. */
mesh->smoothresh = DEG2RADF(30);
}
+
+ for (Camera *camera = bmain->cameras.first; camera; camera = camera->id.next) {
+ /* Initialize to a useful value. */
+ camera->dof.focus_distance = 10.0f;
+ camera->dof.aperture_fstop = 2.8f;
+ }
+
+ for (Material *ma = bmain->materials.first; ma; ma = ma->id.next) {
+ /* Update default material to be a bit more rough. */
+ ma->roughness = 0.4f;
+
+ if (ma->nodetree) {
+ for (bNode *node = ma->nodetree->nodes.first; node; node = node->next) {
+ if (node->type == SH_NODE_BSDF_PRINCIPLED) {
+ bNodeSocket *roughness_socket = nodeFindSocket(node, SOCK_IN, "Roughness");
+ bNodeSocketValueFloat *roughness_data = roughness_socket->default_value;
+ roughness_data->value = 0.4f;
+ }
+ }
+ }
+ }
}
for (bScreen *sc = bmain->screens.first; sc; sc = sc->id.next) {
@@ -415,6 +458,9 @@ void BLO_update_defaults_startup_blend(Main *bmain, const char *app_template)
copy_v3_v3(scene->display.light_direction, (float[3]){M_SQRT1_3, M_SQRT1_3, M_SQRT1_3});
copy_v2_fl2(scene->safe_areas.title, 0.1f, 0.05f);
copy_v2_fl2(scene->safe_areas.action, 0.035f, 0.035f);
+
+ /* Change default cubemap quality. */
+ scene->eevee.gi_filter_quality = 3.0f;
}
if (app_template == NULL) {
diff --git a/source/blender/blenloader/intern/versioning_userdef.c b/source/blender/blenloader/intern/versioning_userdef.c
index d1cb9d32212..89f4d86b1b8 100644
--- a/source/blender/blenloader/intern/versioning_userdef.c
+++ b/source/blender/blenloader/intern/versioning_userdef.c
@@ -127,11 +127,11 @@ static void do_versions_theme(const UserDef *userdef, bTheme *btheme)
FROM_DEFAULT_V4_UCHAR(space_sequencer.text);
FROM_DEFAULT_V4_UCHAR(space_clip.text);
- FROM_DEFAULT_V4_UCHAR(space_graph.scrubbing_background);
- FROM_DEFAULT_V4_UCHAR(space_action.scrubbing_background);
- FROM_DEFAULT_V4_UCHAR(space_nla.scrubbing_background);
- FROM_DEFAULT_V4_UCHAR(space_sequencer.scrubbing_background);
- FROM_DEFAULT_V4_UCHAR(space_clip.scrubbing_background);
+ FROM_DEFAULT_V4_UCHAR(space_graph.time_scrub_background);
+ FROM_DEFAULT_V4_UCHAR(space_action.time_scrub_background);
+ FROM_DEFAULT_V4_UCHAR(space_nla.time_scrub_background);
+ FROM_DEFAULT_V4_UCHAR(space_sequencer.time_scrub_background);
+ FROM_DEFAULT_V4_UCHAR(space_clip.time_scrub_background);
}
if (!USER_VERSION_ATLEAST(280, 67)) {
diff --git a/source/blender/bmesh/intern/bmesh_operators.h b/source/blender/bmesh/intern/bmesh_operators.h
index 0279e4dd23e..78e8ce04115 100644
--- a/source/blender/bmesh/intern/bmesh_operators.h
+++ b/source/blender/bmesh/intern/bmesh_operators.h
@@ -126,6 +126,13 @@ enum {
BEVEL_MITER_ARC,
};
+/* Normal Face Strength values */
+enum {
+ FACE_STRENGTH_WEAK = -16384,
+ FACE_STRENGTH_MEDIUM = 0,
+ FACE_STRENGTH_STRONG = 16384,
+};
+
extern const BMOpDefine *bmo_opdefines[];
extern const int bmo_opdefines_total;
diff --git a/source/blender/bmesh/tools/bmesh_bevel.c b/source/blender/bmesh/tools/bmesh_bevel.c
index a559d13fc70..f0ffea0fbc8 100644
--- a/source/blender/bmesh/tools/bmesh_bevel.c
+++ b/source/blender/bmesh/tools/bmesh_bevel.c
@@ -1256,6 +1256,8 @@ static void set_profile_params(BevelParams *bp, BevVert *bv, BoundVert *bndv)
pro->super_r = bp->pro_super_r;
/* projection direction is direction of the edge */
sub_v3_v3v3(pro->proj_dir, e->e->v1->co, e->e->v2->co);
+ if (e->is_rev)
+ negate_v3(pro->proj_dir);
normalize_v3(pro->proj_dir);
project_to_edge(e->e, co1, co2, pro->midco);
if (DEBUG_OLD_PROJ_TO_PERP_PLANE) {
@@ -1378,19 +1380,28 @@ static void set_profile_params(BevelParams *bp, BevVert *bv, BoundVert *bndv)
/* Move the profile plane for bndv to the plane containing e1 and e2, which share a vert */
static void move_profile_plane(BoundVert *bndv, EdgeHalf *e1, EdgeHalf *e2)
{
- float d1[3], d2[3], no[3], no2[3], dot;
+ float d1[3], d2[3], no[3], no2[3], no3[3], dot2, dot3;
/* only do this if projecting, and e1, e2, and proj_dir are not coplanar */
if (is_zero_v3(bndv->profile.proj_dir)) {
return;
}
sub_v3_v3v3(d1, e1->e->v1->co, e1->e->v2->co);
+ if (e1->is_rev)
+ negate_v3(d1);
+ normalize_v3(d1);
sub_v3_v3v3(d2, e2->e->v1->co, e2->e->v2->co);
+ if (e2->is_rev)
+ negate_v3(d2);
+ normalize_v3(d2);
cross_v3_v3v3(no, d1, d2);
cross_v3_v3v3(no2, d1, bndv->profile.proj_dir);
- if (normalize_v3(no) > BEVEL_EPSILON_BIG && normalize_v3(no2) > BEVEL_EPSILON_BIG) {
- dot = fabsf(dot_v3v3(no, no2));
- if (fabsf(dot - 1.0f) > BEVEL_EPSILON_BIG) {
+ cross_v3_v3v3(no3, d2, bndv->profile.proj_dir);
+ if (normalize_v3(no) > BEVEL_EPSILON_BIG && normalize_v3(no2) > BEVEL_EPSILON_BIG &&
+ normalize_v3(no3) > BEVEL_EPSILON_BIG) {
+ dot2 = dot_v3v3(no, no2);
+ dot3 = dot_v3v3(no, no3);
+ if (fabsf(dot2) < 0.95f && fabsf(dot3) < 0.95f) {
copy_v3_v3(bndv->profile.plane_no, no);
}
}
@@ -1821,6 +1832,9 @@ static void bevel_extend_edge_data(BevVert *bv)
{
VMesh *vm = bv->vmesh;
+ if (vm->mesh_kind == M_TRI_FAN)
+ return;
+
BoundVert *bcur = bv->vmesh->boundstart, *start = bcur;
do {
@@ -2340,7 +2354,7 @@ static void build_boundary_terminal_edge(BevelParams *bp,
/* special case: snap profile to plane of adjacent two edges */
v = vm->boundstart;
BLI_assert(v->ebev != NULL);
- move_profile_plane(v, v->efirst, v->next->elast);
+ move_profile_plane(v, v->next->elast, v->efirst);
calculate_profile(bp, v);
}
diff --git a/source/blender/collada/AnimationClipExporter.h b/source/blender/collada/AnimationClipExporter.h
index 6d67ab7c406..ead894dc941 100644
--- a/source/blender/collada/AnimationClipExporter.h
+++ b/source/blender/collada/AnimationClipExporter.h
@@ -25,13 +25,13 @@ class AnimationClipExporter : COLLADASW::LibraryAnimationClips {
Depsgraph *depsgraph;
Scene *scene;
COLLADASW::StreamWriter *sw;
- const ExportSettings *export_settings;
+ BCExportSettings &export_settings;
std::vector<std::vector<std::string>> anim_meta;
public:
AnimationClipExporter(Depsgraph *depsgraph,
COLLADASW::StreamWriter *sw,
- const ExportSettings *export_settings,
+ BCExportSettings &export_settings,
std::vector<std::vector<std::string>> anim_meta)
: COLLADASW::LibraryAnimationClips(sw),
depsgraph(depsgraph),
diff --git a/source/blender/collada/AnimationExporter.cpp b/source/blender/collada/AnimationExporter.cpp
index a34f92f66d6..2c6ae8a52f5 100644
--- a/source/blender/collada/AnimationExporter.cpp
+++ b/source/blender/collada/AnimationExporter.cpp
@@ -77,24 +77,20 @@ void AnimationExporter::close_animation_container(bool has_container)
bool AnimationExporter::exportAnimations()
{
- Scene *sce = blender_context.get_scene();
+ Scene *sce = export_settings.get_scene();
- LinkNode &export_set = *this->export_settings->export_set;
+ LinkNode *export_set = this->export_settings.get_export_set();
bool has_anim_data = bc_has_animations(sce, export_set);
int animation_count = 0;
if (has_anim_data) {
BCObjectSet animated_subset;
- BCAnimationSampler::get_animated_from_export_set(animated_subset, export_set);
+ BCAnimationSampler::get_animated_from_export_set(animated_subset, *export_set);
animation_count = animated_subset.size();
- BCAnimationSampler animation_sampler(blender_context, animated_subset);
+ BCAnimationSampler animation_sampler(export_settings, animated_subset);
try {
- animation_sampler.sample_scene(export_settings->sampling_rate,
- /*keyframe_at_end = */ true,
- export_settings->open_sim,
- export_settings->keep_keyframes,
- export_settings->export_animation_type);
+ animation_sampler.sample_scene(export_settings, /*keyframe_at_end = */ true);
openLibrary();
@@ -137,7 +133,7 @@ void AnimationExporter::exportAnimation(Object *ob, BCAnimationSampler &sampler)
* Note: For Armatures the skeletal animation has already been exported (see above)
* However Armatures also can have Object animation.
*/
- bool export_as_matrix = this->export_settings->export_transformation_type ==
+ bool export_as_matrix = this->export_settings.get_animation_transformation_type() ==
BC_TRANSFORMATION_TYPE_MATRIX;
if (export_as_matrix) {
@@ -178,7 +174,7 @@ void AnimationExporter::export_curve_animation_set(Object *ob,
bool export_as_matrix)
{
BCAnimationCurveMap *curves = sampler.get_curves(ob);
- bool keep_flat_curves = this->export_settings->keep_flat_curves;
+ bool keep_flat_curves = this->export_settings.get_keep_flat_curves();
BCAnimationCurveMap::iterator it;
for (it = curves->begin(); it != curves->end(); ++it) {
@@ -215,7 +211,7 @@ void AnimationExporter::export_curve_animation_set(Object *ob,
void AnimationExporter::export_matrix_animation(Object *ob, BCAnimationSampler &sampler)
{
- bool keep_flat_curves = this->export_settings->keep_flat_curves;
+ bool keep_flat_curves = this->export_settings.get_keep_flat_curves();
std::vector<float> frames;
sampler.get_object_frames(frames, ob);
@@ -232,17 +228,31 @@ void AnimationExporter::export_matrix_animation(Object *ob, BCAnimationSampler &
std::string target = translate_id(name) + '/' + channel_type;
- export_collada_matrix_animation(id, name, target, frames, samples);
+ BC_global_rotation_type global_rotation_type = get_global_rotation_type(ob);
+ export_collada_matrix_animation(
+ id, name, target, frames, samples, global_rotation_type, ob->parentinv);
}
}
}
+BC_global_rotation_type AnimationExporter::get_global_rotation_type(Object *ob)
+{
+ bool is_export_root = this->export_settings.is_export_root(ob);
+ if (!is_export_root) {
+ return BC_NO_ROTATION;
+ }
+
+ bool apply_global_rotation = this->export_settings.get_apply_global_orientation();
+
+ return (apply_global_rotation) ? BC_DATA_ROTATION : BC_OBJECT_ROTATION;
+}
+
/* Write bone animations in transform matrix sources. */
void AnimationExporter::export_bone_animations_recursive(Object *ob,
Bone *bone,
BCAnimationSampler &sampler)
{
- bool keep_flat_curves = this->export_settings->keep_flat_curves;
+ bool keep_flat_curves = this->export_settings.get_keep_flat_curves();
std::vector<float> frames;
sampler.get_bone_frames(frames, ob, bone);
@@ -347,7 +357,9 @@ void AnimationExporter::export_curve_animation(Object *ob, BCAnimationCurve &cur
collada_target += "/" + get_collada_sid(curve, axis);
}
- export_collada_curve_animation(id, curve_name, collada_target, axis, curve);
+ BC_global_rotation_type global_rotation_type = get_global_rotation_type(ob);
+ export_collada_curve_animation(
+ id, curve_name, collada_target, axis, curve, global_rotation_type);
}
void AnimationExporter::export_bone_animation(Object *ob,
@@ -361,7 +373,9 @@ void AnimationExporter::export_bone_animation(Object *ob,
std::string id = bc_get_action_id(id_name(action), name, bone_name, "pose_matrix");
std::string target = translate_id(id_name(ob) + "_" + bone_name) + "/transform";
- export_collada_matrix_animation(id, name, target, frames, samples);
+ BC_global_rotation_type global_rotation_type = get_global_rotation_type(ob);
+ export_collada_matrix_animation(
+ id, name, target, frames, samples, global_rotation_type, ob->parentinv);
}
bool AnimationExporter::is_bone_deform_group(Bone *bone)
@@ -383,11 +397,13 @@ bool AnimationExporter::is_bone_deform_group(Bone *bone)
return false;
}
-void AnimationExporter::export_collada_curve_animation(std::string id,
- std::string name,
- std::string collada_target,
- std::string axis,
- BCAnimationCurve &curve)
+void AnimationExporter::export_collada_curve_animation(
+ std::string id,
+ std::string name,
+ std::string collada_target,
+ std::string axis,
+ BCAnimationCurve &curve,
+ BC_global_rotation_type global_rotation_type)
{
BCFrames frames;
BCValues values;
@@ -408,7 +424,7 @@ void AnimationExporter::export_collada_curve_animation(std::string id,
bool has_tangents = false;
std::string interpolation_id;
- if (this->export_settings->keep_smooth_curves)
+ if (this->export_settings.get_keep_smooth_curves())
interpolation_id = collada_interpolation_source(curve, id, axis, &has_tangents);
else
interpolation_id = collada_linear_interpolation_source(frames.size(), id);
@@ -444,11 +460,14 @@ void AnimationExporter::export_collada_curve_animation(std::string id,
closeAnimation();
}
-void AnimationExporter::export_collada_matrix_animation(std::string id,
- std::string name,
- std::string target,
- BCFrames &frames,
- BCMatrixSampleMap &samples)
+void AnimationExporter::export_collada_matrix_animation(
+ std::string id,
+ std::string name,
+ std::string target,
+ BCFrames &frames,
+ BCMatrixSampleMap &samples,
+ BC_global_rotation_type global_rotation_type,
+ Matrix &parentinv)
{
fprintf(
stdout, "Export animation matrix %s (%d control points)\n", id.c_str(), int(frames.size()));
@@ -457,7 +476,7 @@ void AnimationExporter::export_collada_matrix_animation(std::string id,
std::string input_id = collada_source_from_values(
BC_SOURCE_TYPE_TIMEFRAME, COLLADASW::InputSemantic::INPUT, frames, id, "");
- std::string output_id = collada_source_from_values(samples, id);
+ std::string output_id = collada_source_from_values(samples, id, global_rotation_type, parentinv);
std::string interpolation_id = collada_linear_interpolation_source(frames.size(), id);
std::string sampler_id = std::string(id) + SAMPLER_ID_SUFFIX;
@@ -540,7 +559,8 @@ std::string AnimationExporter::collada_tangent_from_curve(
const std::string &anim_id,
std::string axis_name)
{
- Scene *scene = blender_context.get_scene();
+ Scene *scene = this->export_settings.get_scene();
+
std::string channel = curve.get_channel_target();
const std::string source_id = anim_id + get_semantic_suffix(semantic);
@@ -585,6 +605,7 @@ std::string AnimationExporter::collada_source_from_values(
const std::string &anim_id,
const std::string axis_name)
{
+ BlenderContext &blender_context = this->export_settings.get_blender_context();
Scene *scene = blender_context.get_scene();
/* T can be float, int or double */
@@ -623,11 +644,14 @@ std::string AnimationExporter::collada_source_from_values(
return source_id;
}
-/**
- * Create a collada matrix source for a set of samples.
+/*
+ * Create a collada matrix source for a set of samples
*/
-std::string AnimationExporter::collada_source_from_values(BCMatrixSampleMap &samples,
- const std::string &anim_id)
+std::string AnimationExporter::collada_source_from_values(
+ BCMatrixSampleMap &samples,
+ const std::string &anim_id,
+ BC_global_rotation_type global_rotation_type,
+ Matrix &parentinv)
{
COLLADASW::InputSemantic::Semantics semantic = COLLADASW::InputSemantic::OUTPUT;
std::string source_id = anim_id + get_semantic_suffix(semantic);
@@ -645,11 +669,18 @@ std::string AnimationExporter::collada_source_from_values(BCMatrixSampleMap &sam
BCMatrixSampleMap::iterator it;
/* could be made configurable */
- int precision = (this->export_settings->limit_precision) ? 6 : -1;
+ int precision = (this->export_settings.get_limit_precision()) ? 6 : -1;
for (it = samples.begin(); it != samples.end(); it++) {
- const BCMatrix *sample = it->second;
- double daemat[4][4];
- sample->get_matrix(daemat, true, precision);
+ BCMatrix sample = BCMatrix(*it->second);
+ BCMatrix global_transform = this->export_settings.get_global_transform();
+ DMatrix daemat;
+ if (this->export_settings.get_apply_global_orientation()) {
+ sample.apply_transform(global_transform);
+ }
+ else {
+ sample.add_transform(global_transform);
+ }
+ sample.get_matrix(daemat, true, precision);
source.appendValues(daemat);
}
diff --git a/source/blender/collada/AnimationExporter.h b/source/blender/collada/AnimationExporter.h
index 71d7d14a112..27474cc2b58 100644
--- a/source/blender/collada/AnimationExporter.h
+++ b/source/blender/collada/AnimationExporter.h
@@ -86,20 +86,22 @@ typedef enum BC_animation_source_type {
BC_SOURCE_TYPE_TIMEFRAME,
} BC_animation_source_type;
+typedef enum BC_global_rotation_type {
+ BC_NO_ROTATION,
+ BC_OBJECT_ROTATION,
+ BC_DATA_ROTATION
+} BC_global_rotation_type;
+
class AnimationExporter : COLLADASW::LibraryAnimations {
private:
- BlenderContext &blender_context;
COLLADASW::StreamWriter *sw;
- const ExportSettings *export_settings;
+ BCExportSettings &export_settings;
+
+ BC_global_rotation_type get_global_rotation_type(Object *ob);
public:
- AnimationExporter(BlenderContext &blender_context,
- COLLADASW::StreamWriter *sw,
- const ExportSettings *export_settings)
- : COLLADASW::LibraryAnimations(sw),
- blender_context(blender_context),
- sw(sw),
- export_settings(export_settings)
+ AnimationExporter(COLLADASW::StreamWriter *sw, BCExportSettings &export_settings)
+ : COLLADASW::LibraryAnimations(sw), sw(sw), export_settings(export_settings)
{
}
@@ -176,14 +178,17 @@ class AnimationExporter : COLLADASW::LibraryAnimations {
std::string name,
std::string target,
std::string axis,
- BCAnimationCurve &curve);
+ BCAnimationCurve &curve,
+ BC_global_rotation_type global_rotation_type);
/* call to the low level collada exporter */
void export_collada_matrix_animation(std::string id,
std::string name,
std::string target,
BCFrames &frames,
- BCMatrixSampleMap &outmats);
+ BCMatrixSampleMap &outmats,
+ BC_global_rotation_type global_rotation_type,
+ Matrix &parentinv);
BCAnimationCurve *get_modified_export_curve(Object *ob,
BCAnimationCurve &curve,
@@ -202,7 +207,10 @@ class AnimationExporter : COLLADASW::LibraryAnimations {
const std::string axis_name);
/* Output sources (matrix data) */
- std::string collada_source_from_values(BCMatrixSampleMap &samples, const std::string &anim_id);
+ std::string collada_source_from_values(BCMatrixSampleMap &samples,
+ const std::string &anim_id,
+ BC_global_rotation_type global_rotation_type,
+ Matrix &parentinv);
/* Interpolation sources */
std::string collada_linear_interpolation_source(int tot, const std::string &anim_id);
diff --git a/source/blender/collada/ArmatureExporter.cpp b/source/blender/collada/ArmatureExporter.cpp
index be50b255f13..f974996191b 100644
--- a/source/blender/collada/ArmatureExporter.cpp
+++ b/source/blender/collada/ArmatureExporter.cpp
@@ -43,8 +43,6 @@ extern "C" {
#include "ArmatureExporter.h"
#include "SceneExporter.h"
-#include "collada_utils.h"
-
// write bone nodes
void ArmatureExporter::add_armature_bones(Object *ob_arm,
ViewLayer *view_layer,
@@ -62,10 +60,7 @@ void ArmatureExporter::add_armature_bones(Object *ob_arm,
}
for (Bone *bone = (Bone *)armature->bonebase.first; bone; bone = bone->next) {
- // start from root bones
- if (!bone->parent) {
- add_bone_node(bone, ob_arm, se, child_objects);
- }
+ add_bone_node(bone, ob_arm, se, child_objects);
}
if (!is_edited) {
@@ -77,7 +72,7 @@ void ArmatureExporter::write_bone_URLs(COLLADASW::InstanceController &ins,
Object *ob_arm,
Bone *bone)
{
- if (bc_is_root_bone(bone, this->export_settings->deform_bones_only)) {
+ if (bc_is_root_bone(bone, this->export_settings.get_deform_bones_only())) {
std::string joint_id = translate_id(id_name(ob_arm) + "_" + bone->name);
ins.addSkeleton(COLLADABU::URI(COLLADABU::Utils::EMPTY_STRING, joint_id));
}
@@ -109,7 +104,7 @@ bool ArmatureExporter::add_instance_controller(Object *ob)
}
InstanceWriter::add_material_bindings(
- ins.getBindMaterial(), ob, this->export_settings->active_uv_only);
+ ins.getBindMaterial(), ob, this->export_settings.get_active_uv_only());
ins.add();
return true;
@@ -157,7 +152,7 @@ void ArmatureExporter::add_bone_node(Bone *bone,
SceneExporter *se,
std::vector<Object *> &child_objects)
{
- if (!(this->export_settings->deform_bones_only && bone->flag & BONE_NO_DEFORM)) {
+ if (can_export(bone)) {
std::string node_id = translate_id(id_name(ob_arm) + "_" + bone->name);
std::string node_name = std::string(bone->name);
std::string node_sid = get_joint_sid(bone);
@@ -169,8 +164,8 @@ void ArmatureExporter::add_bone_node(Bone *bone,
node.setNodeName(node_name);
node.setNodeSid(node_sid);
- if (this->export_settings->use_blender_profile) {
- if (bone->parent) {
+ if (this->export_settings.get_use_blender_profile()) {
+ if (!is_export_root(bone)) {
if (bone->flag & BONE_CONNECTED) {
node.addExtraTechniqueParameter("blender", "connect", true);
}
@@ -184,9 +179,19 @@ void ArmatureExporter::add_bone_node(Bone *bone,
node.addExtraTechniqueParameter("blender", "roll", ebone->roll);
}
if (bc_is_leaf_bone(bone)) {
- node.addExtraTechniqueParameter("blender", "tip_x", bone->arm_tail[0] - bone->arm_head[0]);
- node.addExtraTechniqueParameter("blender", "tip_y", bone->arm_tail[1] - bone->arm_head[1]);
- node.addExtraTechniqueParameter("blender", "tip_z", bone->arm_tail[2] - bone->arm_head[2]);
+ Vector head, tail;
+ const BCMatrix &global_transform = this->export_settings.get_global_transform();
+ if (this->export_settings.get_apply_global_orientation()) {
+ bc_add_global_transform(head, bone->arm_head, global_transform);
+ bc_add_global_transform(tail, bone->arm_tail, global_transform);
+ }
+ else {
+ copy_v3_v3(head, bone->arm_head);
+ copy_v3_v3(tail, bone->arm_tail);
+ }
+ node.addExtraTechniqueParameter("blender", "tip_x", tail[0] - head[0]);
+ node.addExtraTechniqueParameter("blender", "tip_y", tail[1] - head[1]);
+ node.addExtraTechniqueParameter("blender", "tip_z", tail[2] - head[2]);
}
}
@@ -195,12 +200,13 @@ void ArmatureExporter::add_bone_node(Bone *bone,
add_bone_transform(ob_arm, bone, node);
// Write nodes of childobjects, remove written objects from list
- std::vector<Object *>::iterator i = child_objects.begin();
+ std::vector<Object *>::iterator iter = child_objects.begin();
- while (i != child_objects.end()) {
- if ((*i)->partype == PARBONE && STREQ((*i)->parsubstr, bone->name)) {
+ while (iter != child_objects.end()) {
+ Object *ob = *iter;
+ if (ob->partype == PARBONE && STREQ(ob->parsubstr, bone->name)) {
float backup_parinv[4][4];
- copy_m4_m4(backup_parinv, (*i)->parentinv);
+ copy_m4_m4(backup_parinv, ob->parentinv);
// crude, temporary change to parentinv
// so transform gets exported correctly.
@@ -208,28 +214,28 @@ void ArmatureExporter::add_bone_node(Bone *bone,
// Add bone tail- translation... don't know why
// bone parenting is against the tail of a bone
// and not it's head, seems arbitrary.
- (*i)->parentinv[3][1] += bone->length;
+ ob->parentinv[3][1] += bone->length;
// OPEN_SIM_COMPATIBILITY
// TODO: when such objects are animated as
// single matrix the tweak must be applied
// to the result.
- if (export_settings->open_sim) {
+ if (export_settings.get_open_sim()) {
// tweak objects parentinverse to match compatibility
float temp[4][4];
copy_m4_m4(temp, bone->arm_mat);
temp[3][0] = temp[3][1] = temp[3][2] = 0.0f;
- mul_m4_m4m4((*i)->parentinv, temp, (*i)->parentinv);
+ mul_m4_m4m4(ob->parentinv, temp, ob->parentinv);
}
- se->writeNodes(*i);
- copy_m4_m4((*i)->parentinv, backup_parinv);
- i = child_objects.erase(i);
+ se->writeNode(ob);
+ copy_m4_m4(ob->parentinv, backup_parinv);
+ iter = child_objects.erase(iter);
}
else
- i++;
+ iter++;
}
for (Bone *child = (Bone *)bone->childbase.first; child; child = child->next) {
@@ -244,6 +250,18 @@ void ArmatureExporter::add_bone_node(Bone *bone,
}
}
+bool ArmatureExporter::is_export_root(Bone *bone)
+{
+ Bone *entry = bone->parent;
+ while (entry) {
+ if (can_export(entry)) {
+ return false;
+ }
+ entry = entry->parent;
+ }
+ return can_export(bone);
+}
+
void ArmatureExporter::add_bone_transform(Object *ob_arm, Bone *bone, COLLADASW::Node &node)
{
// bPoseChannel *pchan = BKE_pose_channel_find_name(ob_arm->pose, bone->name);
@@ -260,49 +278,45 @@ void ArmatureExporter::add_bone_transform(Object *ob_arm, Bone *bone, COLLADASW:
bc_create_restpose_mat(this->export_settings, bone, bone_rest_mat, bone->arm_mat, true);
- if (bone->parent) {
- /* Get bone-space matrix from parent pose. */
-#if 0
- bPoseChannel *parchan = BKE_pose_channel_find_name(ob_arm->pose, bone->parent->name);
- float invpar[4][4];
- invert_m4_m4(invpar, parchan->pose_mat);
- mul_m4_m4m4(mat, invpar, pchan->pose_mat);
-#endif
- float invpar[4][4];
+ if (is_export_root(bone)) {
+ copy_m4_m4(mat, bone_rest_mat);
+ }
+ else {
+ Matrix parent_inverse;
bc_create_restpose_mat(
this->export_settings, bone->parent, parent_rest_mat, bone->parent->arm_mat, true);
- invert_m4_m4(invpar, parent_rest_mat);
- mul_m4_m4m4(mat, invpar, bone_rest_mat);
- }
- else {
- copy_m4_m4(mat, bone_rest_mat);
+ invert_m4_m4(parent_inverse, parent_rest_mat);
+ mul_m4_m4m4(mat, parent_inverse, bone_rest_mat);
}
// OPEN_SIM_COMPATIBILITY
- if (export_settings->open_sim) {
+
+ if (export_settings.get_open_sim()) {
// Remove rotations vs armature from transform
// parent_rest_rot * mat * irest_rot
- float temp[4][4];
- copy_m4_m4(temp, bone_rest_mat);
- temp[3][0] = temp[3][1] = temp[3][2] = 0.0f;
- invert_m4(temp);
+ Matrix workmat;
+ copy_m4_m4(workmat, bone_rest_mat);
- mul_m4_m4m4(mat, mat, temp);
+ workmat[3][0] = workmat[3][1] = workmat[3][2] = 0.0f;
+ invert_m4(workmat);
- if (bone->parent) {
- copy_m4_m4(temp, parent_rest_mat);
- temp[3][0] = temp[3][1] = temp[3][2] = 0.0f;
+ mul_m4_m4m4(mat, mat, workmat);
- mul_m4_m4m4(mat, temp, mat);
+ if (!is_export_root(bone)) {
+ copy_m4_m4(workmat, parent_rest_mat);
+ workmat[3][0] = workmat[3][1] = workmat[3][2] = 0.0f;
+
+ mul_m4_m4m4(mat, workmat, mat);
}
}
}
- if (this->export_settings->limit_precision)
+ if (this->export_settings.get_limit_precision()) {
bc_sanitize_mat(mat, LIMITTED_PRECISION);
+ }
- TransformWriter::add_node_transform(node, mat, NULL);
+ TransformWriter::add_joint_transform(node, mat, NULL, this->export_settings, has_restmat);
}
std::string ArmatureExporter::get_controller_id(Object *ob_arm, Object *ob)
diff --git a/source/blender/collada/ArmatureExporter.h b/source/blender/collada/ArmatureExporter.h
index 6ef6007960e..da6d6f79ef5 100644
--- a/source/blender/collada/ArmatureExporter.h
+++ b/source/blender/collada/ArmatureExporter.h
@@ -56,7 +56,7 @@ class ArmatureExporter : public COLLADASW::LibraryControllers,
// we make controller ids then?
ArmatureExporter(BlenderContext &blender_context,
COLLADASW::StreamWriter *sw,
- const ExportSettings *export_settings)
+ BCExportSettings &export_settings)
: COLLADASW::LibraryControllers(sw),
blender_context(blender_context),
export_settings(export_settings)
@@ -72,7 +72,7 @@ class ArmatureExporter : public COLLADASW::LibraryControllers,
private:
BlenderContext &blender_context;
- const ExportSettings *export_settings;
+ BCExportSettings &export_settings;
#if 0
std::vector<Object *> written_armatures;
@@ -91,6 +91,12 @@ class ArmatureExporter : public COLLADASW::LibraryControllers,
SceneExporter *se,
std::vector<Object *> &child_objects);
+ inline bool can_export(Bone *bone)
+ {
+ return !(export_settings.get_deform_bones_only() && bone->flag & BONE_NO_DEFORM);
+ }
+
+ bool is_export_root(Bone *bone);
void add_bone_transform(Object *ob_arm, Bone *bone, COLLADASW::Node &node);
std::string get_controller_id(Object *ob_arm, Object *ob);
diff --git a/source/blender/collada/BCAnimationSampler.cpp b/source/blender/collada/BCAnimationSampler.cpp
index ee574e2968b..1e6ff79f132 100644
--- a/source/blender/collada/BCAnimationSampler.cpp
+++ b/source/blender/collada/BCAnimationSampler.cpp
@@ -44,8 +44,8 @@ extern "C" {
static std::string EMPTY_STRING;
static BCAnimationCurveMap BCEmptyAnimationCurves;
-BCAnimationSampler::BCAnimationSampler(BlenderContext &blender_context, BCObjectSet &object_set)
- : blender_context(blender_context)
+BCAnimationSampler::BCAnimationSampler(BCExportSettings &export_settings, BCObjectSet &object_set)
+ : export_settings(export_settings)
{
BCObjectSet::iterator it;
for (it = object_set.begin(); it != object_set.end(); ++it) {
@@ -65,6 +65,7 @@ BCAnimationSampler::~BCAnimationSampler()
void BCAnimationSampler::add_object(Object *ob)
{
+ BlenderContext blender_context = export_settings.get_blender_context();
BCAnimation *animation = new BCAnimation(blender_context.get_context(), ob);
objects[ob] = animation;
@@ -156,6 +157,10 @@ void BCAnimationSampler::update_animation_curves(BCAnimation &animation,
BCSample &BCAnimationSampler::sample_object(Object *ob, int frame_index, bool for_opensim)
{
BCSample &ob_sample = sample_data.add(ob, frame_index);
+ // if (export_settings.get_apply_global_orientation()) {
+ // const BCMatrix &global_transform = export_settings.get_global_transform();
+ // ob_sample.get_matrix(global_transform);
+ //}
if (ob->type == OB_ARMATURE) {
bPoseChannel *pchan;
@@ -163,6 +168,7 @@ BCSample &BCAnimationSampler::sample_object(Object *ob, int frame_index, bool fo
Bone *bone = pchan->bone;
Matrix bmat;
if (bc_bone_matrix_local_get(ob, bone, bmat, for_opensim)) {
+
ob_sample.add_bone_matrix(bone, bmat);
}
}
@@ -170,12 +176,14 @@ BCSample &BCAnimationSampler::sample_object(Object *ob, int frame_index, bool fo
return ob_sample;
}
-void BCAnimationSampler::sample_scene(int sampling_rate,
- int keyframe_at_end,
- bool for_opensim,
- bool keep_keyframes,
- BC_export_animation_type export_animation_type)
+void BCAnimationSampler::sample_scene(BCExportSettings &export_settings, bool keyframe_at_end)
{
+ BlenderContext blender_context = export_settings.get_blender_context();
+ int sampling_rate = export_settings.get_sampling_rate();
+ bool for_opensim = export_settings.get_open_sim();
+ bool keep_keyframes = export_settings.get_keep_keyframes();
+ BC_export_animation_type export_animation_type = export_settings.get_export_animation_type();
+
Scene *scene = blender_context.get_scene();
BCFrameSet scene_sample_frames;
get_sample_frames(scene_sample_frames, sampling_rate, keyframe_at_end, scene);
diff --git a/source/blender/collada/BCAnimationSampler.h b/source/blender/collada/BCAnimationSampler.h
index 9544c6be916..e8d2ab56ae7 100644
--- a/source/blender/collada/BCAnimationSampler.h
+++ b/source/blender/collada/BCAnimationSampler.h
@@ -147,7 +147,7 @@ class BCSampleFrameContainer {
class BCAnimationSampler {
private:
- BlenderContext &blender_context;
+ BCExportSettings &export_settings;
BCSampleFrameContainer sample_data;
BCAnimationObjectMap objects;
@@ -169,16 +169,12 @@ class BCAnimationSampler {
BCAnimation &animation, float *ref, float *val, std::string data_path, int length);
public:
- BCAnimationSampler(BlenderContext &blender_context, BCObjectSet &animated_subset);
+ BCAnimationSampler(BCExportSettings &export_settings, BCObjectSet &animated_subset);
~BCAnimationSampler();
void add_object(Object *ob);
- void sample_scene(int sampling_rate,
- int keyframe_at_end,
- bool for_opensim,
- bool keep_keyframes,
- BC_export_animation_type export_animation_type);
+ void sample_scene(BCExportSettings &export_settings, bool keyframe_at_end);
BCAnimationCurveMap *get_curves(Object *ob);
void get_object_frames(BCFrames &frames, Object *ob);
diff --git a/source/blender/collada/BCSampleData.cpp b/source/blender/collada/BCSampleData.cpp
index 868526928b0..88a7fd5993c 100644
--- a/source/blender/collada/BCSampleData.cpp
+++ b/source/blender/collada/BCSampleData.cpp
@@ -20,10 +20,6 @@
#include "BCSampleData.h"
#include "collada_utils.h"
-BCSample::BCSample(Object *ob) : obmat(ob)
-{
-}
-
BCSample::~BCSample()
{
BCBoneMatrixMap::iterator it;
@@ -43,6 +39,11 @@ void BCSample::add_bone_matrix(Bone *bone, Matrix &mat)
bonemats[bone] = matrix;
}
+BCMatrix::BCMatrix(const BCMatrix &mat)
+{
+ set_transform(mat.matrix);
+}
+
BCMatrix::BCMatrix(Matrix &mat)
{
set_transform(mat);
@@ -53,11 +54,71 @@ BCMatrix::BCMatrix(Object *ob)
set_transform(ob);
}
-void BCMatrix::set_transform(Matrix &mat)
+BCMatrix::BCMatrix()
{
- copy_m4_m4(matrix, mat);
- mat4_decompose(this->loc, this->q, this->size, mat);
- quat_to_eul(this->rot, this->q);
+ unit();
+}
+
+BCMatrix::BCMatrix(BC_global_forward_axis global_forward_axis, BC_global_up_axis global_up_axis)
+{
+ float mrot[3][3];
+ float mat[4][4];
+ mat3_from_axis_conversion(
+ BC_DEFAULT_FORWARD, BC_DEFAULT_UP, global_forward_axis, global_up_axis, mrot);
+
+ transpose_m3(mrot); // TODO: Verify that mat3_from_axis_conversion() returns a transposed matrix
+ copy_m4_m3(mat, mrot);
+ set_transform(mat);
+}
+
+void BCMatrix::add_transform(const Matrix &mat, bool inverse)
+{
+ add_transform(this->matrix, mat, this->matrix, inverse);
+}
+
+void BCMatrix::add_transform(const BCMatrix &mat, bool inverse)
+{
+ add_transform(this->matrix, mat.matrix, this->matrix, inverse);
+}
+
+void BCMatrix::apply_transform(const BCMatrix &mat, bool inverse)
+{
+ apply_transform(this->matrix, mat.matrix, this->matrix, inverse);
+}
+
+void BCMatrix::add_transform(Matrix &to, const Matrix &transform, const Matrix &from, bool inverse)
+{
+ if (inverse) {
+ Matrix globinv;
+ invert_m4_m4(globinv, transform);
+ add_transform(to, globinv, from, /*inverse=*/false);
+ }
+ else {
+ mul_m4_m4m4(to, transform, from);
+ }
+}
+
+void BCMatrix::apply_transform(Matrix &to,
+ const Matrix &transform,
+ const Matrix &from,
+ bool inverse)
+{
+ Matrix globinv;
+ invert_m4_m4(globinv, transform);
+ if (inverse) {
+ add_transform(to, globinv, from, /*inverse=*/false);
+ }
+ else {
+ mul_m4_m4m4(to, transform, from);
+ mul_m4_m4m4(to, to, globinv);
+ }
+}
+
+void BCMatrix::add_inverted_transform(Matrix &to, const Matrix &transform, const Matrix &from)
+{
+ Matrix workmat;
+ invert_m4_m4(workmat, transform);
+ mul_m4_m4m4(to, workmat, from);
}
void BCMatrix::set_transform(Object *ob)
@@ -71,6 +132,13 @@ void BCMatrix::set_transform(Object *ob)
quat_to_compatible_eul(this->rot, ob->rot, this->q);
}
+void BCMatrix::set_transform(Matrix &mat)
+{
+ copy_m4_m4(matrix, mat);
+ mat4_decompose(this->loc, this->q, this->size, mat);
+ quat_to_eul(this->rot, this->q);
+}
+
const BCMatrix *BCSample::get_matrix(Bone *bone) const
{
BCBoneMatrixMap::const_iterator it = bonemats.find(bone);
@@ -126,12 +194,28 @@ void BCMatrix::sanitize(Matrix &mat, int precision)
void BCMatrix::unit()
{
- unit_m4(matrix);
+ unit_m4(this->matrix);
+ mat4_decompose(this->loc, this->q, this->size, this->matrix);
+ quat_to_eul(this->rot, this->q);
}
/* We need double here because the OpenCollada API needs it.
* precision = -1 indicates to not limit the precision. */
-void BCMatrix::get_matrix(double (&mat)[4][4], const bool transposed, const int precision) const
+void BCMatrix::get_matrix(DMatrix &mat, const bool transposed, const int precision) const
+{
+ for (int i = 0; i < 4; i++)
+ for (int j = 0; j < 4; j++) {
+ float val = (transposed) ? matrix[j][i] : matrix[i][j];
+ if (precision >= 0)
+ val = floor((val * pow(10, precision) + 0.5)) / pow(10, precision);
+ mat[i][j] = val;
+ }
+}
+
+void BCMatrix::get_matrix(Matrix &mat,
+ const bool transposed,
+ const int precision,
+ const bool inverted) const
{
for (int i = 0; i < 4; i++)
for (int j = 0; j < 4; j++) {
@@ -140,6 +224,10 @@ void BCMatrix::get_matrix(double (&mat)[4][4], const bool transposed, const int
val = floor((val * pow(10, precision) + 0.5)) / pow(10, precision);
mat[i][j] = val;
}
+
+ if (inverted) {
+ invert_m4(mat);
+ }
}
const bool BCMatrix::in_range(const BCMatrix &other, float distance) const
diff --git a/source/blender/collada/BCSampleData.h b/source/blender/collada/BCSampleData.h
index 9cb56c95e0f..709bd3e59ef 100644
--- a/source/blender/collada/BCSampleData.h
+++ b/source/blender/collada/BCSampleData.h
@@ -24,6 +24,8 @@
#include <map>
#include <algorithm>
+#include "ExportSettings.h"
+
extern "C" {
#include "BKE_object.h"
#include "BLI_math_rotation.h"
@@ -34,40 +36,6 @@ extern "C" {
#include "DNA_camera_types.h"
}
-typedef float(Matrix)[4][4];
-
-class BCMatrix {
-
- private:
- mutable float matrix[4][4];
- mutable float size[3];
- mutable float rot[3];
- mutable float loc[3];
- mutable float q[4];
-
- void unit();
- void copy(Matrix &r, Matrix &a);
- void set_transform(Object *ob);
- void set_transform(Matrix &mat);
-
- public:
- float (&location() const)[3];
- float (&rotation() const)[3];
- float (&scale() const)[3];
- float (&quat() const)[4];
-
- BCMatrix(Matrix &mat);
- BCMatrix(Object *ob);
-
- void get_matrix(double (&mat)[4][4],
- const bool transposed = false,
- const int precision = -1) const;
-
- const bool in_range(const BCMatrix &other, float distance) const;
- static void sanitize(Matrix &matrix, int precision);
- static void transpose(Matrix &matrix);
-};
-
typedef std::map<Bone *, BCMatrix *> BCBoneMatrixMap;
class BCSample {
@@ -76,7 +44,10 @@ class BCSample {
BCBoneMatrixMap bonemats; /* For Armature animation */
public:
- BCSample(Object *ob);
+ BCSample(Object *ob) : obmat(ob)
+ {
+ }
+
~BCSample();
void add_bone_matrix(Bone *bone, Matrix &mat);
diff --git a/source/blender/collada/BlenderContext.cpp b/source/blender/collada/BlenderContext.cpp
index 384f235e00c..709f84c3f77 100644
--- a/source/blender/collada/BlenderContext.cpp
+++ b/source/blender/collada/BlenderContext.cpp
@@ -18,9 +18,92 @@
* \ingroup collada
*/
+#include <vector>
+
#include "BlenderContext.h"
#include "BKE_scene.h"
+bool bc_is_base_node(LinkNode *export_set, Object *ob, ViewLayer *view_layer)
+{
+ Object *root = bc_get_highest_exported_ancestor_or_self(export_set, ob, view_layer);
+ return (root == ob);
+}
+
+/**
+ * Returns the highest selected ancestor
+ * returns NULL if no ancestor is selected
+ * IMPORTANT: This function expects that all exported objects have set:
+ * ob->id.tag & LIB_TAG_DOIT
+ */
+Object *bc_get_highest_exported_ancestor_or_self(LinkNode *export_set,
+ Object *ob,
+ ViewLayer *view_layer)
+{
+ Object *ancestor = ob;
+ while (ob->parent) {
+ if (bc_is_in_Export_set(export_set, ob->parent, view_layer)) {
+ ancestor = ob->parent;
+ }
+ ob = ob->parent;
+ }
+ return ancestor;
+}
+
+void bc_get_children(std::vector<Object *> &child_set, Object *ob, ViewLayer *view_layer)
+{
+ Base *base;
+ for (base = (Base *)view_layer->object_bases.first; base; base = base->next) {
+ Object *cob = base->object;
+ if (cob->parent == ob) {
+ switch (ob->type) {
+ case OB_MESH:
+ case OB_CAMERA:
+ case OB_LAMP:
+ case OB_EMPTY:
+ case OB_ARMATURE:
+ child_set.push_back(cob);
+ default:
+ break;
+ }
+ }
+ }
+}
+
+bool bc_is_in_Export_set(LinkNode *export_set, Object *ob, ViewLayer *view_layer)
+{
+ bool to_export = (BLI_linklist_index(export_set, ob) != -1);
+
+ if (!to_export) {
+ /* Mark this object as to_export even if it is not in the
+ export list, but it contains children to export */
+
+ std::vector<Object *> children;
+ bc_get_children(children, ob, view_layer);
+ for (int i = 0; i < children.size(); i++) {
+ if (bc_is_in_Export_set(export_set, children[i], view_layer)) {
+ to_export = true;
+ break;
+ }
+ }
+ }
+ return to_export;
+}
+
+int bc_is_marked(Object *ob)
+{
+ return ob && (ob->id.tag & LIB_TAG_DOIT);
+}
+
+void bc_remove_mark(Object *ob)
+{
+ ob->id.tag &= ~LIB_TAG_DOIT;
+}
+
+void bc_set_mark(Object *ob)
+{
+ ob->id.tag |= LIB_TAG_DOIT;
+}
+
BlenderContext::BlenderContext(bContext *C)
{
context = C;
diff --git a/source/blender/collada/BlenderContext.h b/source/blender/collada/BlenderContext.h
index f79f3a52507..c23a1b0f312 100644
--- a/source/blender/collada/BlenderContext.h
+++ b/source/blender/collada/BlenderContext.h
@@ -21,14 +21,105 @@
#ifndef __BLENDERCONTEXT_H__
#define __BLENDERCONTEXT_H__
+#ifdef __cplusplus
+
extern "C" {
+#endif
+
#include "DNA_object_types.h"
+#include "BLI_linklist.h"
#include "BKE_context.h"
#include "BKE_main.h"
#include "DEG_depsgraph.h"
#include "DEG_depsgraph_query.h"
+#include "DNA_layer_types.h"
+
+typedef float(Vector)[3];
+typedef float(Matrix)[4][4];
+typedef double(DMatrix)[4][4];
+
+typedef enum BC_global_forward_axis {
+ BC_GLOBAL_FORWARD_X = 0,
+ BC_GLOBAL_FORWARD_Y = 1,
+ BC_GLOBAL_FORWARD_Z = 2,
+ BC_GLOBAL_FORWARD_MINUS_X = 3,
+ BC_GLOBAL_FORWARD_MINUS_Y = 4,
+ BC_GLOBAL_FORWARD_MINUS_Z = 5
+} BC_global_forward_axis;
+
+typedef enum BC_global_up_axis {
+ BC_GLOBAL_UP_X = 0,
+ BC_GLOBAL_UP_Y = 1,
+ BC_GLOBAL_UP_Z = 2,
+ BC_GLOBAL_UP_MINUS_X = 3,
+ BC_GLOBAL_UP_MINUS_Y = 4,
+ BC_GLOBAL_UP_MINUS_Z = 5
+} BC_global_up_axis;
+
+static const BC_global_forward_axis BC_DEFAULT_FORWARD = BC_GLOBAL_FORWARD_Y;
+static const BC_global_up_axis BC_DEFAULT_UP = BC_GLOBAL_UP_Z;
+
+bool bc_is_in_Export_set(LinkNode *export_set, Object *ob, ViewLayer *view_layer);
+bool bc_is_base_node(LinkNode *export_set, Object *ob, ViewLayer *view_layer);
+Object *bc_get_highest_exported_ancestor_or_self(LinkNode *export_set,
+ Object *ob,
+ ViewLayer *view_layer);
+int bc_is_marked(Object *ob);
+void bc_remove_mark(Object *ob);
+void bc_set_mark(Object *ob);
+
+#ifdef __cplusplus
}
+class BCMatrix {
+
+ private:
+ mutable float matrix[4][4];
+ mutable float size[3];
+ mutable float rot[3];
+ mutable float loc[3];
+ mutable float q[4];
+
+ void unit();
+ void copy(Matrix &r, Matrix &a);
+
+ public:
+ float (&location() const)[3];
+ float (&rotation() const)[3];
+ float (&scale() const)[3];
+ float (&quat() const)[4];
+
+ BCMatrix(BC_global_forward_axis global_forward_axis, BC_global_up_axis global_up_axis);
+ BCMatrix(const BCMatrix &mat);
+ BCMatrix(Matrix &mat);
+ BCMatrix(Object *ob);
+ BCMatrix();
+
+ void get_matrix(DMatrix &matrix, const bool transposed = false, const int precision = -1) const;
+ void get_matrix(Matrix &matrix,
+ const bool transposed = false,
+ const int precision = -1,
+ const bool inverted = false) const;
+ void set_transform(Object *ob);
+ void set_transform(Matrix &mat);
+ void add_transform(Matrix &to,
+ const Matrix &transform,
+ const Matrix &from,
+ const bool inverted = false);
+ void apply_transform(Matrix &to,
+ const Matrix &transform,
+ const Matrix &from,
+ const bool inverted = false);
+ void add_inverted_transform(Matrix &to, const Matrix &transform, const Matrix &from);
+ void add_transform(const Matrix &matrix, const bool inverted = false);
+ void add_transform(const BCMatrix &matrix, const bool inverted = false);
+ void apply_transform(const BCMatrix &matrix, const bool inverted = false);
+
+ const bool in_range(const BCMatrix &other, float distance) const;
+ static void sanitize(Matrix &matrix, int precision);
+ static void transpose(Matrix &matrix);
+};
+
class BlenderContext {
private:
bContext *context;
@@ -47,5 +138,6 @@ class BlenderContext {
ViewLayer *get_view_layer();
Main *get_main();
};
+#endif
#endif
diff --git a/source/blender/collada/CameraExporter.cpp b/source/blender/collada/CameraExporter.cpp
index a46ee74be91..74862c44270 100644
--- a/source/blender/collada/CameraExporter.cpp
+++ b/source/blender/collada/CameraExporter.cpp
@@ -29,8 +29,7 @@ extern "C" {
#include "collada_internal.h"
-CamerasExporter::CamerasExporter(COLLADASW::StreamWriter *sw,
- const ExportSettings *export_settings)
+CamerasExporter::CamerasExporter(COLLADASW::StreamWriter *sw, BCExportSettings &export_settings)
: COLLADASW::LibraryCameras(sw), export_settings(export_settings)
{
}
@@ -52,7 +51,7 @@ void CamerasExporter::exportCameras(Scene *sce)
{
openLibrary();
- forEachCameraObjectInExportSet(sce, *this, this->export_settings->export_set);
+ forEachCameraObjectInExportSet(sce, *this, this->export_settings.get_export_set());
closeLibrary();
}
diff --git a/source/blender/collada/CameraExporter.h b/source/blender/collada/CameraExporter.h
index 0a90fc017e8..04bcc4a5dad 100644
--- a/source/blender/collada/CameraExporter.h
+++ b/source/blender/collada/CameraExporter.h
@@ -34,13 +34,13 @@ extern "C" {
class CamerasExporter : COLLADASW::LibraryCameras {
public:
- CamerasExporter(COLLADASW::StreamWriter *sw, const ExportSettings *export_settings);
+ CamerasExporter(COLLADASW::StreamWriter *sw, BCExportSettings &export_settings);
void exportCameras(Scene *sce);
void operator()(Object *ob, Scene *sce);
private:
bool exportBlenderProfile(COLLADASW::Camera &cla, Camera *cam);
- const ExportSettings *export_settings;
+ BCExportSettings &export_settings;
};
#endif
diff --git a/source/blender/collada/ControllerExporter.cpp b/source/blender/collada/ControllerExporter.cpp
index c79a4e1a1f7..cb15a3a7a7c 100644
--- a/source/blender/collada/ControllerExporter.cpp
+++ b/source/blender/collada/ControllerExporter.cpp
@@ -57,7 +57,7 @@ void ControllerExporter::write_bone_URLs(COLLADASW::InstanceController &ins,
Object *ob_arm,
Bone *bone)
{
- if (bc_is_root_bone(bone, this->export_settings->deform_bones_only)) {
+ if (bc_is_root_bone(bone, this->export_settings.get_deform_bones_only())) {
std::string node_id = translate_id(id_name(ob_arm) + "_" + bone->name);
ins.addSkeleton(COLLADABU::URI(COLLADABU::Utils::EMPTY_STRING, node_id));
}
@@ -89,7 +89,7 @@ bool ControllerExporter::add_instance_controller(Object *ob)
}
InstanceWriter::add_material_bindings(
- ins.getBindMaterial(), ob, this->export_settings->active_uv_only);
+ ins.getBindMaterial(), ob, this->export_settings.get_active_uv_only());
ins.add();
return true;
@@ -102,7 +102,7 @@ void ControllerExporter::export_controllers()
GeometryFunctor gf;
gf.forEachMeshObjectInExportSet<ControllerExporter>(
- sce, *this, this->export_settings->export_set);
+ sce, *this, this->export_settings.get_export_set());
closeLibrary();
}
@@ -115,7 +115,7 @@ void ControllerExporter::operator()(Object *ob)
if (ob_arm) {
export_skin_controller(ob, ob_arm);
}
- if (key && this->export_settings->include_shapekeys) {
+ if (key && this->export_settings.get_include_shapekeys()) {
export_morph_controller(ob, key);
}
}
@@ -189,7 +189,7 @@ void ControllerExporter::export_skin_controller(Object *ob, Object *ob_arm)
} MDeformWeight;
#endif
- bool use_instantiation = this->export_settings->use_object_instantiation;
+ bool use_instantiation = this->export_settings.get_use_object_instantiation();
Mesh *me;
if (((Mesh *)ob->data)->dvert == NULL) {
@@ -198,9 +198,9 @@ void ControllerExporter::export_skin_controller(Object *ob, Object *ob_arm)
me = bc_get_mesh_copy(blender_context,
ob,
- this->export_settings->export_mesh_type,
- this->export_settings->apply_modifiers,
- this->export_settings->triangulate);
+ this->export_settings.get_export_mesh_type(),
+ this->export_settings.get_apply_modifiers(),
+ this->export_settings.get_triangulate());
std::string controller_name = id_name(ob_arm);
std::string controller_id = get_controller_id(ob_arm, ob);
@@ -297,14 +297,14 @@ void ControllerExporter::export_skin_controller(Object *ob, Object *ob_arm)
void ControllerExporter::export_morph_controller(Object *ob, Key *key)
{
- bool use_instantiation = this->export_settings->use_object_instantiation;
+ bool use_instantiation = this->export_settings.get_use_object_instantiation();
Mesh *me;
me = bc_get_mesh_copy(blender_context,
ob,
- this->export_settings->export_mesh_type,
- this->export_settings->apply_modifiers,
- this->export_settings->triangulate);
+ this->export_settings.get_export_mesh_type(),
+ this->export_settings.get_apply_modifiers(),
+ this->export_settings.get_triangulate());
std::string controller_name = id_name(ob) + "-morph";
std::string controller_id = get_controller_id(key, ob);
@@ -431,9 +431,16 @@ void ControllerExporter::add_bind_shape_mat(Object *ob)
float f_obmat[4][4];
BKE_object_matrix_local_get(ob, f_obmat);
+ if (export_settings.get_apply_global_orientation()) {
+ // do nothing, rotation is going to be applied to the Data
+ }
+ else {
+ bc_add_global_transform(f_obmat, export_settings.get_global_transform());
+ }
+
// UnitConverter::mat4_to_dae_double(bind_mat, ob->obmat);
UnitConverter::mat4_to_dae_double(bind_mat, f_obmat);
- if (this->export_settings->limit_precision)
+ if (this->export_settings.get_limit_precision())
bc_sanitize_mat(bind_mat, LIMITTED_PRECISION);
addBindShapeTransform(bind_mat);
@@ -532,8 +539,7 @@ std::string ControllerExporter::add_inv_bind_mats_source(Object *ob_arm,
this->export_settings, pchan->bone, bind_mat, pchan->bone->arm_mat, true);
/* SL/OPEN_SIM COMPATIBILITY */
- if (export_settings->open_sim) {
-
+ if (export_settings.get_open_sim()) {
float loc[3];
float rot[3] = {0, 0, 0};
float scale[3];
@@ -547,9 +553,15 @@ std::string ControllerExporter::add_inv_bind_mats_source(Object *ob_arm,
/* make world-space matrix (bind_mat is armature-space) */
mul_m4_m4m4(world, ob_arm->obmat, bind_mat);
+ if (!has_bindmat) {
+ if (export_settings.get_apply_global_orientation()) {
+ bc_apply_global_transform(world, export_settings.get_global_transform());
+ }
+ }
+
invert_m4_m4(mat, world);
UnitConverter::mat4_to_dae(inv_bind_mat, mat);
- if (this->export_settings->limit_precision)
+ if (this->export_settings.get_limit_precision())
bc_sanitize_mat(inv_bind_mat, LIMITTED_PRECISION);
source.appendValues(inv_bind_mat);
}
diff --git a/source/blender/collada/ControllerExporter.h b/source/blender/collada/ControllerExporter.h
index 38d85cb7ebc..200f8431f62 100644
--- a/source/blender/collada/ControllerExporter.h
+++ b/source/blender/collada/ControllerExporter.h
@@ -53,13 +53,17 @@ class SceneExporter;
class ControllerExporter : public COLLADASW::LibraryControllers,
protected TransformWriter,
protected InstanceWriter {
+ private:
+ BlenderContext &blender_context;
+ BCExportSettings export_settings;
+
public:
// XXX exporter writes wrong data for shared armatures. A separate
// controller should be written for each armature-mesh binding how do
// we make controller ids then?
ControllerExporter(BlenderContext &blender_context,
COLLADASW::StreamWriter *sw,
- const ExportSettings *export_settings)
+ BCExportSettings &export_settings)
: COLLADASW::LibraryControllers(sw),
blender_context(blender_context),
export_settings(export_settings)
@@ -75,9 +79,6 @@ class ControllerExporter : public COLLADASW::LibraryControllers,
void operator()(Object *ob);
private:
- BlenderContext &blender_context;
- const ExportSettings *export_settings;
-
#if 0
std::vector<Object *> written_armatures;
diff --git a/source/blender/collada/DocumentExporter.cpp b/source/blender/collada/DocumentExporter.cpp
index c8202eb3cf6..f9232851fbb 100644
--- a/source/blender/collada/DocumentExporter.cpp
+++ b/source/blender/collada/DocumentExporter.cpp
@@ -146,9 +146,9 @@ char *bc_CustomData_get_active_layer_name(const CustomData *data, int type)
return data->layers[layer_index].name;
}
-DocumentExporter::DocumentExporter(BlenderContext &blender_context,
- const ExportSettings *export_settings)
- : blender_context(blender_context), export_settings(export_settings)
+DocumentExporter::DocumentExporter(BlenderContext &blender_context, ExportSettings *exportSettings)
+ : blender_context(blender_context),
+ export_settings(BCExportSettings(exportSettings, blender_context))
{
}
@@ -262,7 +262,7 @@ int DocumentExporter::exportCurrentScene()
asset.getContributor().mAuthoringTool = version_buf;
asset.add();
- LinkNode *export_set = this->export_settings->export_set;
+ LinkNode *export_set = this->export_settings.get_export_set();
// <library_cameras>
if (bc_has_object_type(export_set, OB_CAMERA)) {
CamerasExporter ce(writer, this->export_settings);
@@ -296,7 +296,8 @@ int DocumentExporter::exportCurrentScene()
// <library_controllers>
ArmatureExporter arm_exporter(blender_context, writer, this->export_settings);
ControllerExporter controller_exporter(blender_context, writer, this->export_settings);
- if (bc_has_object_type(export_set, OB_ARMATURE) || this->export_settings->include_shapekeys) {
+ if (bc_has_object_type(export_set, OB_ARMATURE) ||
+ this->export_settings.get_include_shapekeys()) {
controller_exporter.export_controllers();
}
@@ -304,9 +305,9 @@ int DocumentExporter::exportCurrentScene()
SceneExporter se(blender_context, writer, &arm_exporter, this->export_settings);
- if (this->export_settings->include_animations) {
+ if (this->export_settings.get_include_animations()) {
// <library_animations>
- AnimationExporter ae(blender_context, writer, this->export_settings);
+ AnimationExporter ae(writer, this->export_settings);
ae.exportAnimations();
}
@@ -322,10 +323,10 @@ int DocumentExporter::exportCurrentScene()
delete writer;
// Finally move the created document into place
- fprintf(stdout, "Collada export to: %s\n", this->export_settings->filepath);
- int status = BLI_rename(native_filename.c_str(), this->export_settings->filepath);
+ fprintf(stdout, "Collada export to: %s\n", this->export_settings.get_filepath());
+ int status = BLI_rename(native_filename.c_str(), this->export_settings.get_filepath());
if (status != 0) {
- status = BLI_copy(native_filename.c_str(), this->export_settings->filepath);
+ status = BLI_copy(native_filename.c_str(), this->export_settings.get_filepath());
BLI_delete(native_filename.c_str(), false, false);
}
return status;
diff --git a/source/blender/collada/DocumentExporter.h b/source/blender/collada/DocumentExporter.h
index a5608d13a71..70722ae601e 100644
--- a/source/blender/collada/DocumentExporter.h
+++ b/source/blender/collada/DocumentExporter.h
@@ -31,13 +31,13 @@ extern "C" {
class DocumentExporter {
public:
- DocumentExporter(BlenderContext &blender_context, const ExportSettings *export_settings);
+ DocumentExporter(BlenderContext &blender_context, ExportSettings *export_settings);
int exportCurrentScene();
void exportScenes(const char *filename);
private:
BlenderContext &blender_context;
- const ExportSettings *export_settings;
+ BCExportSettings export_settings;
KeyImageMap key_image_map;
};
diff --git a/source/blender/collada/DocumentImporter.cpp b/source/blender/collada/DocumentImporter.cpp
index 3aceebe0422..60813fb951c 100644
--- a/source/blender/collada/DocumentImporter.cpp
+++ b/source/blender/collada/DocumentImporter.cpp
@@ -1125,7 +1125,6 @@ bool DocumentImporter::writeAnimation(const COLLADAFW::Animation *anim)
if (mImportStage == Fetching_Controller_data)
return true;
- /* return true; */
return anim_importer.write_animation(anim);
}
diff --git a/source/blender/collada/EffectExporter.cpp b/source/blender/collada/EffectExporter.cpp
index a6e75ba41a9..61603226dfd 100644
--- a/source/blender/collada/EffectExporter.cpp
+++ b/source/blender/collada/EffectExporter.cpp
@@ -53,7 +53,7 @@ static std::string getActiveUVLayerName(Object *ob)
}
EffectsExporter::EffectsExporter(COLLADASW::StreamWriter *sw,
- const ExportSettings *export_settings,
+ BCExportSettings &export_settings,
KeyImageMap &key_image_map)
: COLLADASW::LibraryEffects(sw), export_settings(export_settings), key_image_map(key_image_map)
{
@@ -84,7 +84,8 @@ void EffectsExporter::exportEffects(bContext *C, Scene *sce)
this->scene = sce;
openLibrary();
MaterialFunctor mf;
- mf.forEachMaterialInExportSet<EffectsExporter>(sce, *this, this->export_settings->export_set);
+ mf.forEachMaterialInExportSet<EffectsExporter>(
+ sce, *this, this->export_settings.get_export_set());
closeLibrary();
}
diff --git a/source/blender/collada/EffectExporter.h b/source/blender/collada/EffectExporter.h
index 25df2d7eb89..75511800081 100644
--- a/source/blender/collada/EffectExporter.h
+++ b/source/blender/collada/EffectExporter.h
@@ -40,7 +40,7 @@
class EffectsExporter : COLLADASW::LibraryEffects {
public:
EffectsExporter(COLLADASW::StreamWriter *sw,
- const ExportSettings *export_settings,
+ BCExportSettings &export_settings,
KeyImageMap &key_image_map);
void exportEffects(bContext *C, Scene *sce);
@@ -73,7 +73,7 @@ class EffectsExporter : COLLADASW::LibraryEffects {
bool hasEffects(Scene *sce);
- const ExportSettings *export_settings;
+ BCExportSettings &export_settings;
KeyImageMap &key_image_map;
Scene *scene;
bContext *mContext;
diff --git a/source/blender/collada/ExportSettings.h b/source/blender/collada/ExportSettings.h
index a362b72be00..36f3ea40da9 100644
--- a/source/blender/collada/ExportSettings.h
+++ b/source/blender/collada/ExportSettings.h
@@ -22,10 +22,13 @@
#define __EXPORTSETTINGS_H__
#ifdef __cplusplus
+# include <vector>
+
extern "C" {
#endif
#include "BLI_linklist.h"
+#include "BlenderContext.h"
typedef enum BC_export_mesh_type {
BC_MESH_TYPE_VIEW,
@@ -34,7 +37,7 @@ typedef enum BC_export_mesh_type {
typedef enum BC_export_transformation_type {
BC_TRANSFORMATION_TYPE_MATRIX,
- BC_TRANSFORMATION_TYPE_TRANSROTLOC,
+ BC_TRANSFORMATION_TYPE_DECOMPOSED,
} BC_export_transformation_type;
typedef enum BC_export_animation_type {
@@ -52,6 +55,10 @@ typedef enum BC_ui_export_section {
typedef struct ExportSettings {
bool apply_modifiers;
+ BC_global_forward_axis global_forward;
+ BC_global_up_axis global_up;
+ bool apply_global_orientation;
+
BC_export_mesh_type export_mesh_type;
bool selected;
@@ -74,7 +81,8 @@ typedef struct ExportSettings {
bool use_object_instantiation;
bool use_blender_profile;
bool sort_by_name;
- BC_export_transformation_type export_transformation_type;
+ BC_export_transformation_type object_transformation_type;
+ BC_export_transformation_type animation_transformation_type;
bool open_sim;
bool limit_precision;
@@ -86,6 +94,201 @@ typedef struct ExportSettings {
#ifdef __cplusplus
}
+
+void bc_get_children(std::vector<Object *> &child_set, Object *ob, ViewLayer *view_layer);
+
+class BCExportSettings {
+
+ private:
+ const ExportSettings &export_settings;
+ BlenderContext &blender_context;
+ const BCMatrix global_transform;
+
+ public:
+ BCExportSettings(ExportSettings *exportSettings, BlenderContext &blenderContext)
+ : export_settings(*exportSettings),
+ blender_context(blenderContext),
+ global_transform(BCMatrix(exportSettings->global_forward, exportSettings->global_up))
+
+ {
+ }
+
+ const BCMatrix &get_global_transform()
+ {
+ return global_transform;
+ }
+
+ bool get_apply_modifiers()
+ {
+ return export_settings.apply_modifiers;
+ }
+
+ BC_global_forward_axis get_global_forward()
+ {
+ return export_settings.global_forward;
+ }
+
+ BC_global_up_axis get_global_up()
+ {
+ return export_settings.global_up;
+ }
+
+ bool get_apply_global_orientation()
+ {
+ return export_settings.apply_global_orientation;
+ }
+
+ BC_export_mesh_type get_export_mesh_type()
+ {
+ return export_settings.export_mesh_type;
+ }
+
+ bool get_selected()
+ {
+ return export_settings.selected;
+ }
+
+ bool get_include_children()
+ {
+ return export_settings.include_children;
+ }
+
+ bool get_include_armatures()
+ {
+ return export_settings.include_armatures;
+ }
+
+ bool get_include_shapekeys()
+ {
+ return export_settings.include_shapekeys;
+ }
+
+ bool get_deform_bones_only()
+ {
+ return export_settings.deform_bones_only;
+ }
+
+ bool get_include_animations()
+ {
+ return export_settings.include_animations;
+ }
+
+ bool get_include_all_actions()
+ {
+ return export_settings.include_all_actions;
+ }
+
+ int get_sampling_rate()
+ {
+ return export_settings.sampling_rate;
+ }
+
+ bool get_keep_smooth_curves()
+ {
+ return export_settings.keep_smooth_curves;
+ }
+
+ bool get_keep_keyframes()
+ {
+ return export_settings.keep_keyframes;
+ }
+
+ bool get_keep_flat_curves()
+ {
+ return export_settings.keep_flat_curves;
+ }
+
+ bool get_active_uv_only()
+ {
+ return export_settings.active_uv_only;
+ }
+
+ BC_export_animation_type get_export_animation_type()
+ {
+ return export_settings.export_animation_type;
+ }
+
+ bool get_use_texture_copies()
+ {
+ return export_settings.use_texture_copies;
+ }
+
+ bool get_triangulate()
+ {
+ return export_settings.triangulate;
+ }
+
+ bool get_use_object_instantiation()
+ {
+ return export_settings.use_object_instantiation;
+ }
+
+ bool get_use_blender_profile()
+ {
+ return export_settings.use_blender_profile;
+ }
+
+ bool get_sort_by_name()
+ {
+ return export_settings.sort_by_name;
+ }
+
+ BC_export_transformation_type get_object_transformation_type()
+ {
+ return export_settings.object_transformation_type;
+ }
+
+ BC_export_transformation_type get_animation_transformation_type()
+ {
+ return export_settings.animation_transformation_type;
+ }
+
+ bool get_open_sim()
+ {
+ return export_settings.open_sim;
+ }
+
+ bool get_limit_precision()
+ {
+ return export_settings.limit_precision;
+ }
+
+ bool get_keep_bind_info()
+ {
+ return export_settings.keep_bind_info;
+ }
+
+ char *get_filepath()
+ {
+ return export_settings.filepath;
+ }
+
+ LinkNode *get_export_set()
+ {
+ return export_settings.export_set;
+ }
+
+ BlenderContext &get_blender_context()
+ {
+ return blender_context;
+ }
+
+ Scene *get_scene()
+ {
+ return blender_context.get_scene();
+ }
+
+ ViewLayer *get_view_layer()
+ {
+ return blender_context.get_view_layer();
+ }
+
+ bool is_export_root(Object *ob)
+ {
+ return bc_is_base_node(get_export_set(), ob, get_view_layer());
+ }
+};
+
#endif
#endif
diff --git a/source/blender/collada/GeometryExporter.cpp b/source/blender/collada/GeometryExporter.cpp
index bda6fec70a8..5125a9a0562 100644
--- a/source/blender/collada/GeometryExporter.cpp
+++ b/source/blender/collada/GeometryExporter.cpp
@@ -48,19 +48,20 @@ void GeometryExporter::exportGeom()
openLibrary();
GeometryFunctor gf;
- gf.forEachMeshObjectInExportSet<GeometryExporter>(sce, *this, this->export_settings->export_set);
+ gf.forEachMeshObjectInExportSet<GeometryExporter>(
+ sce, *this, this->export_settings.get_export_set());
closeLibrary();
}
void GeometryExporter::operator()(Object *ob)
{
- bool use_instantiation = this->export_settings->use_object_instantiation;
+ bool use_instantiation = this->export_settings.get_use_object_instantiation();
Mesh *me = bc_get_mesh_copy(blender_context,
ob,
- this->export_settings->export_mesh_type,
- this->export_settings->apply_modifiers,
- this->export_settings->triangulate);
+ this->export_settings.get_export_mesh_type(),
+ this->export_settings.get_apply_modifiers(),
+ this->export_settings.get_triangulate());
std::string geom_id = get_geometry_id(ob, use_instantiation);
std::vector<Normal> nor;
@@ -128,7 +129,7 @@ void GeometryExporter::operator()(Object *ob)
closeGeometry();
- if (this->export_settings->include_shapekeys) {
+ if (this->export_settings.get_include_shapekeys()) {
Key *key = BKE_key_from_object(ob);
if (key) {
KeyBlock *kb = (KeyBlock *)key->block.first;
@@ -380,14 +381,14 @@ void GeometryExporter::create_mesh_primitive_list(short material_index,
int active_uv_index = CustomData_get_active_layer_index(&me->ldata, CD_MLOOPUV);
for (int i = 0; i < num_layers; i++) {
int layer_index = CustomData_get_layer_index_n(&me->ldata, CD_MLOOPUV, i);
- if (!this->export_settings->active_uv_only || layer_index == active_uv_index) {
+ if (!this->export_settings.get_active_uv_only() || layer_index == active_uv_index) {
// char *name = CustomData_get_layer_name(&me->ldata, CD_MLOOPUV, i);
COLLADASW::Input texcoord_input(
COLLADASW::InputSemantic::TEXCOORD,
- makeUrl(makeTexcoordSourceId(geom_id, i, this->export_settings->active_uv_only)),
+ makeUrl(makeTexcoordSourceId(geom_id, i, this->export_settings.get_active_uv_only())),
2, // this is only until we have optimized UV sets
- (this->export_settings->active_uv_only) ? 0 : layer_index - 1 /* set (0,1,2,...) */
+ (this->export_settings.get_active_uv_only()) ? 0 : layer_index - 1 /* set (0,1,2,...) */
);
til.push_back(texcoord_input);
}
@@ -466,7 +467,14 @@ void GeometryExporter::createVertsSource(std::string geom_id, Mesh *me)
/* appends data to <float_array> */
int i = 0;
for (i = 0; i < totverts; i++) {
- source.appendValues(verts[i].co[0], verts[i].co[1], verts[i].co[2]);
+ Vector co;
+ if (export_settings.get_apply_global_orientation()) {
+ bc_add_global_transform(co, verts[i].co, export_settings.get_global_transform());
+ }
+ else {
+ copy_v3_v3(co, verts[i].co);
+ }
+ source.appendValues(co[0], co[1], co[2]);
}
source.finish();
@@ -547,12 +555,12 @@ void GeometryExporter::createTexcoordsSource(std::string geom_id, Mesh *me)
int active_uv_index = CustomData_get_active_layer_index(&me->ldata, CD_MLOOPUV);
for (int a = 0; a < num_layers; a++) {
int layer_index = CustomData_get_layer_index_n(&me->ldata, CD_MLOOPUV, a);
- if (!this->export_settings->active_uv_only || layer_index == active_uv_index) {
+ if (!this->export_settings.get_active_uv_only() || layer_index == active_uv_index) {
MLoopUV *mloops = (MLoopUV *)CustomData_get_layer_n(&me->ldata, CD_MLOOPUV, a);
COLLADASW::FloatSourceF source(mSW);
std::string layer_id = makeTexcoordSourceId(
- geom_id, a, this->export_settings->active_uv_only);
+ geom_id, a, this->export_settings.get_active_uv_only());
source.setId(layer_id);
source.setArrayId(layer_id + ARRAY_ID_SUFFIX);
@@ -606,7 +614,12 @@ void GeometryExporter::createNormalsSource(std::string geom_id, Mesh *me, std::v
std::vector<Normal>::iterator it;
for (it = nor.begin(); it != nor.end(); it++) {
Normal &n = *it;
- source.appendValues(n.x, n.y, n.z);
+
+ Vector no{n.x, n.y, n.z};
+ if (export_settings.get_apply_global_orientation()) {
+ bc_add_global_transform(no, export_settings.get_global_transform());
+ }
+ source.appendValues(no[0], no[1], no[2]);
}
source.finish();
diff --git a/source/blender/collada/GeometryExporter.h b/source/blender/collada/GeometryExporter.h
index 976059b0925..7262784db82 100644
--- a/source/blender/collada/GeometryExporter.h
+++ b/source/blender/collada/GeometryExporter.h
@@ -41,8 +41,6 @@
struct Depsgraph;
-extern Object *bc_get_highest_selected_ancestor_or_self(Object *ob);
-
class Normal {
public:
float x;
@@ -66,7 +64,7 @@ class GeometryExporter : COLLADASW::LibraryGeometries {
/* TODO: optimize UV sets by making indexed list with duplicates removed */
GeometryExporter(BlenderContext &blender_context,
COLLADASW::StreamWriter *sw,
- const ExportSettings *export_settings)
+ BCExportSettings &export_settings)
: COLLADASW::LibraryGeometries(sw),
blender_context(blender_context),
export_settings(export_settings)
@@ -122,7 +120,7 @@ class GeometryExporter : COLLADASW::LibraryGeometries {
private:
std::set<std::string> exportedGeometry;
BlenderContext &blender_context;
- const ExportSettings *export_settings;
+ BCExportSettings &export_settings;
Mesh *get_mesh(Scene *sce, Object *ob, int apply_modifiers);
};
diff --git a/source/blender/collada/ImageExporter.cpp b/source/blender/collada/ImageExporter.cpp
index b606799efde..71201c8a55c 100644
--- a/source/blender/collada/ImageExporter.cpp
+++ b/source/blender/collada/ImageExporter.cpp
@@ -43,7 +43,7 @@ extern "C" {
#include "MaterialExporter.h"
ImagesExporter::ImagesExporter(COLLADASW::StreamWriter *sw,
- const ExportSettings *export_settings,
+ BCExportSettings &export_settings,
KeyImageMap &key_image_map)
: COLLADASW::LibraryImages(sw), export_settings(export_settings), key_image_map(key_image_map)
{
@@ -76,7 +76,7 @@ void ImagesExporter::export_UV_Image(Image *image, bool use_copies)
char export_file[FILE_MAX];
/* Destination folder for exported assets */
- BLI_split_dir_part(this->export_settings->filepath, export_dir, sizeof(export_dir));
+ BLI_split_dir_part(this->export_settings.get_filepath(), export_dir, sizeof(export_dir));
if (is_generated || is_dirty || use_copies || is_packed) {
@@ -152,7 +152,7 @@ void ImagesExporter::export_UV_Image(Image *image, bool use_copies)
void ImagesExporter::exportImages(Scene *sce)
{
- bool use_texture_copies = this->export_settings->use_texture_copies;
+ bool use_texture_copies = this->export_settings.get_use_texture_copies();
openLibrary();
KeyImageMap::iterator iter;
diff --git a/source/blender/collada/ImageExporter.h b/source/blender/collada/ImageExporter.h
index ac0c1d5c976..b72d2709382 100644
--- a/source/blender/collada/ImageExporter.h
+++ b/source/blender/collada/ImageExporter.h
@@ -38,12 +38,12 @@
class ImagesExporter : COLLADASW::LibraryImages {
public:
ImagesExporter(COLLADASW::StreamWriter *sw,
- const ExportSettings *export_settings,
+ BCExportSettings &export_settings,
KeyImageMap &key_image_map);
void exportImages(Scene *sce);
private:
- const ExportSettings *export_settings;
+ BCExportSettings &export_settings;
KeyImageMap &key_image_map;
void export_UV_Image(Image *image, bool use_texture_copies);
};
diff --git a/source/blender/collada/LightExporter.cpp b/source/blender/collada/LightExporter.cpp
index 39721b2eb3c..463981ceefa 100644
--- a/source/blender/collada/LightExporter.cpp
+++ b/source/blender/collada/LightExporter.cpp
@@ -41,7 +41,7 @@ void forEachLightObjectInExportSet(Scene *sce, Functor &f, LinkNode *export_set)
}
}
-LightsExporter::LightsExporter(COLLADASW::StreamWriter *sw, const ExportSettings *export_settings)
+LightsExporter::LightsExporter(COLLADASW::StreamWriter *sw, BCExportSettings &export_settings)
: COLLADASW::LibraryLights(sw), export_settings(export_settings)
{
}
@@ -50,7 +50,7 @@ void LightsExporter::exportLights(Scene *sce)
{
openLibrary();
- forEachLightObjectInExportSet(sce, *this, this->export_settings->export_set);
+ forEachLightObjectInExportSet(sce, *this, this->export_settings.get_export_set());
closeLibrary();
}
diff --git a/source/blender/collada/LightExporter.h b/source/blender/collada/LightExporter.h
index fc468f1f4a3..045ccfe1ce8 100644
--- a/source/blender/collada/LightExporter.h
+++ b/source/blender/collada/LightExporter.h
@@ -32,13 +32,13 @@
class LightsExporter : COLLADASW::LibraryLights {
public:
- LightsExporter(COLLADASW::StreamWriter *sw, const ExportSettings *export_settings);
+ LightsExporter(COLLADASW::StreamWriter *sw, BCExportSettings &export_settings);
void exportLights(Scene *sce);
void operator()(Object *ob);
private:
bool exportBlenderProfile(COLLADASW::Light &cla, Light *la);
- const ExportSettings *export_settings;
+ BCExportSettings &export_settings;
};
#endif
diff --git a/source/blender/collada/MaterialExporter.cpp b/source/blender/collada/MaterialExporter.cpp
index e071712b20d..8bf7a220c4a 100644
--- a/source/blender/collada/MaterialExporter.cpp
+++ b/source/blender/collada/MaterialExporter.cpp
@@ -23,7 +23,7 @@
#include "collada_internal.h"
MaterialsExporter::MaterialsExporter(COLLADASW::StreamWriter *sw,
- const ExportSettings *export_settings)
+ BCExportSettings &export_settings)
: COLLADASW::LibraryMaterials(sw), export_settings(export_settings)
{
/* pass */
@@ -36,7 +36,7 @@ void MaterialsExporter::exportMaterials(Scene *sce)
MaterialFunctor mf;
mf.forEachMaterialInExportSet<MaterialsExporter>(
- sce, *this, this->export_settings->export_set);
+ sce, *this, this->export_settings.get_export_set());
closeLibrary();
}
@@ -45,7 +45,7 @@ void MaterialsExporter::exportMaterials(Scene *sce)
bool MaterialsExporter::hasMaterials(Scene *sce)
{
LinkNode *node;
- for (node = this->export_settings->export_set; node; node = node->next) {
+ for (node = this->export_settings.get_export_set(); node; node = node->next) {
Object *ob = (Object *)node->link;
int a;
for (a = 0; a < ob->totcol; a++) {
diff --git a/source/blender/collada/MaterialExporter.h b/source/blender/collada/MaterialExporter.h
index d47a001596d..027fba1f8ef 100644
--- a/source/blender/collada/MaterialExporter.h
+++ b/source/blender/collada/MaterialExporter.h
@@ -41,13 +41,13 @@ extern "C" {
class MaterialsExporter : COLLADASW::LibraryMaterials {
public:
- MaterialsExporter(COLLADASW::StreamWriter *sw, const ExportSettings *export_settings);
+ MaterialsExporter(COLLADASW::StreamWriter *sw, BCExportSettings &export_settings);
void exportMaterials(Scene *sce);
void operator()(Material *ma, Object *ob);
private:
bool hasMaterials(Scene *sce);
- const ExportSettings *export_settings;
+ BCExportSettings &export_settings;
};
// used in forEachMaterialInScene
diff --git a/source/blender/collada/SceneExporter.cpp b/source/blender/collada/SceneExporter.cpp
index 8017790572f..7bf6a145886 100644
--- a/source/blender/collada/SceneExporter.cpp
+++ b/source/blender/collada/SceneExporter.cpp
@@ -23,10 +23,12 @@ extern "C" {
#include "BKE_collection.h"
#include "BKE_object.h"
#include "BLI_listbase.h"
+#include "BKE_library.h"
}
#include "SceneExporter.h"
#include "collada_utils.h"
+#include "BCSampleData.h"
void SceneExporter::exportScene()
{
@@ -43,18 +45,18 @@ void SceneExporter::exportScene()
void SceneExporter::exportHierarchy()
{
LinkNode *node;
- std::vector<Object *> base_objects;
+ ColladaBaseNodes base_objects;
/* Ensure all objects in the export_set are marked */
- for (node = this->export_settings->export_set; node; node = node->next) {
+ for (node = this->export_settings.get_export_set(); node; node = node->next) {
Object *ob = (Object *)node->link;
ob->id.tag |= LIB_TAG_DOIT;
}
/* Now find all exportable base objects (highest in export hierarchy) */
- for (node = this->export_settings->export_set; node; node = node->next) {
+ for (node = this->export_settings.get_export_set(); node; node = node->next) {
Object *ob = (Object *)node->link;
- if (bc_is_base_node(this->export_settings->export_set, ob)) {
+ if (this->export_settings.is_export_root(ob)) {
switch (ob->type) {
case OB_MESH:
case OB_CAMERA:
@@ -62,7 +64,7 @@ void SceneExporter::exportHierarchy()
case OB_EMPTY:
case OB_GPENCIL:
case OB_ARMATURE:
- base_objects.push_back(ob);
+ base_objects.add(ob);
break;
}
}
@@ -70,10 +72,10 @@ void SceneExporter::exportHierarchy()
/* And now export the base objects: */
for (int index = 0; index < base_objects.size(); index++) {
- Object *ob = base_objects[index];
+ Object *ob = base_objects.get(index);
+ writeNode(ob);
if (bc_is_marked(ob)) {
bc_remove_mark(ob);
- writeNodes(ob);
}
}
}
@@ -88,30 +90,31 @@ void SceneExporter::writeNodeList(std::vector<Object *> &child_objects, Object *
* the hidden elements are exported as well. */
for (int i = 0; i < child_objects.size(); ++i) {
Object *child = child_objects[i];
+ writeNode(child);
if (bc_is_marked(child)) {
bc_remove_mark(child);
- writeNodes(child);
}
}
}
-void SceneExporter::writeNodes(Object *ob)
+void SceneExporter::writeNode(Object *ob)
{
ViewLayer *view_layer = blender_context.get_view_layer();
std::vector<Object *> child_objects;
bc_get_children(child_objects, ob, view_layer);
- bool can_export = bc_is_in_Export_set(this->export_settings->export_set, ob, view_layer);
+ bool can_export = bc_is_in_Export_set(this->export_settings.get_export_set(), ob, view_layer);
/* Add associated armature first if available */
bool armature_exported = false;
Object *ob_arm = bc_get_assigned_armature(ob);
if (ob_arm != NULL) {
- armature_exported = bc_is_in_Export_set(this->export_settings->export_set, ob_arm, view_layer);
+ armature_exported = bc_is_in_Export_set(
+ this->export_settings.get_export_set(), ob_arm, view_layer);
if (armature_exported && bc_is_marked(ob_arm)) {
+ writeNode(ob_arm);
bc_remove_mark(ob_arm);
- writeNodes(ob_arm);
armature_exported = true;
}
}
@@ -123,16 +126,12 @@ void SceneExporter::writeNodes(Object *ob)
colladaNode.setType(COLLADASW::Node::NODE);
colladaNode.start();
-
if (ob->type == OB_MESH && armature_exported) {
/* for skinned mesh we write obmat in <bind_shape_matrix> */
- TransformWriter::add_node_transform_identity(colladaNode);
+ TransformWriter::add_node_transform_identity(colladaNode, this->export_settings);
}
else {
- TransformWriter::add_node_transform_ob(colladaNode,
- ob,
- this->export_settings->export_transformation_type,
- this->export_settings->limit_precision);
+ TransformWriter::add_node_transform_ob(colladaNode, ob, this->export_settings);
}
/* <instance_geometry> */
@@ -143,12 +142,12 @@ void SceneExporter::writeNodes(Object *ob)
}
if (!instance_controller_created) {
COLLADASW::InstanceGeometry instGeom(mSW);
- instGeom.setUrl(
- COLLADASW::URI(COLLADABU::Utils::EMPTY_STRING,
- get_geometry_id(ob, this->export_settings->use_object_instantiation)));
+ instGeom.setUrl(COLLADASW::URI(
+ COLLADABU::Utils::EMPTY_STRING,
+ get_geometry_id(ob, this->export_settings.get_use_object_instantiation())));
instGeom.setName(encode_xml(id_name(ob)));
InstanceWriter::add_material_bindings(
- instGeom.getBindMaterial(), ob, this->export_settings->active_uv_only);
+ instGeom.getBindMaterial(), ob, this->export_settings.get_active_uv_only());
instGeom.add();
}
}
@@ -232,7 +231,11 @@ void SceneExporter::writeNodes(Object *ob)
}
}
}
+ bc_remove_mark(ob);
writeNodeList(child_objects, ob);
colladaNode.end();
}
+ else {
+ writeNodeList(child_objects, ob);
+ }
}
diff --git a/source/blender/collada/SceneExporter.h b/source/blender/collada/SceneExporter.h
index dc0a0c3e2ad..a61d045ad5d 100644
--- a/source/blender/collada/SceneExporter.h
+++ b/source/blender/collada/SceneExporter.h
@@ -82,9 +82,10 @@ extern "C" {
#include "COLLADASWBaseInputElement.h"
#include "ArmatureExporter.h"
-
#include "ExportSettings.h"
+extern void bc_get_children(std::vector<Object *> &child_set, Object *ob, ViewLayer *view_layer);
+
class SceneExporter : COLLADASW::LibraryVisualScenes,
protected TransformWriter,
protected InstanceWriter {
@@ -92,7 +93,7 @@ class SceneExporter : COLLADASW::LibraryVisualScenes,
SceneExporter(BlenderContext &blender_context,
COLLADASW::StreamWriter *sw,
ArmatureExporter *arm,
- const ExportSettings *export_settings)
+ BCExportSettings &export_settings)
: COLLADASW::LibraryVisualScenes(sw),
blender_context(blender_context),
arm_exporter(arm),
@@ -106,11 +107,11 @@ class SceneExporter : COLLADASW::LibraryVisualScenes,
BlenderContext &blender_context;
friend class ArmatureExporter;
ArmatureExporter *arm_exporter;
- const ExportSettings *export_settings;
+ BCExportSettings &export_settings;
void exportHierarchy();
void writeNodeList(std::vector<Object *> &child_objects, Object *parent);
- void writeNodes(Object *ob);
+ void writeNode(Object *ob);
};
#endif
diff --git a/source/blender/collada/TransformWriter.cpp b/source/blender/collada/TransformWriter.cpp
index 2ab9105976e..560ce8a359f 100644
--- a/source/blender/collada/TransformWriter.cpp
+++ b/source/blender/collada/TransformWriter.cpp
@@ -25,12 +25,12 @@
#include "TransformWriter.h"
-void TransformWriter::add_node_transform(COLLADASW::Node &node,
- float mat[4][4],
- float parent_mat[4][4],
- bool limit_precision)
+void TransformWriter::add_joint_transform(COLLADASW::Node &node,
+ float mat[4][4],
+ float parent_mat[4][4],
+ BCExportSettings &export_settings,
+ bool has_restmat)
{
- float loc[3], rot[3], scale[3];
float local[4][4];
if (parent_mat) {
@@ -42,67 +42,45 @@ void TransformWriter::add_node_transform(COLLADASW::Node &node,
copy_m4_m4(local, mat);
}
+ if (!has_restmat && export_settings.get_apply_global_orientation()) {
+ bc_apply_global_transform(local, export_settings.get_global_transform());
+ }
+
double dmat[4][4];
UnitConverter *converter = new UnitConverter();
converter->mat4_to_dae_double(dmat, local);
delete converter;
- bc_decompose(local, loc, rot, NULL, scale);
-
- if (node.getType() == COLLADASW::Node::JOINT) {
- // XXX Why are joints handled differently ?
+ if (export_settings.get_object_transformation_type() == BC_TRANSFORMATION_TYPE_MATRIX) {
node.addMatrix("transform", dmat);
}
else {
+ float loc[3], rot[3], scale[3];
+ bc_decompose(local, loc, rot, NULL, scale);
add_transform(node, loc, rot, scale);
}
}
void TransformWriter::add_node_transform_ob(COLLADASW::Node &node,
Object *ob,
- BC_export_transformation_type transformation_type,
- bool limit_precision)
+ BCExportSettings &export_settings)
{
-#if 0
- float rot[3], loc[3], scale[3];
-
- if (ob->parent) {
- float C[4][4], tmat[4][4], imat[4][4], mat[4][4];
-
- // factor out scale from obmat
-
- copy_v3_v3(scale, ob->scale);
-
- ob->scale[0] = ob->scale[1] = ob->scale[2] = 1.0f;
- BKE_object_to_mat4(ob, C);
- copy_v3_v3(ob->scale, scale);
+ BC_export_transformation_type transformation_type =
+ export_settings.get_object_transformation_type();
+ bool limit_precision = export_settings.get_limit_precision();
- mul_m4_series(tmat, ob->parent->obmat, ob->parentinv, C);
-
- // calculate local mat
-
- invert_m4_m4(imat, ob->parent->obmat);
- mul_m4_m4m4(mat, imat, tmat);
-
- // done
+ /* Export the local Matrix (relative to the object parent,
+ * be it an object, bone or vertex(-tices)). */
+ Matrix f_obmat;
+ BKE_object_matrix_local_get(ob, f_obmat);
- mat4_to_eul(rot, mat);
- copy_v3_v3(loc, mat[3]);
+ if (export_settings.get_apply_global_orientation()) {
+ bc_apply_global_transform(f_obmat, export_settings.get_global_transform());
}
else {
- copy_v3_v3(loc, ob->loc);
- copy_v3_v3(rot, ob->rot);
- copy_v3_v3(scale, ob->scale);
+ bc_add_global_transform(f_obmat, export_settings.get_global_transform());
}
- add_transform(node, loc, rot, scale);
-#endif
-
- /* Export the local Matrix (relative to the object parent,
- * be it an object, bone or vertex(-tices)). */
- float f_obmat[4][4];
- BKE_object_matrix_local_get(ob, f_obmat);
-
switch (transformation_type) {
case BC_TRANSFORMATION_TYPE_MATRIX: {
UnitConverter converter;
@@ -113,7 +91,7 @@ void TransformWriter::add_node_transform_ob(COLLADASW::Node &node,
node.addMatrix("transform", d_obmat);
break;
}
- case BC_TRANSFORMATION_TYPE_TRANSROTLOC: {
+ case BC_TRANSFORMATION_TYPE_DECOMPOSED: {
float loc[3], rot[3], scale[3];
bc_decompose(f_obmat, loc, rot, NULL, scale);
if (limit_precision) {
@@ -127,10 +105,27 @@ void TransformWriter::add_node_transform_ob(COLLADASW::Node &node,
}
}
-void TransformWriter::add_node_transform_identity(COLLADASW::Node &node)
+void TransformWriter::add_node_transform_identity(COLLADASW::Node &node,
+ BCExportSettings &export_settings)
{
- float loc[3] = {0.0f, 0.0f, 0.0f}, scale[3] = {1.0f, 1.0f, 1.0f}, rot[3] = {0.0f, 0.0f, 0.0f};
- add_transform(node, loc, rot, scale);
+ BC_export_transformation_type transformation_type =
+ export_settings.get_object_transformation_type();
+ switch (transformation_type) {
+ case BC_TRANSFORMATION_TYPE_MATRIX: {
+ BCMatrix mat;
+ DMatrix d_obmat;
+ mat.get_matrix(d_obmat);
+ node.addMatrix("transform", d_obmat);
+ break;
+ }
+ default: {
+ float loc[3] = {0.0f, 0.0f, 0.0f};
+ float scale[3] = {1.0f, 1.0f, 1.0f};
+ float rot[3] = {0.0f, 0.0f, 0.0f};
+ add_transform(node, loc, rot, scale);
+ break;
+ }
+ }
}
void TransformWriter::add_transform(COLLADASW::Node &node,
diff --git a/source/blender/collada/TransformWriter.h b/source/blender/collada/TransformWriter.h
index 22ba0716cfe..d2e4b369cdc 100644
--- a/source/blender/collada/TransformWriter.h
+++ b/source/blender/collada/TransformWriter.h
@@ -31,17 +31,15 @@
class TransformWriter {
protected:
- void add_node_transform(COLLADASW::Node &node,
- float mat[4][4],
- float parent_mat[4][4],
- bool limit_precision = false);
+ void add_joint_transform(COLLADASW::Node &node,
+ float mat[4][4],
+ float parent_mat[4][4],
+ BCExportSettings &export_settings,
+ bool has_restmat);
- void add_node_transform_ob(COLLADASW::Node &node,
- Object *ob,
- BC_export_transformation_type transformation_type,
- bool limit_precision = false);
+ void add_node_transform_ob(COLLADASW::Node &node, Object *ob, BCExportSettings &export_settings);
- void add_node_transform_identity(COLLADASW::Node &node);
+ void add_node_transform_identity(COLLADASW::Node &node, BCExportSettings &export_settings);
private:
void add_transform(COLLADASW::Node &node, float loc[3], float rot[3], float scale[3]);
diff --git a/source/blender/collada/collada_utils.cpp b/source/blender/collada/collada_utils.cpp
index 9f2d3f951ec..9e8896c2b9f 100644
--- a/source/blender/collada/collada_utils.cpp
+++ b/source/blender/collada/collada_utils.cpp
@@ -60,6 +60,7 @@ extern "C" {
#include "ED_armature.h"
#include "ED_screen.h"
#include "ED_node.h"
+#include "ED_object.h"
#include "MEM_guardedalloc.h"
@@ -104,26 +105,6 @@ int bc_test_parent_loop(Object *par, Object *ob)
return bc_test_parent_loop(par->parent, ob);
}
-void bc_get_children(std::vector<Object *> &child_set, Object *ob, ViewLayer *view_layer)
-{
- Base *base;
- for (base = (Base *)view_layer->object_bases.first; base; base = base->next) {
- Object *cob = base->object;
- if (cob->parent == ob) {
- switch (ob->type) {
- case OB_MESH:
- case OB_CAMERA:
- case OB_LAMP:
- case OB_EMPTY:
- case OB_ARMATURE:
- child_set.push_back(cob);
- default:
- break;
- }
- }
- }
-}
-
bool bc_validateConstraints(bConstraint *con)
{
const bConstraintTypeInfo *cti = BKE_constraint_typeinfo_get(con);
@@ -146,43 +127,19 @@ bool bc_validateConstraints(bConstraint *con)
return true;
}
-/* a shortened version of parent_set_exec()
- * if is_parent_space is true then ob->obmat will be multiplied by par->obmat before parenting */
-int bc_set_parent(Object *ob, Object *par, bContext *C, bool is_parent_space)
+bool bc_set_parent(Object *ob, Object *par, bContext *C, bool is_parent_space)
{
- Object workob;
- Depsgraph *depsgraph = CTX_data_depsgraph(C);
- Scene *sce = CTX_data_scene(C);
-
- if (!par || bc_test_parent_loop(par, ob))
- return false;
-
- ob->parent = par;
- ob->partype = PAROBJECT;
-
- ob->parsubstr[0] = 0;
+ Scene *scene = CTX_data_scene(C);
+ int partype = PAR_OBJECT;
+ const bool xmirror = false;
+ const bool keep_transform = false;
- if (is_parent_space) {
- float mat[4][4];
- /* calc par->obmat */
- BKE_object_where_is_calc(depsgraph, sce, par);
-
- /* move child obmat into world space */
- mul_m4_m4m4(mat, par->obmat, ob->obmat);
- copy_m4_m4(ob->obmat, mat);
+ if (par && is_parent_space) {
+ mul_m4_m4m4(ob->obmat, par->obmat, ob->obmat);
}
- /* apply child obmat (i.e. decompose it into rot/loc/size) */
- BKE_object_apply_mat4(ob, ob->obmat, 0, 0);
-
- /* compute parentinv */
- BKE_object_workob_calc_parent(depsgraph, sce, ob, &workob);
- invert_m4_m4(ob->parentinv, workob.obmat);
-
- DEG_id_tag_update(&ob->id, ID_RECALC_TRANSFORM | ID_RECALC_GEOMETRY);
- DEG_id_tag_update(&par->id, ID_RECALC_TRANSFORM);
-
- return true;
+ bool ok = ED_object_parent_set(NULL, C, scene, ob, par, partype, xmirror, keep_transform, NULL);
+ return ok;
}
std::vector<bAction *> bc_getSceneActions(const bContext *C, Object *ob, bool all_actions)
@@ -309,49 +266,6 @@ Object *bc_get_assigned_armature(Object *ob)
return ob_arm;
}
-/**
- * Returns the highest selected ancestor
- * returns NULL if no ancestor is selected
- * IMPORTANT: This function expects that all exported objects have set:
- * ob->id.tag & LIB_TAG_DOIT
- */
-Object *bc_get_highest_selected_ancestor_or_self(LinkNode *export_set, Object *ob)
-
-{
- Object *ancestor = ob;
- while (ob->parent && bc_is_marked(ob->parent)) {
- ob = ob->parent;
- ancestor = ob;
- }
- return ancestor;
-}
-
-bool bc_is_base_node(LinkNode *export_set, Object *ob)
-{
- Object *root = bc_get_highest_selected_ancestor_or_self(export_set, ob);
- return (root == ob);
-}
-
-bool bc_is_in_Export_set(LinkNode *export_set, Object *ob, ViewLayer *view_layer)
-{
- bool to_export = (BLI_linklist_index(export_set, ob) != -1);
-
- if (!to_export) {
- /* Mark this object as to_export even if it is not in the
- * export list, but it contains children to export. */
-
- std::vector<Object *> children;
- bc_get_children(children, ob, view_layer);
- for (int i = 0; i < children.size(); i++) {
- if (bc_is_in_Export_set(export_set, children[i], view_layer)) {
- to_export = true;
- break;
- }
- }
- }
- return to_export;
-}
-
bool bc_has_object_type(LinkNode *export_set, short obtype)
{
LinkNode *node;
@@ -366,21 +280,6 @@ bool bc_has_object_type(LinkNode *export_set, short obtype)
return false;
}
-int bc_is_marked(Object *ob)
-{
- return ob && (ob->id.tag & LIB_TAG_DOIT);
-}
-
-void bc_remove_mark(Object *ob)
-{
- ob->id.tag &= ~LIB_TAG_DOIT;
-}
-
-void bc_set_mark(Object *ob)
-{
- ob->id.tag |= LIB_TAG_DOIT;
-}
-
/* Use bubble sort algorithm for sorting the export set */
void bc_bubble_sort_by_Object_name(LinkNode *export_set)
{
@@ -1026,26 +925,75 @@ bool bc_has_animations(Object *ob)
return false;
}
-bool bc_has_animations(Scene *sce, LinkNode &export_set)
+bool bc_has_animations(Scene *sce, LinkNode *export_set)
{
LinkNode *node;
+ if (export_set) {
+ for (node = export_set; node; node = node->next) {
+ Object *ob = (Object *)node->link;
- for (node = &export_set; node; node = node->next) {
- Object *ob = (Object *)node->link;
-
- if (bc_has_animations(ob))
- return true;
+ if (bc_has_animations(ob))
+ return true;
+ }
}
return false;
}
+void bc_add_global_transform(Matrix &to_mat,
+ const Matrix &from_mat,
+ const BCMatrix &global_transform,
+ const bool invert)
+{
+ copy_m4_m4(to_mat, from_mat);
+ bc_add_global_transform(to_mat, global_transform, invert);
+}
+
+void bc_add_global_transform(Vector &to_vec,
+ const Vector &from_vec,
+ const BCMatrix &global_transform,
+ const bool invert)
+{
+ copy_v3_v3(to_vec, from_vec);
+ bc_add_global_transform(to_vec, global_transform, invert);
+}
+
+void bc_add_global_transform(Matrix &to_mat, const BCMatrix &global_transform, const bool invert)
+{
+ BCMatrix mat(to_mat);
+ mat.add_transform(global_transform, invert);
+ mat.get_matrix(to_mat);
+}
+
+void bc_add_global_transform(Vector &to_vec, const BCMatrix &global_transform, const bool invert)
+{
+ Matrix mat;
+ Vector from_vec;
+ copy_v3_v3(from_vec, to_vec);
+ global_transform.get_matrix(mat, false, 6, invert);
+ mul_v3_m4v3(to_vec, mat, from_vec);
+}
+
+void bc_apply_global_transform(Matrix &to_mat, const BCMatrix &global_transform, const bool invert)
+{
+ BCMatrix mat(to_mat);
+ mat.apply_transform(global_transform, invert);
+ mat.get_matrix(to_mat);
+}
+
+void bc_apply_global_transform(Vector &to_vec, const BCMatrix &global_transform, const bool invert)
+{
+ Matrix transform;
+ global_transform.get_matrix(transform);
+ mul_v3_m4v3(to_vec, transform, to_vec);
+}
+
/**
* Check if custom information about bind matrix exists and modify the from_mat
* accordingly.
*
* Note: This is old style for Blender <= 2.78 only kept for compatibility
*/
-void bc_create_restpose_mat(const ExportSettings *export_settings,
+void bc_create_restpose_mat(BCExportSettings &export_settings,
Bone *bone,
float to_mat[4][4],
float from_mat[4][4],
@@ -1056,9 +1004,9 @@ void bc_create_restpose_mat(const ExportSettings *export_settings,
float scale[3];
static const float V0[3] = {0, 0, 0};
- if (!has_custom_props(bone, export_settings->keep_bind_info, "restpose_loc") &&
- !has_custom_props(bone, export_settings->keep_bind_info, "restpose_rot") &&
- !has_custom_props(bone, export_settings->keep_bind_info, "restpose_scale")) {
+ if (!has_custom_props(bone, export_settings.get_keep_bind_info(), "restpose_loc") &&
+ !has_custom_props(bone, export_settings.get_keep_bind_info(), "restpose_rot") &&
+ !has_custom_props(bone, export_settings.get_keep_bind_info(), "restpose_scale")) {
/* No need */
copy_m4_m4(to_mat, from_mat);
return;
@@ -1067,7 +1015,7 @@ void bc_create_restpose_mat(const ExportSettings *export_settings,
bc_decompose(from_mat, loc, rot, NULL, scale);
loc_eulO_size_to_mat4(to_mat, loc, rot, scale, 6);
- if (export_settings->keep_bind_info) {
+ if (export_settings.get_keep_bind_info()) {
bc_get_property_vector(bone, "restpose_loc", loc, loc);
if (use_local_space && bone->parent) {
@@ -1083,7 +1031,7 @@ void bc_create_restpose_mat(const ExportSettings *export_settings,
}
}
- if (export_settings->keep_bind_info) {
+ if (export_settings.get_keep_bind_info()) {
if (bc_get_IDProperty(bone, "restpose_rot_x"))
rot[0] = DEG2RADF(bc_get_property(bone, "restpose_rot_x", 0));
if (bc_get_IDProperty(bone, "restpose_rot_y"))
@@ -1092,7 +1040,7 @@ void bc_create_restpose_mat(const ExportSettings *export_settings,
rot[2] = DEG2RADF(bc_get_property(bone, "restpose_rot_z", 0));
}
- if (export_settings->keep_bind_info) {
+ if (export_settings.get_keep_bind_info()) {
bc_get_property_vector(bone, "restpose_scale", scale, scale);
}
diff --git a/source/blender/collada/collada_utils.h b/source/blender/collada/collada_utils.h
index dfd5519be31..ca40de6fc1d 100644
--- a/source/blender/collada/collada_utils.h
+++ b/source/blender/collada/collada_utils.h
@@ -133,10 +133,9 @@ std::string bc_get_action_id(std::string action_name,
extern float bc_get_float_value(const COLLADAFW::FloatOrDoubleArray &array, unsigned int index);
extern int bc_test_parent_loop(Object *par, Object *ob);
-extern void bc_get_children(std::vector<Object *> &child_set, Object *ob, ViewLayer *view_layer);
extern bool bc_validateConstraints(bConstraint *con);
-extern int bc_set_parent(Object *ob, Object *par, bContext *C, bool is_parent_space = true);
+bool bc_set_parent(Object *ob, Object *par, bContext *C, bool is_parent_space = true);
extern Object *bc_add_object(
Main *bmain, Scene *scene, ViewLayer *view_layer, int type, const char *name);
extern Mesh *bc_get_mesh_copy(BlenderContext &blender_context,
@@ -146,15 +145,8 @@ extern Mesh *bc_get_mesh_copy(BlenderContext &blender_context,
bool triangulate);
extern Object *bc_get_assigned_armature(Object *ob);
-extern Object *bc_get_highest_selected_ancestor_or_self(LinkNode *export_set, Object *ob);
-extern bool bc_is_base_node(LinkNode *export_set, Object *ob);
-extern bool bc_is_in_Export_set(LinkNode *export_set, Object *ob, ViewLayer *view_layer);
extern bool bc_has_object_type(LinkNode *export_set, short obtype);
-extern int bc_is_marked(Object *ob);
-extern void bc_remove_mark(Object *ob);
-extern void bc_set_mark(Object *ob);
-
extern char *bc_CustomData_get_layer_name(const CustomData *data, int type, int n);
extern char *bc_CustomData_get_active_layer_name(const CustomData *data, int type);
@@ -235,15 +227,62 @@ extern bool bc_get_property_matrix(Bone *bone, std::string key, float mat[4][4])
extern void bc_enable_fcurves(bAction *act, char *bone_name);
extern bool bc_bone_matrix_local_get(Object *ob, Bone *bone, Matrix &mat, bool for_opensim);
extern bool bc_is_animated(BCMatrixSampleMap &values);
-extern bool bc_has_animations(Scene *sce, LinkNode &node);
+extern bool bc_has_animations(Scene *sce, LinkNode *node);
extern bool bc_has_animations(Object *ob);
-extern void bc_create_restpose_mat(const ExportSettings *export_settings,
+extern void bc_add_global_transform(Matrix &to_mat,
+ const Matrix &from_mat,
+ const BCMatrix &global_transform,
+ const bool invert = false);
+extern void bc_add_global_transform(Vector &to_vec,
+ const Vector &from_vec,
+ const BCMatrix &global_transform,
+ const bool invert = false);
+extern void bc_add_global_transform(Vector &to_vec,
+ const BCMatrix &global_transform,
+ const bool invert = false);
+extern void bc_add_global_transform(Matrix &to_mat,
+ const BCMatrix &global_transform,
+ const bool invert = false);
+extern void bc_apply_global_transform(Matrix &to_mat,
+ const BCMatrix &global_transform,
+ const bool invert = false);
+extern void bc_apply_global_transform(Vector &to_vec,
+ const BCMatrix &global_transform,
+ const bool invert = false);
+extern void bc_create_restpose_mat(BCExportSettings &export_settings,
Bone *bone,
float to_mat[4][4],
- float world[4][4],
+ float from_mat[4][4],
bool use_local_space);
+class ColladaBaseNodes {
+ private:
+ std::vector<Object *> base_objects;
+
+ public:
+ void add(Object *ob)
+ {
+ base_objects.push_back(ob);
+ }
+
+ bool contains(Object *ob)
+ {
+ std::vector<Object *>::iterator it = std::find(base_objects.begin(), base_objects.end(), ob);
+ return (it != base_objects.end());
+ }
+
+ int size()
+ {
+ return base_objects.size();
+ }
+
+ Object *get(int index)
+ {
+ return base_objects[index];
+ }
+};
+
class BCPolygonNormalsIndices {
std::vector<unsigned int> normal_indices;
@@ -293,7 +332,7 @@ class BoneExtended {
bool has_roll();
float get_roll();
- void set_tail(float *vec);
+ void set_tail(float vec[]);
float *get_tail();
bool has_tail();
diff --git a/source/blender/compositor/operations/COM_ScaleOperation.cpp b/source/blender/compositor/operations/COM_ScaleOperation.cpp
index 1c5b2a71859..37ce832209c 100644
--- a/source/blender/compositor/operations/COM_ScaleOperation.cpp
+++ b/source/blender/compositor/operations/COM_ScaleOperation.cpp
@@ -95,10 +95,10 @@ bool ScaleOperation::determineDependingAreaOfInterest(rcti *input,
const float scx = scaleX[0];
const float scy = scaleY[0];
- newInput.xmax = this->m_centerX + (input->xmax - this->m_centerX) / scx;
- newInput.xmin = this->m_centerX + (input->xmin - this->m_centerX) / scx;
- newInput.ymax = this->m_centerY + (input->ymax - this->m_centerY) / scy;
- newInput.ymin = this->m_centerY + (input->ymin - this->m_centerY) / scy;
+ newInput.xmax = this->m_centerX + (input->xmax - this->m_centerX) / scx + 1;
+ newInput.xmin = this->m_centerX + (input->xmin - this->m_centerX) / scx - 1;
+ newInput.ymax = this->m_centerY + (input->ymax - this->m_centerY) / scy + 1;
+ newInput.ymin = this->m_centerY + (input->ymin - this->m_centerY) / scy - 1;
}
else {
newInput.xmax = this->getWidth();
diff --git a/source/blender/depsgraph/CMakeLists.txt b/source/blender/depsgraph/CMakeLists.txt
index ba6b3b32d60..c3099c9486d 100644
--- a/source/blender/depsgraph/CMakeLists.txt
+++ b/source/blender/depsgraph/CMakeLists.txt
@@ -42,11 +42,13 @@ set(SRC
intern/builder/deg_builder_map.cc
intern/builder/deg_builder_nodes.cc
intern/builder/deg_builder_nodes_rig.cc
+ intern/builder/deg_builder_nodes_scene.cc
intern/builder/deg_builder_nodes_view_layer.cc
intern/builder/deg_builder_pchanmap.cc
intern/builder/deg_builder_relations.cc
intern/builder/deg_builder_relations_keys.cc
intern/builder/deg_builder_relations_rig.cc
+ intern/builder/deg_builder_relations_scene.cc
intern/builder/deg_builder_relations_view_layer.cc
intern/builder/deg_builder_rna.cc
intern/builder/deg_builder_transitive.cc
diff --git a/source/blender/depsgraph/DEG_depsgraph_build.h b/source/blender/depsgraph/DEG_depsgraph_build.h
index 2d0bc6ff15b..15abc0c0a64 100644
--- a/source/blender/depsgraph/DEG_depsgraph_build.h
+++ b/source/blender/depsgraph/DEG_depsgraph_build.h
@@ -52,14 +52,19 @@ extern "C" {
/* Graph Building -------------------------------- */
-/* Build depsgraph for the given scene, and dump results in given
- * graph container.
- */
+/* Build depsgraph for the given scene, and dump results in given graph container. */
void DEG_graph_build_from_view_layer(struct Depsgraph *graph,
struct Main *bmain,
struct Scene *scene,
struct ViewLayer *view_layer);
+/* Special version of builder which produces dependency graph suitable for the render pipeline.
+ * It will contain sequencer and compositor (if needed) and all their dependencies. */
+void DEG_graph_build_for_render_pipeline(struct Depsgraph *graph,
+ struct Main *bmain,
+ struct Scene *scene,
+ struct ViewLayer *view_layer);
+
/* Tag relations from the given graph for update. */
void DEG_graph_tag_relations_update(struct Depsgraph *graph);
diff --git a/source/blender/depsgraph/DEG_depsgraph_query.h b/source/blender/depsgraph/DEG_depsgraph_query.h
index a7b5535d11a..9b7e5b95fdc 100644
--- a/source/blender/depsgraph/DEG_depsgraph_query.h
+++ b/source/blender/depsgraph/DEG_depsgraph_query.h
@@ -29,6 +29,9 @@
#include "DEG_depsgraph.h"
#include "DEG_depsgraph_build.h"
+/* Needed for the instance iterator. */
+#include "DNA_object_types.h"
+
struct ID;
struct BLI_Iterator;
diff --git a/source/blender/depsgraph/intern/builder/deg_builder_map.cc b/source/blender/depsgraph/intern/builder/deg_builder_map.cc
index a519f3e60b5..4bca4f037b0 100644
--- a/source/blender/depsgraph/intern/builder/deg_builder_map.cc
+++ b/source/blender/depsgraph/intern/builder/deg_builder_map.cc
@@ -23,41 +23,52 @@
#include "intern/builder/deg_builder_map.h"
-#include "BLI_utildefines.h"
-#include "BLI_ghash.h"
-
#include "DNA_ID.h"
namespace DEG {
BuilderMap::BuilderMap()
{
- set = BLI_gset_ptr_new("deg builder gset");
}
BuilderMap::~BuilderMap()
{
- BLI_gset_free(set, NULL);
}
-bool BuilderMap::checkIsBuilt(ID *id)
+bool BuilderMap::checkIsBuilt(ID *id, int tag) const
{
- return BLI_gset_haskey(set, id);
+ return (getIDTag(id) & tag) == tag;
}
-void BuilderMap::tagBuild(ID *id)
+void BuilderMap::tagBuild(ID *id, int tag)
{
- BLI_gset_insert(set, id);
+ IDTagMap::iterator it = id_tags_.find(id);
+ if (it == id_tags_.end()) {
+ id_tags_.insert(make_pair(id, tag));
+ return;
+ }
+ it->second |= tag;
}
-bool BuilderMap::checkIsBuiltAndTag(ID *id)
+bool BuilderMap::checkIsBuiltAndTag(ID *id, int tag)
{
- void **key_p;
- if (!BLI_gset_ensure_p_ex(set, id, &key_p)) {
- *key_p = id;
+ IDTagMap::iterator it = id_tags_.find(id);
+ if (it == id_tags_.end()) {
+ id_tags_.insert(make_pair(id, tag));
return false;
}
- return true;
+ const bool result = (it->second & tag) == tag;
+ it->second |= tag;
+ return result;
+}
+
+int BuilderMap::getIDTag(ID *id) const
+{
+ IDTagMap::const_iterator it = id_tags_.find(id);
+ if (it == id_tags_.end()) {
+ return 0;
+ }
+ return it->second;
}
} // namespace DEG
diff --git a/source/blender/depsgraph/intern/builder/deg_builder_map.h b/source/blender/depsgraph/intern/builder/deg_builder_map.h
index c1db1d9d2bb..dd124e07a00 100644
--- a/source/blender/depsgraph/intern/builder/deg_builder_map.h
+++ b/source/blender/depsgraph/intern/builder/deg_builder_map.h
@@ -23,6 +23,8 @@
#pragma once
+#include "intern/depsgraph_type.h"
+
struct GSet;
struct ID;
@@ -30,34 +32,51 @@ namespace DEG {
class BuilderMap {
public:
+ enum {
+ TAG_ANIMATION = (1 << 0),
+ TAG_PARAMETERS = (1 << 1),
+ TAG_TRANSFORM = (1 << 2),
+ TAG_GEOMETRY = (1 << 3),
+
+ TAG_SCENE_COMPOSITOR = (1 << 4),
+ TAG_SCENE_SEQUENCER = (1 << 5),
+
+ /* All ID components has been built. */
+ TAG_COMPLETE = (TAG_ANIMATION | TAG_PARAMETERS | TAG_TRANSFORM | TAG_GEOMETRY |
+ TAG_SCENE_COMPOSITOR | TAG_SCENE_SEQUENCER),
+ };
+
BuilderMap();
~BuilderMap();
- /* Check whether given ID is already handled by builder (or if it's being
- * handled). */
- bool checkIsBuilt(ID *id);
+ /* Check whether given ID is already handled by builder (or if it's being handled). */
+ bool checkIsBuilt(ID *id, int tag = TAG_COMPLETE) const;
/* Tag given ID as handled/built. */
- void tagBuild(ID *id);
+ void tagBuild(ID *id, int tag = TAG_COMPLETE);
- /* Combination of previous two functions, returns truth if ID was already
- * handled, or tags is handled otherwise and return false. */
- bool checkIsBuiltAndTag(ID *id);
+ /* Combination of previous two functions, returns truth if ID was already handled, or tags is
+ * handled otherwise and return false. */
+ bool checkIsBuiltAndTag(ID *id, int tag = TAG_COMPLETE);
- template<typename T> bool checkIsBuilt(T *datablock)
+ template<typename T> bool checkIsBuilt(T *datablock, int tag = TAG_COMPLETE) const
{
- return checkIsBuilt(&datablock->id);
+ return checkIsBuilt(&datablock->id, tag);
}
- template<typename T> void tagBuild(T *datablock)
+ template<typename T> void tagBuild(T *datablock, int tag = TAG_COMPLETE)
{
- tagBuild(&datablock->id);
+ tagBuild(&datablock->id, tag);
}
- template<typename T> bool checkIsBuiltAndTag(T *datablock)
+ template<typename T> bool checkIsBuiltAndTag(T *datablock, int tag = TAG_COMPLETE)
{
- return checkIsBuiltAndTag(&datablock->id);
+ return checkIsBuiltAndTag(&datablock->id, tag);
}
- GSet *set;
+ protected:
+ int getIDTag(ID *id) const;
+
+ typedef map<ID *, int> IDTagMap;
+ IDTagMap id_tags_;
};
} // namespace DEG
diff --git a/source/blender/depsgraph/intern/builder/deg_builder_nodes.cc b/source/blender/depsgraph/intern/builder/deg_builder_nodes.cc
index 0d10bd1d3dc..93e5dd14ae0 100644
--- a/source/blender/depsgraph/intern/builder/deg_builder_nodes.cc
+++ b/source/blender/depsgraph/intern/builder/deg_builder_nodes.cc
@@ -453,6 +453,9 @@ void DepsgraphNodeBuilder::build_id(ID *id)
case ID_CF:
build_cachefile((CacheFile *)id);
break;
+ case ID_SCE:
+ build_scene_parameters((Scene *)id);
+ break;
default:
fprintf(stderr, "Unhandled ID %s\n", id->name);
BLI_assert(!"Should never happen");
@@ -540,7 +543,10 @@ void DepsgraphNodeBuilder::build_object(int base_index,
IDNode *id_node = add_id_node(&object->id);
Object *object_cow = get_cow_datablock(object);
id_node->linked_state = linked_state;
- if (object == scene_->camera) {
+ /* NOTE: Scene is NULL when building dependency graph for render pipeline.
+ * Probably need to assign that to something non-NULL, but then the logic here will still be
+ * somewhat weird. */
+ if (scene_ != NULL && object == scene_->camera) {
id_node->is_directly_visible = true;
}
else {
@@ -681,7 +687,7 @@ void DepsgraphNodeBuilder::build_object_data(Object *object, bool is_object_visi
break;
default: {
ID *obdata = (ID *)object->data;
- if (built_map_.checkIsBuilt(obdata) == 0) {
+ if (!built_map_.checkIsBuilt(obdata)) {
build_animdata(obdata);
}
break;
@@ -1306,6 +1312,9 @@ void DepsgraphNodeBuilder::build_camera(Camera *camera)
}
build_animdata(&camera->id);
build_parameters(&camera->id);
+ if (camera->dof.focus_object != NULL) {
+ build_object(-1, camera->dof.focus_object, DEG_ID_LINKED_INDIRECTLY, false);
+ }
}
void DepsgraphNodeBuilder::build_light(Light *lamp)
@@ -1363,8 +1372,16 @@ void DepsgraphNodeBuilder::build_nodetree(bNodeTree *ntree)
build_object(-1, (Object *)id, DEG_ID_LINKED_INDIRECTLY, true);
}
else if (id_type == ID_SCE) {
- /* Scenes are used by compositor trees, and handled by render
- * pipeline. No need to build dependencies for them here. */
+ Scene *node_scene = (Scene *)id;
+ build_scene_parameters(node_scene);
+ /* Camera is used by defocus node.
+ *
+ * On the one hand it's annoying to always pull it in, but on another hand it's also annoying
+ * to have hardcoded node-type exception here. */
+ if (node_scene->camera != NULL) {
+ /* TODO(sergey): Use visibility of owner of the node tree. */
+ build_object(-1, node_scene->camera, DEG_ID_LINKED_INDIRECTLY, true);
+ }
}
else if (id_type == ID_TXT) {
/* Ignore script nodes. */
@@ -1439,19 +1456,6 @@ void DepsgraphNodeBuilder::build_image(Image *image)
&image->id, NodeType::GENERIC_DATABLOCK, OperationCode::GENERIC_DATABLOCK_UPDATE);
}
-void DepsgraphNodeBuilder::build_compositor(Scene *scene)
-{
- /* For now, just a plain wrapper? */
- // TODO: create compositing component?
- // XXX: component type undefined!
- // graph->get_node(&scene->id, NULL, NodeType::COMPOSITING, NULL);
-
- /* for now, nodetrees are just parameters; compositing occurs in internals
- * of renderer... */
- add_component_node(&scene->id, NodeType::PARAMETERS);
- build_nodetree(scene->nodetree);
-}
-
void DepsgraphNodeBuilder::build_gpencil(bGPdata *gpd)
{
if (built_map_.checkIsBuiltAndTag(gpd)) {
@@ -1492,7 +1496,7 @@ void DepsgraphNodeBuilder::build_mask(Mask *mask)
return;
}
ID *mask_id = &mask->id;
- Mask *mask_cow = get_cow_datablock(mask);
+ Mask *mask_cow = (Mask *)ensure_cow_id(mask_id);
/* F-Curve based animation. */
build_animdata(mask_id);
build_parameters(mask_id);
diff --git a/source/blender/depsgraph/intern/builder/deg_builder_nodes.h b/source/blender/depsgraph/intern/builder/deg_builder_nodes.h
index 41314380b23..c3a04a9ad88 100644
--- a/source/blender/depsgraph/intern/builder/deg_builder_nodes.h
+++ b/source/blender/depsgraph/intern/builder/deg_builder_nodes.h
@@ -152,6 +152,11 @@ class DepsgraphNodeBuilder : public DepsgraphBuilder {
ID *id, NodeType comp_type, OperationCode opcode, const char *name = "", int name_tag = -1);
void build_id(ID *id);
+
+ void build_scene_render(Scene *scene);
+ void build_scene_parameters(Scene *scene);
+ void build_scene_compositor(Scene *scene);
+
void build_layer_collections(ListBase *lb);
void build_view_layer(Scene *scene,
ViewLayer *view_layer,
@@ -200,7 +205,6 @@ class DepsgraphNodeBuilder : public DepsgraphBuilder {
void build_texture(Tex *tex);
void build_image(Image *image);
void build_world(World *world);
- void build_compositor(Scene *scene);
void build_gpencil(bGPdata *gpd);
void build_cachefile(CacheFile *cache_file);
void build_mask(Mask *mask);
diff --git a/source/blender/depsgraph/intern/builder/deg_builder_nodes_scene.cc b/source/blender/depsgraph/intern/builder/deg_builder_nodes_scene.cc
new file mode 100644
index 00000000000..b092799e692
--- /dev/null
+++ b/source/blender/depsgraph/intern/builder/deg_builder_nodes_scene.cc
@@ -0,0 +1,63 @@
+/*
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * The Original Code is Copyright (C) 2013 Blender Foundation.
+ * All rights reserved.
+ */
+
+/** \file
+ * \ingroup depsgraph
+ */
+
+#include "intern/builder/deg_builder_nodes.h"
+
+#include "DNA_scene_types.h"
+
+namespace DEG {
+
+void DepsgraphNodeBuilder::build_scene_render(Scene *scene)
+{
+ scene_ = scene;
+ const bool build_compositor = (scene->r.scemode & R_DOCOMP);
+ IDNode *id_node = add_id_node(&scene->id);
+ id_node->linked_state = DEG_ID_LINKED_DIRECTLY;
+ add_time_source();
+ build_scene_parameters(scene);
+ if (build_compositor) {
+ build_scene_compositor(scene);
+ }
+}
+
+void DepsgraphNodeBuilder::build_scene_parameters(Scene *scene)
+{
+ if (built_map_.checkIsBuiltAndTag(scene, BuilderMap::TAG_PARAMETERS)) {
+ return;
+ }
+ add_operation_node(&scene->id, NodeType::PARAMETERS, OperationCode::SCENE_EVAL);
+ add_operation_node(&scene->id, NodeType::PARAMETERS, OperationCode::PARAMETERS_EVAL);
+}
+
+void DepsgraphNodeBuilder::build_scene_compositor(Scene *scene)
+{
+ if (built_map_.checkIsBuiltAndTag(scene, BuilderMap::TAG_SCENE_COMPOSITOR)) {
+ return;
+ }
+ if (scene->nodetree == NULL) {
+ return;
+ }
+ build_nodetree(scene->nodetree);
+}
+
+} // namespace DEG
diff --git a/source/blender/depsgraph/intern/builder/deg_builder_nodes_view_layer.cc b/source/blender/depsgraph/intern/builder/deg_builder_nodes_view_layer.cc
index b898b3d3519..baebd682f3f 100644
--- a/source/blender/depsgraph/intern/builder/deg_builder_nodes_view_layer.cc
+++ b/source/blender/depsgraph/intern/builder/deg_builder_nodes_view_layer.cc
@@ -125,9 +125,7 @@ void DepsgraphNodeBuilder::build_view_layer(Scene *scene,
build_world(scene->world);
}
/* Compositor nodes */
- if (scene->nodetree != NULL) {
- build_compositor(scene);
- }
+ build_scene_compositor(scene);
/* Cache file. */
LISTBASE_FOREACH (CacheFile *, cachefile, &bmain_->cachefiles) {
build_cachefile(cachefile);
@@ -157,7 +155,7 @@ void DepsgraphNodeBuilder::build_view_layer(Scene *scene,
OperationCode::VIEW_LAYER_EVAL,
function_bind(BKE_layer_eval_view_layer_indexed, _1, scene_cow, view_layer_index_));
/* Parameters evaluation for scene relations mainly. */
- add_operation_node(&scene->id, NodeType::PARAMETERS, OperationCode::SCENE_EVAL);
+ build_scene_parameters(scene);
/* Build all set scenes. */
if (scene->set != NULL) {
ViewLayer *set_view_layer = BKE_view_layer_default_render(scene->set);
diff --git a/source/blender/depsgraph/intern/builder/deg_builder_relations.cc b/source/blender/depsgraph/intern/builder/deg_builder_relations.cc
index 5686bcac5cb..54d5223497e 100644
--- a/source/blender/depsgraph/intern/builder/deg_builder_relations.cc
+++ b/source/blender/depsgraph/intern/builder/deg_builder_relations.cc
@@ -497,6 +497,9 @@ void DepsgraphRelationBuilder::build_id(ID *id)
case ID_CF:
build_cachefile((CacheFile *)id);
break;
+ case ID_SCE:
+ build_scene_parameters((Scene *)id);
+ break;
default:
fprintf(stderr, "Unhandled ID %s\n", id->name);
BLI_assert(!"Should never happen");
@@ -563,6 +566,7 @@ void DepsgraphRelationBuilder::build_object(Base *base, Object *object)
&object->id, NodeType::TRANSFORM, OperationCode::TRANSFORM_LOCAL);
OperationKey parent_transform_key(
&object->id, NodeType::TRANSFORM, OperationCode::TRANSFORM_PARENT);
+ OperationKey transform_eval_key(&object->id, NodeType::TRANSFORM, OperationCode::TRANSFORM_EVAL);
OperationKey final_transform_key(
&object->id, NodeType::TRANSFORM, OperationCode::TRANSFORM_FINAL);
OperationKey ob_eval_key(&object->id, NodeType::TRANSFORM, OperationCode::TRANSFORM_EVAL);
@@ -638,16 +642,18 @@ void DepsgraphRelationBuilder::build_object(Base *base, Object *object)
}
/* Proxy object to copy from. */
if (object->proxy_from != NULL) {
+ /* Object is linked here (comes from the library). */
build_object(NULL, object->proxy_from);
ComponentKey ob_transform_key(&object->proxy_from->id, NodeType::TRANSFORM);
ComponentKey proxy_transform_key(&object->id, NodeType::TRANSFORM);
add_relation(ob_transform_key, proxy_transform_key, "Proxy Transform");
}
- if (object->proxy_group != NULL) {
+ if (object->proxy_group != NULL && object->proxy_group != object->proxy) {
+ /* Object is local here (local in .blend file, users interacts with it). */
build_object(NULL, object->proxy_group);
OperationKey proxy_group_eval_key(
&object->proxy_group->id, NodeType::TRANSFORM, OperationCode::TRANSFORM_EVAL);
- add_relation(proxy_group_eval_key, final_transform_key, "Proxy Group Transform");
+ add_relation(proxy_group_eval_key, transform_eval_key, "Proxy Group Transform");
}
/* Object dupligroup. */
if (object->instance_collection != NULL) {
@@ -1852,7 +1858,7 @@ void DepsgraphRelationBuilder::build_object_data_geometry(Object *object)
/* Special case: modifiers evaluation queries scene for various things like
* data mask to be used. We add relation here to ensure object is never
* evaluated prior to Scene's CoW is ready. */
- OperationKey scene_key(&scene_->id, NodeType::LAYER_COLLECTIONS, OperationCode::VIEW_LAYER_EVAL);
+ OperationKey scene_key(&scene_->id, NodeType::PARAMETERS, OperationCode::SCENE_EVAL);
Relation *rel = add_relation(scene_key, obdata_ubereval_key, "CoW Relation");
rel->flag |= RELATION_FLAG_NO_FLUSH;
/* Modifiers */
@@ -2070,6 +2076,7 @@ void DepsgraphRelationBuilder::build_camera(Camera *camera)
build_animdata(&camera->id);
build_parameters(&camera->id);
if (camera->dof.focus_object != NULL) {
+ build_object(NULL, camera->dof.focus_object);
ComponentKey camera_parameters_key(&camera->id, NodeType::PARAMETERS);
ComponentKey dof_ob_key(&camera->dof.focus_object->id, NodeType::TRANSFORM);
add_relation(dof_ob_key, camera_parameters_key, "Camera DOF");
@@ -2125,8 +2132,15 @@ void DepsgraphRelationBuilder::build_nodetree(bNodeTree *ntree)
build_object(NULL, (Object *)id);
}
else if (id_type == ID_SCE) {
- /* Scenes are used by compositor trees, and handled by render
- * pipeline. No need to build dependencies for them here. */
+ Scene *node_scene = (Scene *)id;
+ build_scene_parameters(node_scene);
+ /* Camera is used by defocus node.
+ *
+ * On the one hand it's annoying to always pull it in, but on another hand it's also annoying
+ * to have hardcoded node-type exception here. */
+ if (node_scene->camera != NULL) {
+ build_object(NULL, node_scene->camera);
+ }
}
else if (id_type == ID_TXT) {
/* Ignore script nodes. */
@@ -2214,12 +2228,6 @@ void DepsgraphRelationBuilder::build_image(Image *image)
build_parameters(&image->id);
}
-void DepsgraphRelationBuilder::build_compositor(Scene *scene)
-{
- /* For now, just a plain wrapper? */
- build_nodetree(scene->nodetree);
-}
-
void DepsgraphRelationBuilder::build_gpencil(bGPdata *gpd)
{
if (built_map_.checkIsBuiltAndTag(gpd)) {
diff --git a/source/blender/depsgraph/intern/builder/deg_builder_relations.h b/source/blender/depsgraph/intern/builder/deg_builder_relations.h
index 1cf0b48128f..7d302092119 100644
--- a/source/blender/depsgraph/intern/builder/deg_builder_relations.h
+++ b/source/blender/depsgraph/intern/builder/deg_builder_relations.h
@@ -194,6 +194,11 @@ class DepsgraphRelationBuilder : public DepsgraphBuilder {
void add_special_eval_flag(ID *object, uint32_t flag);
void build_id(ID *id);
+
+ void build_scene_render(Scene *scene);
+ void build_scene_parameters(Scene *scene);
+ void build_scene_compositor(Scene *scene);
+
void build_layer_collections(ListBase *lb);
void build_view_layer(Scene *scene, ViewLayer *view_layer);
void build_collection(LayerCollection *from_layer_collection,
@@ -258,7 +263,6 @@ class DepsgraphRelationBuilder : public DepsgraphBuilder {
void build_material(Material *ma);
void build_texture(Tex *tex);
void build_image(Image *image);
- void build_compositor(Scene *scene);
void build_gpencil(bGPdata *gpd);
void build_cachefile(CacheFile *cache_file);
void build_mask(Mask *mask);
diff --git a/source/blender/depsgraph/intern/builder/deg_builder_relations_scene.cc b/source/blender/depsgraph/intern/builder/deg_builder_relations_scene.cc
new file mode 100644
index 00000000000..26bb1bd3d2a
--- /dev/null
+++ b/source/blender/depsgraph/intern/builder/deg_builder_relations_scene.cc
@@ -0,0 +1,62 @@
+/*
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * The Original Code is Copyright (C) 2013 Blender Foundation.
+ * All rights reserved.
+ */
+
+/** \file
+ * \ingroup depsgraph
+ */
+
+#include "intern/builder/deg_builder_relations.h"
+
+#include "DNA_scene_types.h"
+
+namespace DEG {
+
+void DepsgraphRelationBuilder::build_scene_render(Scene *scene)
+{
+ scene_ = scene;
+ const bool build_compositor = (scene->r.scemode & R_DOCOMP);
+ build_scene_parameters(scene);
+ if (build_compositor) {
+ build_scene_compositor(scene);
+ }
+}
+
+void DepsgraphRelationBuilder::build_scene_parameters(Scene *scene)
+{
+ if (built_map_.checkIsBuiltAndTag(scene, BuilderMap::TAG_PARAMETERS)) {
+ return;
+ }
+ OperationKey parameters_eval_key(
+ &scene->id, NodeType::PARAMETERS, OperationCode::PARAMETERS_EVAL);
+ OperationKey scene_eval_key(&scene->id, NodeType::PARAMETERS, OperationCode::SCENE_EVAL);
+ add_relation(parameters_eval_key, scene_eval_key, "Parameters -> Scene Eval");
+}
+
+void DepsgraphRelationBuilder::build_scene_compositor(Scene *scene)
+{
+ if (built_map_.checkIsBuiltAndTag(scene, BuilderMap::TAG_SCENE_COMPOSITOR)) {
+ return;
+ }
+ if (scene->nodetree == NULL) {
+ return;
+ }
+ build_nodetree(scene->nodetree);
+}
+
+} // namespace DEG
diff --git a/source/blender/depsgraph/intern/builder/deg_builder_relations_view_layer.cc b/source/blender/depsgraph/intern/builder/deg_builder_relations_view_layer.cc
index b5a926ad597..b832473bde9 100644
--- a/source/blender/depsgraph/intern/builder/deg_builder_relations_view_layer.cc
+++ b/source/blender/depsgraph/intern/builder/deg_builder_relations_view_layer.cc
@@ -106,10 +106,6 @@ void DepsgraphRelationBuilder::build_view_layer(Scene *scene, ViewLayer *view_la
if (scene->world != NULL) {
build_world(scene->world);
}
- /* Compositor nodes. */
- if (scene->nodetree != NULL) {
- build_compositor(scene);
- }
/* Masks. */
LISTBASE_FOREACH (Mask *, mask, &bmain_->masks) {
build_mask(mask);
@@ -128,6 +124,14 @@ void DepsgraphRelationBuilder::build_view_layer(Scene *scene, ViewLayer *view_la
build_collection(NULL, NULL, fls->group);
}
}
+ /* Scene parameters, compositor and such. */
+ build_scene_compositor(scene);
+ build_scene_parameters(scene);
+ /* Make final scene evaluation dependent on view layer evaluation. */
+ OperationKey scene_view_layer_key(
+ &scene->id, NodeType::LAYER_COLLECTIONS, OperationCode::VIEW_LAYER_EVAL);
+ OperationKey scene_eval_key(&scene->id, NodeType::PARAMETERS, OperationCode::SCENE_EVAL);
+ add_relation(scene_view_layer_key, scene_eval_key, "View Layer -> Scene Eval");
/* Build all set scenes. */
if (scene->set != NULL) {
ViewLayer *set_view_layer = BKE_view_layer_default_render(scene->set);
diff --git a/source/blender/depsgraph/intern/depsgraph.cc b/source/blender/depsgraph/intern/depsgraph.cc
index e2a9dde1eea..5d96bfad95e 100644
--- a/source/blender/depsgraph/intern/depsgraph.cc
+++ b/source/blender/depsgraph/intern/depsgraph.cc
@@ -73,7 +73,8 @@ Depsgraph::Depsgraph(Scene *scene, ViewLayer *view_layer, eEvaluationMode mode)
ctime(BKE_scene_frame_get(scene)),
scene_cow(NULL),
is_active(false),
- debug_is_evaluating(false)
+ debug_is_evaluating(false),
+ is_render_pipeline_depsgraph(false)
{
BLI_spin_init(&lock);
id_hash = BLI_ghash_ptr_new("Depsgraph id hash");
diff --git a/source/blender/depsgraph/intern/depsgraph.h b/source/blender/depsgraph/intern/depsgraph.h
index 2dcbb6b5574..073ec99b3aa 100644
--- a/source/blender/depsgraph/intern/depsgraph.h
+++ b/source/blender/depsgraph/intern/depsgraph.h
@@ -194,6 +194,12 @@ struct Depsgraph {
bool debug_is_evaluating;
+ /* Is set to truth for dependency graph which are used for post-processing (compositor and
+ * sequencer).
+ * Such dependency graph needs all view layers (so render pipeline can access names), but it
+ * does not need any bases. */
+ bool is_render_pipeline_depsgraph;
+
/* Cached list of colliders/effectors for collections and the scene
* created along with relations, for fast lookup during evaluation. */
GHash *physics_relations[DEG_PHYSICS_RELATIONS_NUM];
diff --git a/source/blender/depsgraph/intern/depsgraph_build.cc b/source/blender/depsgraph/intern/depsgraph_build.cc
index dd2979160cd..138b23888b4 100644
--- a/source/blender/depsgraph/intern/depsgraph_build.cc
+++ b/source/blender/depsgraph/intern/depsgraph_build.cc
@@ -222,9 +222,33 @@ struct Depsgraph *DEG_get_graph_from_handle(struct DepsNodeHandle *node_handle)
/* ******************** */
/* Graph Building API's */
-/* Build depsgraph for the given scene layer, and dump results in given
- * graph container.
- */
+static void graph_build_finalize_common(DEG::Depsgraph *deg_graph, Main *bmain)
+{
+ /* Detect and solve cycles. */
+ DEG::deg_graph_detect_cycles(deg_graph);
+ /* Simplify the graph by removing redundant relations (to optimize
+ * traversal later). */
+ /* TODO: it would be useful to have an option to disable this in cases where
+ * it is causing trouble. */
+ if (G.debug_value == 799) {
+ DEG::deg_graph_transitive_reduction(deg_graph);
+ }
+ /* Store pointers to commonly used valuated datablocks. */
+ deg_graph->scene_cow = (Scene *)deg_graph->get_cow_id(&deg_graph->scene->id);
+ /* Flush visibility layer and re-schedule nodes for update. */
+ DEG::deg_graph_build_finalize(bmain, deg_graph);
+ DEG_graph_on_visible_update(bmain, reinterpret_cast<::Depsgraph *>(deg_graph));
+#if 0
+ if (!DEG_debug_consistency_check(deg_graph)) {
+ printf("Consistency validation failed, ABORTING!\n");
+ abort();
+ }
+#endif
+ /* Relations are up to date. */
+ deg_graph->need_update = false;
+}
+
+/* Build depsgraph for the given scene layer, and dump results in given graph container. */
void DEG_graph_build_from_view_layer(Depsgraph *graph,
Main *bmain,
Scene *scene,
@@ -245,34 +269,46 @@ void DEG_graph_build_from_view_layer(Depsgraph *graph,
node_builder.begin_build();
node_builder.build_view_layer(scene, view_layer, DEG::DEG_ID_LINKED_DIRECTLY);
node_builder.end_build();
- /* Hook up relationships between operations - to determine evaluation
- * order. */
+ /* Hook up relationships between operations - to determine evaluation order. */
DEG::DepsgraphRelationBuilder relation_builder(bmain, deg_graph, &builder_cache);
relation_builder.begin_build();
relation_builder.build_view_layer(scene, view_layer);
relation_builder.build_copy_on_write_relations();
- /* Detect and solve cycles. */
- DEG::deg_graph_detect_cycles(deg_graph);
- /* Simplify the graph by removing redundant relations (to optimize
- * traversal later). */
- /* TODO: it would be useful to have an option to disable this in cases where
- * it is causing trouble. */
- if (G.debug_value == 799) {
- DEG::deg_graph_transitive_reduction(deg_graph);
+ /* Finalize building. */
+ graph_build_finalize_common(deg_graph, bmain);
+ /* Finish statistics. */
+ if (G.debug & (G_DEBUG_DEPSGRAPH_BUILD | G_DEBUG_DEPSGRAPH_TIME)) {
+ printf("Depsgraph built in %f seconds.\n", PIL_check_seconds_timer() - start_time);
}
- /* Store pointers to commonly used valuated datablocks. */
- deg_graph->scene_cow = (Scene *)deg_graph->get_cow_id(&deg_graph->scene->id);
- /* Flush visibility layer and re-schedule nodes for update. */
- DEG::deg_graph_build_finalize(bmain, deg_graph);
- DEG_graph_on_visible_update(bmain, graph);
-#if 0
- if (!DEG_debug_consistency_check(deg_graph)) {
- printf("Consistency validation failed, ABORTING!\n");
- abort();
+}
+
+void DEG_graph_build_for_render_pipeline(Depsgraph *graph,
+ Main *bmain,
+ Scene *scene,
+ ViewLayer * /*view_layer*/)
+{
+ double start_time = 0.0;
+ if (G.debug & (G_DEBUG_DEPSGRAPH_BUILD | G_DEBUG_DEPSGRAPH_TIME)) {
+ start_time = PIL_check_seconds_timer();
}
-#endif
- /* Relations are up to date. */
- deg_graph->need_update = false;
+ DEG::Depsgraph *deg_graph = reinterpret_cast<DEG::Depsgraph *>(graph);
+ /* Perform sanity checks. */
+ BLI_assert(deg_graph->scene == scene);
+ deg_graph->is_render_pipeline_depsgraph = true;
+ DEG::DepsgraphBuilderCache builder_cache;
+ /* Generate all the nodes in the graph first */
+ DEG::DepsgraphNodeBuilder node_builder(bmain, deg_graph, &builder_cache);
+ node_builder.begin_build();
+ node_builder.build_scene_render(scene);
+ node_builder.end_build();
+ /* Hook up relationships between operations - to determine evaluation
+ * order. */
+ DEG::DepsgraphRelationBuilder relation_builder(bmain, deg_graph, &builder_cache);
+ relation_builder.begin_build();
+ relation_builder.build_scene_render(scene);
+ relation_builder.build_copy_on_write_relations();
+ /* Finalize building. */
+ graph_build_finalize_common(deg_graph, bmain);
/* Finish statistics. */
if (G.debug & (G_DEBUG_DEPSGRAPH_BUILD | G_DEBUG_DEPSGRAPH_TIME)) {
printf("Depsgraph built in %f seconds.\n", PIL_check_seconds_timer() - start_time);
diff --git a/source/blender/depsgraph/intern/depsgraph_tag.cc b/source/blender/depsgraph/intern/depsgraph_tag.cc
index 7dcba8b7655..fc1c6be19af 100644
--- a/source/blender/depsgraph/intern/depsgraph_tag.cc
+++ b/source/blender/depsgraph/intern/depsgraph_tag.cc
@@ -249,7 +249,6 @@ void depsgraph_id_tag_copy_on_write(Depsgraph *graph, IDNode *id_node, eUpdateSo
{
ComponentNode *cow_comp = id_node->find_component(NodeType::COPY_ON_WRITE);
cow_comp->tag_update(graph, update_source);
- id_node->id_orig->recalc |= ID_RECALC_COPY_ON_WRITE;
}
void depsgraph_tag_component(Depsgraph *graph,
@@ -357,16 +356,16 @@ static void graph_id_tag_update_single_flag(Main *bmain,
/* TODO(sergey): Shall we raise some panic here? */
return;
}
- /* Tag ID recalc flag. */
- DepsNodeFactory *factory = type_get_factory(component_type);
- BLI_assert(factory != NULL);
- id->recalc |= factory->id_recalc_tag();
/* Some sanity checks before moving forward. */
if (id_node == NULL) {
/* Happens when object is tagged for update and not yet in the
* dependency graph (but will be after relations update). */
return;
}
+ /* Tag ID recalc flag. */
+ DepsNodeFactory *factory = type_get_factory(component_type);
+ BLI_assert(factory != NULL);
+ id_node->id_cow->recalc |= factory->id_recalc_tag();
/* Tag corresponding dependency graph operation for update. */
if (component_type == NodeType::ID_REF) {
id_node->tag_update(graph, update_source);
@@ -440,7 +439,7 @@ void deg_graph_node_tag_zero(Main *bmain,
}
ID *id = id_node->id_orig;
/* TODO(sergey): Which recalc flags to set here? */
- id->recalc |= ID_RECALC_ALL & ~(ID_RECALC_PSYS_ALL | ID_RECALC_ANIMATION);
+ id_node->id_cow->recalc |= ID_RECALC_ALL & ~(ID_RECALC_PSYS_ALL | ID_RECALC_ANIMATION);
GHASH_FOREACH_BEGIN (ComponentNode *, comp_node, id_node->components) {
if (comp_node->type == NodeType::ANIMATION) {
continue;
@@ -540,6 +539,8 @@ NodeType geometry_tag_to_component(const ID *id)
return NodeType::GEOMETRY;
case ID_PAL: /* Palettes */
return NodeType::PARAMETERS;
+ case ID_MSK:
+ return NodeType::PARAMETERS;
default:
break;
}
@@ -577,7 +578,6 @@ void graph_id_tag_update(
if (flag == 0) {
deg_graph_node_tag_zero(bmain, graph, id_node, update_source);
}
- id->recalc |= flag;
int current_flag = flag;
while (current_flag != 0) {
IDRecalcFlag tag = (IDRecalcFlag)(1 << bitscan_forward_clear_i(&current_flag));
@@ -742,17 +742,12 @@ static void deg_graph_clear_id_node_func(void *__restrict data_v,
DEG::Depsgraph *deg_graph = reinterpret_cast<DEG::Depsgraph *>(data_v);
DEG::IDNode *id_node = deg_graph->id_nodes[i];
id_node->id_cow->recalc &= ~ID_RECALC_ALL;
- id_node->id_orig->recalc &= ~ID_RECALC_ALL;
/* Clear embedded node trees too. */
bNodeTree *ntree_cow = ntreeFromID(id_node->id_cow);
if (ntree_cow) {
ntree_cow->id.recalc &= ~ID_RECALC_ALL;
}
- bNodeTree *ntree_orig = ntreeFromID(id_node->id_orig);
- if (ntree_orig) {
- ntree_orig->id.recalc &= ~ID_RECALC_ALL;
- }
}
void DEG_ids_clear_recalc(Main *UNUSED(bmain), Depsgraph *depsgraph)
diff --git a/source/blender/depsgraph/intern/eval/deg_eval_copy_on_write.cc b/source/blender/depsgraph/intern/eval/deg_eval_copy_on_write.cc
index 2a76d5cd362..4bc05bc9185 100644
--- a/source/blender/depsgraph/intern/eval/deg_eval_copy_on_write.cc
+++ b/source/blender/depsgraph/intern/eval/deg_eval_copy_on_write.cc
@@ -327,7 +327,7 @@ ViewLayer *get_original_view_layer(const Depsgraph *depsgraph, const IDNode *id_
return BKE_view_layer_default_render(scene_orig);
}
/* Is possible to have scene linked indirectly (i.e. via the driver) which
- * we need to support. Currently there aer issues somewhere else, which
+ * we need to support. Currently there are issues somewhere else, which
* makes testing hard. This is a reported problem, so will eventually be
* properly fixed.
*
@@ -340,7 +340,30 @@ void scene_remove_unused_view_layers(const Depsgraph *depsgraph,
const IDNode *id_node,
Scene *scene_cow)
{
- const ViewLayer *view_layer_input = get_original_view_layer(depsgraph, id_node);
+ const ViewLayer *view_layer_input;
+ if (depsgraph->is_render_pipeline_depsgraph) {
+ /* If the dependency graph is used for post-processing (such as compositor) we do need to
+ * have access to its view layer names so can not remove any view layers.
+ * On a more positive side we can remove all the bases from all the view layers.
+ *
+ * NOTE: Need to clear pointers which might be pointing to original on freed (due to being
+ * unused) data.
+ *
+ * NOTE: Need to keep view layers for all scenes, even indirect ones. This is because of
+ * render layer node possibly pointing to another scene. */
+ LISTBASE_FOREACH (ViewLayer *, view_layer, &scene_cow->view_layers) {
+ view_layer->basact = NULL;
+ }
+ return;
+ }
+ else if (id_node->linked_state == DEG_ID_LINKED_INDIRECTLY) {
+ /* Indirectly linked scenes means it's not an input scene and not a set scene, and is pulled
+ * via some driver. Such scenes should not have view layers after copy. */
+ view_layer_input = NULL;
+ }
+ else {
+ view_layer_input = get_original_view_layer(depsgraph, id_node);
+ }
ViewLayer *view_layer_eval = NULL;
/* Find evaluated view layer. At the same time we free memory used by
* all other of the view layers. */
@@ -349,24 +372,35 @@ void scene_remove_unused_view_layers(const Depsgraph *depsgraph,
view_layer_cow != NULL;
view_layer_cow = view_layer_next) {
view_layer_next = view_layer_cow->next;
- if (STREQ(view_layer_input->name, view_layer_cow->name)) {
+ if (view_layer_input != NULL && STREQ(view_layer_input->name, view_layer_cow->name)) {
view_layer_eval = view_layer_cow;
}
else {
BKE_view_layer_free_ex(view_layer_cow, false);
}
}
- BLI_assert(view_layer_eval != NULL);
- /* Make evaluated view layer the only one in the evaluated scene. */
- view_layer_eval->prev = view_layer_eval->next = NULL;
+ /* Make evaluated view layer the only one in the evaluated scene (if it exists). */
+ if (view_layer_eval != NULL) {
+ view_layer_eval->prev = view_layer_eval->next = NULL;
+ }
scene_cow->view_layers.first = view_layer_eval;
scene_cow->view_layers.last = view_layer_eval;
}
+void scene_remove_all_bases(Scene *scene_cow)
+{
+ LISTBASE_FOREACH (ViewLayer *, view_layer, &scene_cow->view_layers) {
+ BLI_freelistN(&view_layer->object_bases);
+ }
+}
+
/* Makes it so given view layer only has bases corresponding to enabled
* objects. */
void view_layer_remove_disabled_bases(const Depsgraph *depsgraph, ViewLayer *view_layer)
{
+ if (view_layer == NULL) {
+ return;
+ }
ListBase enabled_bases = {NULL, NULL};
LISTBASE_FOREACH_MUTABLE (Base *, base, &view_layer->object_bases) {
/* TODO(sergey): Would be cool to optimize this somehow, or make it so
@@ -397,6 +431,10 @@ void view_layer_remove_disabled_bases(const Depsgraph *depsgraph, ViewLayer *vie
void view_layer_update_orig_base_pointers(const ViewLayer *view_layer_orig,
ViewLayer *view_layer_eval)
{
+ if (view_layer_orig == NULL || view_layer_eval == NULL) {
+ /* Happens when scene is only used for parameters or compositor/sequencer. */
+ return;
+ }
Base *base_orig = reinterpret_cast<Base *>(view_layer_orig->object_bases.first);
LISTBASE_FOREACH (Base *, base_eval, &view_layer_eval->object_bases) {
base_eval->base_orig = base_orig;
@@ -409,6 +447,11 @@ void scene_setup_view_layers_before_remap(const Depsgraph *depsgraph,
Scene *scene_cow)
{
scene_remove_unused_view_layers(depsgraph, id_node, scene_cow);
+ /* If dependency graph is used for post-processing we don't need any bases and can free of them.
+ * Do it before re-mapping to make that process faster. */
+ if (depsgraph->is_render_pipeline_depsgraph) {
+ scene_remove_all_bases(scene_cow);
+ }
}
void scene_setup_view_layers_after_remap(const Depsgraph *depsgraph,
@@ -821,7 +864,7 @@ ID *deg_expand_copy_on_write_datablock(const Depsgraph *depsgraph,
/* Correct or tweak some pointers which are not taken care by foreach
* from above. */
update_id_after_copy(depsgraph, id_node, id_orig, id_cow);
- id_cow->recalc = id_orig->recalc | id_cow_recalc;
+ id_cow->recalc = id_cow_recalc;
return id_cow;
}
diff --git a/source/blender/depsgraph/intern/eval/deg_eval_flush.cc b/source/blender/depsgraph/intern/eval/deg_eval_flush.cc
index 0bd5b3b4f82..6d8dcf2778f 100644
--- a/source/blender/depsgraph/intern/eval/deg_eval_flush.cc
+++ b/source/blender/depsgraph/intern/eval/deg_eval_flush.cc
@@ -234,10 +234,6 @@ void flush_editors_id_update(Depsgraph *graph, const DEGEditorUpdateContext *upd
/* TODO(sergey): Do we need to pass original or evaluated ID here? */
ID *id_orig = id_node->id_orig;
ID *id_cow = id_node->id_cow;
- /* Copy tag from original data to CoW storage.
- * This is because DEG_id_tag_update() sets tags on original
- * data. */
- id_cow->recalc |= (id_orig->recalc & ID_RECALC_ALL);
/* Gather recalc flags from all changed components. */
GHASH_FOREACH_BEGIN (ComponentNode *, comp_node, id_node->components) {
if (comp_node->custom_flags != COMPONENT_STATE_DONE) {
diff --git a/source/blender/draw/engines/basic/basic_engine.c b/source/blender/draw/engines/basic/basic_engine.c
index aad92c9658a..a274eda84fe 100644
--- a/source/blender/draw/engines/basic/basic_engine.c
+++ b/source/blender/draw/engines/basic/basic_engine.c
@@ -94,11 +94,6 @@ static void basic_cache_init(void *vedata)
const DRWContextState *draw_ctx = DRW_context_state_get();
BASIC_Shaders *sh_data = &e_data.sh_data[draw_ctx->sh_cfg];
- const RegionView3D *rv3d = draw_ctx->rv3d;
-
- if (draw_ctx->sh_cfg == GPU_SHADER_CFG_CLIPPED) {
- DRW_state_clip_planes_set_from_rv3d(draw_ctx->rv3d);
- }
if (!stl->g_data) {
/* Alloc transient pointers */
@@ -110,7 +105,7 @@ static void basic_cache_init(void *vedata)
DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_LESS_EQUAL);
stl->g_data->depth_shgrp = DRW_shgroup_create(sh_data->depth, psl->depth_pass);
if (draw_ctx->sh_cfg == GPU_SHADER_CFG_CLIPPED) {
- DRW_shgroup_world_clip_planes_from_rv3d(stl->g_data->depth_shgrp, rv3d);
+ DRW_shgroup_state_enable(stl->g_data->depth_shgrp, DRW_STATE_CLIP_PLANES);
}
psl->depth_pass_cull = DRW_pass_create("Depth Pass Cull",
@@ -118,7 +113,7 @@ static void basic_cache_init(void *vedata)
DRW_STATE_CULL_BACK);
stl->g_data->depth_shgrp_cull = DRW_shgroup_create(sh_data->depth, psl->depth_pass_cull);
if (draw_ctx->sh_cfg == GPU_SHADER_CFG_CLIPPED) {
- DRW_shgroup_world_clip_planes_from_rv3d(stl->g_data->depth_shgrp_cull, rv3d);
+ DRW_shgroup_state_enable(stl->g_data->depth_shgrp_cull, DRW_STATE_CLIP_PLANES);
}
}
}
diff --git a/source/blender/draw/engines/eevee/eevee_data.c b/source/blender/draw/engines/eevee/eevee_data.c
index b7b8702b41a..0ce271275d0 100644
--- a/source/blender/draw/engines/eevee/eevee_data.c
+++ b/source/blender/draw/engines/eevee/eevee_data.c
@@ -62,7 +62,6 @@ 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);
- DRW_UBO_FREE_SAFE(sldata->clip_ubo);
}
EEVEE_ViewLayerData *EEVEE_view_layer_data_get(void)
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 ae8e7614302..c14f08857c3 100644
--- a/source/blender/draw/engines/eevee/eevee_depth_of_field.c
+++ b/source/blender/draw/engines/eevee/eevee_depth_of_field.c
@@ -140,14 +140,7 @@ int EEVEE_depth_of_field_init(EEVEE_ViewLayerData *UNUSED(sldata),
float focus_dist = BKE_camera_object_dof_distance(camera);
float focal_len = cam->lens;
- /* this is factor that converts to the scene scale. focal length and sensor are expressed in
- * mm unit.scale_length is how many meters per blender unit we have. We want to convert to
- * blender units though because the shader reads coordinates in world space, which is in
- * blender units.
- * Note however that focus_distance is already in blender units and shall not be scaled here
- * (see T48157). */
- float scale = (scene_eval->unit.system) ? scene_eval->unit.scale_length : 1.0f;
- float scale_camera = 0.001f / scale;
+ const float scale_camera = 0.001f;
/* we want radius here for the aperture number */
float aperture = 0.5f * scale_camera * focal_len / fstop;
float focal_len_scaled = scale_camera * focal_len;
diff --git a/source/blender/draw/engines/eevee/eevee_effects.c b/source/blender/draw/engines/eevee/eevee_effects.c
index 8a85c6671fd..8b176f8e5b2 100644
--- a/source/blender/draw/engines/eevee/eevee_effects.c
+++ b/source/blender/draw/engines/eevee/eevee_effects.c
@@ -175,16 +175,6 @@ void EEVEE_effects_init(EEVEE_ViewLayerData *sldata,
}
/**
- * Ping Pong buffer
- */
- if ((effects->enabled_effects & EFFECT_POST_BUFFER) != 0) {
- SETUP_BUFFER(txl->color_post, fbl->effect_fb, fbl->effect_color_fb);
- }
- else {
- CLEANUP_BUFFER(txl->color_post, fbl->effect_fb, fbl->effect_color_fb);
- }
-
- /**
* MinMax Pyramid
*/
const bool half_res_hiz = true;
@@ -360,6 +350,13 @@ void EEVEE_effects_cache_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata)
DRW_shgroup_uniform_vec4(grp, "color2", effects->color_checker_light, 1);
DRW_shgroup_uniform_int_copy(grp, "size", 8);
DRW_shgroup_call(grp, quad, NULL);
+
+ float mat[4][4];
+ unit_m4(mat);
+
+ /* Using default view bypasses the culling. */
+ const DRWView *default_view = DRW_view_default_get();
+ effects->checker_view = DRW_view_create_sub(default_view, mat, mat);
}
}
@@ -378,6 +375,16 @@ void EEVEE_effects_draw_init(EEVEE_ViewLayerData *UNUSED(sldata), EEVEE_Data *ve
else {
CLEANUP_BUFFER(txl->color_double_buffer, fbl->double_buffer_fb, fbl->double_buffer_color_fb);
}
+
+ /**
+ * Ping Pong buffer
+ */
+ if ((effects->enabled_effects & EFFECT_POST_BUFFER) != 0) {
+ SETUP_BUFFER(txl->color_post, fbl->effect_fb, fbl->effect_color_fb);
+ }
+ else {
+ CLEANUP_BUFFER(txl->color_post, fbl->effect_fb, fbl->effect_color_fb);
+ }
}
#if 0 /* Not required for now */
@@ -515,16 +522,11 @@ void EEVEE_draw_alpha_checker(EEVEE_Data *vedata)
EEVEE_EffectsInfo *effects = stl->effects;
if ((effects->enabled_effects & EFFECT_ALPHA_CHECKER) != 0) {
- float mat[4][4];
- unit_m4(mat);
-
- /* Fragile, rely on the fact that GPU_SHADER_2D_CHECKER
- * only use the persmat. */
- DRW_viewport_matrix_override_set(mat, DRW_MAT_PERS);
+ DRW_view_set_active(effects->checker_view);
DRW_draw_pass(psl->alpha_checker);
- DRW_viewport_matrix_override_unset(DRW_MAT_PERS);
+ DRW_view_set_active(NULL);
}
}
@@ -534,16 +536,17 @@ static void EEVEE_velocity_resolve(EEVEE_Data *vedata)
EEVEE_FramebufferList *fbl = vedata->fbl;
EEVEE_StorageList *stl = vedata->stl;
EEVEE_EffectsInfo *effects = stl->effects;
+ struct DRWView *view = effects->taa_view;
if ((effects->enabled_effects & EFFECT_VELOCITY_BUFFER) != 0) {
DefaultTextureList *dtxl = DRW_viewport_texture_list_get();
e_data.depth_src = dtxl->depth;
- DRW_viewport_matrix_get(effects->velocity_curr_persinv, DRW_MAT_PERSINV);
+ DRW_view_persmat_get(view, effects->velocity_curr_persinv, true);
GPU_framebuffer_bind(fbl->velocity_resolve_fb);
DRW_draw_pass(psl->velocity_resolve);
}
- DRW_viewport_matrix_get(effects->velocity_past_persmat, DRW_MAT_PERS);
+ DRW_view_persmat_get(view, effects->velocity_past_persmat, false);
}
void EEVEE_draw_effects(EEVEE_ViewLayerData *UNUSED(sldata), EEVEE_Data *vedata)
@@ -594,7 +597,7 @@ void EEVEE_draw_effects(EEVEE_ViewLayerData *UNUSED(sldata), EEVEE_Data *vedata)
}
/* Record pers matrix for the next frame. */
- DRW_viewport_matrix_get(stl->effects->prev_persmat, DRW_MAT_PERS);
+ DRW_view_persmat_get(effects->taa_view, effects->prev_persmat, false);
/* Update double buffer status if render mode. */
if (DRW_state_is_image_render()) {
diff --git a/source/blender/draw/engines/eevee/eevee_engine.c b/source/blender/draw/engines/eevee/eevee_engine.c
index 481b566eff0..22f7b786330 100644
--- a/source/blender/draw/engines/eevee/eevee_engine.c
+++ b/source/blender/draw/engines/eevee/eevee_engine.c
@@ -79,20 +79,12 @@ static void eevee_engine_init(void *ved)
sldata->common_ubo = DRW_uniformbuffer_create(sizeof(sldata->common_data),
&sldata->common_data);
}
- if (sldata->clip_ubo == NULL) {
- sldata->clip_ubo = DRW_uniformbuffer_create(sizeof(sldata->clip_data), &sldata->clip_data);
- }
/* EEVEE_effects_init needs to go first for TAA */
EEVEE_effects_init(sldata, vedata, camera, false);
EEVEE_materials_init(sldata, stl, fbl);
EEVEE_lights_init(sldata);
EEVEE_lightprobes_init(sldata, vedata);
-
- if ((stl->effects->taa_current_sample > 1) && !DRW_state_is_image_render()) {
- /* XXX otherwise it would break the other engines. */
- DRW_viewport_matrix_override_unset_all();
- }
}
static void eevee_cache_init(void *vedata)
@@ -214,15 +206,22 @@ static void eevee_draw_background(void *vedata)
/* Copy previous persmat to UBO data */
copy_m4_m4(sldata->common_data.prev_persmat, stl->effects->prev_persmat);
+ /* Refresh Probes */
+ DRW_stats_group_start("Probes Refresh");
+ EEVEE_lightprobes_refresh(sldata, vedata);
+ EEVEE_lightprobes_refresh_planar(sldata, vedata);
+ DRW_stats_group_end();
+
+ /* Refresh shadows */
+ DRW_stats_group_start("Shadows");
+ EEVEE_draw_shadows(sldata, vedata, stl->effects->taa_view);
+ DRW_stats_group_end();
+
if (((stl->effects->enabled_effects & EFFECT_TAA) != 0) &&
(stl->effects->taa_current_sample > 1) && !DRW_state_is_image_render() &&
!taa_use_reprojection) {
- DRW_viewport_matrix_override_set(stl->effects->overide_persmat, DRW_MAT_PERS);
- DRW_viewport_matrix_override_set(stl->effects->overide_persinv, DRW_MAT_PERSINV);
- DRW_viewport_matrix_override_set(stl->effects->overide_winmat, DRW_MAT_WIN);
- DRW_viewport_matrix_override_set(stl->effects->overide_wininv, DRW_MAT_WININV);
+ DRW_view_set_active(stl->effects->taa_view);
}
-
/* when doing viewport rendering the overrides needs to be recalculated for
* every loop as this normally happens once inside
* `EEVEE_temporal_sampling_init` */
@@ -231,21 +230,6 @@ static void eevee_draw_background(void *vedata)
EEVEE_temporal_sampling_update_matrices(vedata);
}
- /* Refresh Probes */
- DRW_stats_group_start("Probes Refresh");
- EEVEE_lightprobes_refresh(sldata, vedata);
- /* Probes refresh can have reset the current sample. */
- if (stl->effects->taa_current_sample == 1) {
- DRW_viewport_matrix_override_unset_all();
- }
- EEVEE_lightprobes_refresh_planar(sldata, vedata);
- DRW_stats_group_end();
-
- /* Refresh shadows */
- DRW_stats_group_start("Shadows");
- EEVEE_draw_shadows(sldata, vedata);
- DRW_stats_group_end();
-
/* Set ray type. */
sldata->common_data.ray_type = EEVEE_RAY_CAMERA;
sldata->common_data.ray_depth = 0.0f;
@@ -309,9 +293,7 @@ static void eevee_draw_background(void *vedata)
EEVEE_draw_effects(sldata, vedata);
DRW_stats_group_end();
- if ((stl->effects->taa_current_sample > 1)) {
- DRW_viewport_matrix_override_unset_all();
- }
+ DRW_view_set_active(NULL);
}
/* Tonemapping and transfer result to default framebuffer. */
@@ -391,7 +373,7 @@ static void eevee_id_object_update(void *UNUSED(vedata), Object *object)
{
EEVEE_LightProbeEngineData *ped = EEVEE_lightprobe_data_get(object);
if (ped != NULL && ped->dd.recalc != 0) {
- ped->need_update = (ped->dd.recalc & (ID_RECALC_TRANSFORM | ID_RECALC_COPY_ON_WRITE)) != 0;
+ ped->need_update = (ped->dd.recalc & (ID_RECALC_TRANSFORM)) != 0;
ped->dd.recalc = 0;
}
EEVEE_LightEngineData *led = EEVEE_light_data_get(object);
diff --git a/source/blender/draw/engines/eevee/eevee_lightcache.c b/source/blender/draw/engines/eevee/eevee_lightcache.c
index 3e0e5f6d00f..536ecb1bc42 100644
--- a/source/blender/draw/engines/eevee/eevee_lightcache.c
+++ b/source/blender/draw/engines/eevee/eevee_lightcache.c
@@ -717,16 +717,20 @@ static void eevee_lightbake_cache_create(EEVEE_Data *vedata, EEVEE_LightBake *lb
stl->g_data->background_alpha = 1.0f;
/* XXX TODO remove this. This is in order to make the init functions work. */
- DRWMatrixState dummy_mats = {{{{{0}}}}};
- DRW_viewport_matrix_override_set_all(&dummy_mats);
+ if (DRW_view_default_get() == NULL) {
+ float winmat[4][4], viewmat[4][4];
+ unit_m4(viewmat);
+ unit_m4(winmat);
+ negate_v3(winmat[2]);
+ DRWView *view = DRW_view_create(viewmat, winmat, NULL, NULL, NULL);
+ DRW_view_default_set(view);
+ DRW_view_set_active(view);
+ }
if (sldata->common_ubo == NULL) {
sldata->common_ubo = DRW_uniformbuffer_create(sizeof(sldata->common_data),
&sldata->common_data);
}
- if (sldata->clip_ubo == NULL) {
- sldata->clip_ubo = DRW_uniformbuffer_create(sizeof(sldata->clip_data), &sldata->clip_data);
- }
/* HACK: set txl->color but unset it before Draw Manager frees it. */
txl->color = lbake->rt_color;
@@ -743,6 +747,7 @@ static void eevee_lightbake_cache_create(EEVEE_Data *vedata, EEVEE_LightBake *lb
EEVEE_effects_cache_init(sldata, vedata);
EEVEE_materials_cache_init(sldata, vedata);
+ EEVEE_subsurface_cache_init(sldata, vedata);
EEVEE_lights_cache_init(sldata, vedata);
EEVEE_lightprobes_cache_init(sldata, vedata);
diff --git a/source/blender/draw/engines/eevee/eevee_lightprobes.c b/source/blender/draw/engines/eevee/eevee_lightprobes.c
index 92cd465f771..78565f9c465 100644
--- a/source/blender/draw/engines/eevee/eevee_lightprobes.c
+++ b/source/blender/draw/engines/eevee/eevee_lightprobes.c
@@ -167,6 +167,11 @@ void EEVEE_lightprobes_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata)
e_data.hammersley = create_hammersley_sample_texture(HAMMERSLEY_SIZE);
}
+ memset(stl->g_data->bake_views, 0, sizeof(stl->g_data->bake_views));
+ memset(stl->g_data->cube_views, 0, sizeof(stl->g_data->cube_views));
+ memset(stl->g_data->world_views, 0, sizeof(stl->g_data->world_views));
+ memset(stl->g_data->planar_views, 0, sizeof(stl->g_data->planar_views));
+
/* Use fallback if we don't have gpu texture allocated an we cannot restore them. */
bool use_fallback_lightcache = (scene_eval->eevee.light_cache == NULL) ||
((scene_eval->eevee.light_cache->grid_tx.tex == NULL) &&
@@ -463,7 +468,8 @@ static bool eevee_lightprobes_culling_test(Object *ob)
for (int v = 0; v < 8; ++v) {
mul_m4_v3(tmp, bbox.vec[v]);
}
- return DRW_culling_box_test(&bbox);
+ const DRWView *default_view = DRW_view_default_get();
+ return DRW_culling_box_test(default_view, &bbox);
}
case LIGHTPROBE_TYPE_CUBE:
return true; /* TODO */
@@ -487,6 +493,8 @@ void EEVEE_lightprobes_cache_add(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata
}
if (probe->type == LIGHTPROBE_TYPE_PLANAR) {
+ /* TODO(fclem): Culling should be done after cache generation.
+ * This is needed for future draw cache persistence. */
if (!eevee_lightprobes_culling_test(ob)) {
return; /* Culled */
}
@@ -673,22 +681,35 @@ void EEVEE_lightprobes_planar_data_from_object(Object *ob,
eplanar->attenuation_bias = max_dist * -eplanar->attenuation_scale;
}
-static void lightbake_planar_compute_render_matrices(EEVEE_PlanarReflection *eplanar,
- DRWMatrixState *r_matstate,
- const float viewmat[4][4],
- const float winmat[4][4])
+static void lightbake_planar_ensure_view(EEVEE_PlanarReflection *eplanar,
+ const DRWView *main_view,
+ DRWView **r_planar_view)
{
+ float winmat[4][4], viewmat[4][4];
+ DRW_view_viewmat_get(main_view, viewmat, false);
/* Temporal sampling jitter should be already applied to the DRW_MAT_WIN. */
- copy_m4_m4(r_matstate->winmat, winmat);
+ DRW_view_winmat_get(main_view, winmat, false);
/* Invert X to avoid flipping the triangle facing direction. */
- r_matstate->winmat[0][0] = -r_matstate->winmat[0][0];
- r_matstate->winmat[1][0] = -r_matstate->winmat[1][0];
- r_matstate->winmat[2][0] = -r_matstate->winmat[2][0];
- r_matstate->winmat[3][0] = -r_matstate->winmat[3][0];
+ winmat[0][0] = -winmat[0][0];
+ winmat[1][0] = -winmat[1][0];
+ winmat[2][0] = -winmat[2][0];
+ winmat[3][0] = -winmat[3][0];
/* Reflect Camera Matrix. */
- mul_m4_m4m4(r_matstate->viewmat, viewmat, eplanar->mtx);
- /* Apply Projection Matrix. */
- mul_m4_m4m4(r_matstate->persmat, r_matstate->winmat, r_matstate->viewmat);
+ mul_m4_m4m4(viewmat, viewmat, eplanar->mtx);
+
+ if (*r_planar_view == NULL) {
+ *r_planar_view = DRW_view_create(
+ viewmat, winmat, NULL, NULL, EEVEE_lightprobes_obj_visibility_cb);
+ /* Compute offset plane equation (fix missing texels near reflection plane). */
+ float clip_plane[4];
+ copy_v4_v4(clip_plane, eplanar->plane_equation);
+ clip_plane[3] += eplanar->clipsta;
+ /* Set clipping plane */
+ DRW_view_clip_planes_set(*r_planar_view, &clip_plane, 1);
+ }
+ else {
+ DRW_view_update(*r_planar_view, viewmat, winmat, NULL, NULL);
+ }
}
static void eevee_lightprobes_extract_from_cache(EEVEE_LightProbesInfo *pinfo, LightCache *lcache)
@@ -756,7 +777,7 @@ void EEVEE_lightprobes_cache_finish(EEVEE_ViewLayerData *sldata, EEVEE_Data *ved
}
}
- if (pinfo->num_planar) {
+ if (pinfo->num_planar > 0) {
EEVEE_PassList *psl = vedata->psl;
EEVEE_TextureList *txl = vedata->txl;
DRW_PASS_CREATE(psl->probe_planar_downsample_ps, DRW_STATE_WRITE_COLOR);
@@ -783,32 +804,43 @@ typedef struct EEVEE_BakeRenderData {
static void render_cubemap(void (*callback)(int face, EEVEE_BakeRenderData *user_data),
EEVEE_BakeRenderData *user_data,
const float pos[3],
- float clipsta,
- float clipend)
+ float near,
+ float far,
+ bool do_culling)
{
- DRWMatrixState matstate;
+ EEVEE_StorageList *stl = user_data->vedata->stl;
+ DRWView **views = do_culling ? stl->g_data->bake_views : stl->g_data->world_views;
- /* Move to capture position */
- float posmat[4][4];
- unit_m4(posmat);
- negate_v3_v3(posmat[3], pos);
+ float winmat[4][4], viewmat[4][4];
+ perspective_m4(winmat, -near, near, -near, near, near, far);
- perspective_m4(matstate.winmat, -clipsta, clipsta, -clipsta, clipsta, clipsta, clipend);
- invert_m4_m4(matstate.wininv, matstate.winmat);
+ /* Prepare views at the same time for faster culling. */
+ for (int i = 0; i < 6; i++) {
+ unit_m4(viewmat);
+ negate_v3_v3(viewmat[3], pos);
+ mul_m4_m4m4(viewmat, cubefacemat[i], viewmat);
- /* 1 - Render to each cubeface individually.
- * We do this instead of using geometry shader because a) it's faster,
- * b) it's easier than fixing the nodetree shaders (for view dependent effects). */
- for (int i = 0; i < 6; ++i) {
- /* Setup custom matrices */
- mul_m4_m4m4(matstate.viewmat, cubefacemat[i], posmat);
- mul_m4_m4m4(matstate.persmat, matstate.winmat, matstate.viewmat);
- invert_m4_m4(matstate.persinv, matstate.persmat);
- invert_m4_m4(matstate.viewinv, matstate.viewmat);
- invert_m4_m4(matstate.wininv, matstate.winmat);
-
- DRW_viewport_matrix_override_set_all(&matstate);
+ if (do_culling) {
+ if (views[i] == NULL) {
+ views[i] = DRW_view_create(viewmat, winmat, NULL, NULL, NULL);
+ }
+ else {
+ DRW_view_update(views[i], viewmat, winmat, NULL, NULL);
+ }
+ }
+ else {
+ if (views[i] == NULL) {
+ const DRWView *default_view = DRW_view_default_get();
+ views[i] = DRW_view_create_sub(default_view, viewmat, winmat);
+ }
+ else {
+ DRW_view_update_sub(views[i], viewmat, winmat);
+ }
+ }
+ }
+ for (int i = 0; i < 6; ++i) {
+ DRW_view_set_active(views[i]);
callback(i, user_data);
}
}
@@ -818,21 +850,16 @@ static void render_reflections(void (*callback)(int face, EEVEE_BakeRenderData *
EEVEE_PlanarReflection *planar_data,
int ref_count)
{
- DRWMatrixState matstate;
-
- float original_viewmat[4][4], original_winmat[4][4];
- DRW_viewport_matrix_get(original_viewmat, DRW_MAT_VIEW);
- DRW_viewport_matrix_get(original_winmat, DRW_MAT_WIN);
-
+ EEVEE_StorageList *stl = user_data->vedata->stl;
+ DRWView *main_view = stl->effects->taa_view;
+ DRWView **views = stl->g_data->planar_views;
+ /* Prepare views at the same time for faster culling. */
for (int i = 0; i < ref_count; ++i) {
- /* Setup custom matrices */
- lightbake_planar_compute_render_matrices(
- planar_data + i, &matstate, original_viewmat, original_winmat);
- invert_m4_m4(matstate.persinv, matstate.persmat);
- invert_m4_m4(matstate.viewinv, matstate.viewmat);
- invert_m4_m4(matstate.wininv, matstate.winmat);
- DRW_viewport_matrix_override_set_all(&matstate);
+ lightbake_planar_ensure_view(&planar_data[i], main_view, &views[i]);
+ }
+ for (int i = 0; i < ref_count; ++i) {
+ DRW_view_set_active(views[i]);
callback(i, user_data);
}
}
@@ -858,17 +885,20 @@ void EEVEE_lightbake_render_world(EEVEE_ViewLayerData *UNUSED(sldata),
.face_fb = face_fb,
};
- render_cubemap(lightbake_render_world_face, &brdata, (float[3]){0.0f}, 1.0f, 10.0f);
+ render_cubemap(lightbake_render_world_face, &brdata, (float[3]){0.0f}, 1.0f, 10.0f, false);
}
static void lightbake_render_scene_face(int face, EEVEE_BakeRenderData *user_data)
{
EEVEE_ViewLayerData *sldata = user_data->sldata;
EEVEE_PassList *psl = user_data->vedata->psl;
+ EEVEE_PrivateData *g_data = user_data->vedata->stl->g_data;
+ DRWView **views = g_data->bake_views;
+
struct GPUFrameBuffer **face_fb = user_data->face_fb;
/* Be sure that cascaded shadow maps are updated. */
- EEVEE_draw_shadows(sldata, user_data->vedata);
+ EEVEE_draw_shadows(sldata, user_data->vedata, views[face]);
GPU_framebuffer_bind(face_fb[face]);
GPU_framebuffer_clear_depth(face_fb[face], 1.0f);
@@ -897,7 +927,7 @@ void EEVEE_lightbake_render_scene(EEVEE_ViewLayerData *sldata,
.face_fb = face_fb,
};
- render_cubemap(lightbake_render_scene_face, &brdata, pos, near_clip, far_clip);
+ render_cubemap(lightbake_render_scene_face, &brdata, pos, near_clip, far_clip, true);
}
static void lightbake_render_scene_reflected(int layer, EEVEE_BakeRenderData *user_data)
@@ -906,9 +936,9 @@ static void lightbake_render_scene_reflected(int layer, EEVEE_BakeRenderData *us
EEVEE_ViewLayerData *sldata = user_data->sldata;
EEVEE_PassList *psl = vedata->psl;
EEVEE_TextureList *txl = vedata->txl;
+ EEVEE_StorageList *stl = vedata->stl;
EEVEE_FramebufferList *fbl = vedata->fbl;
EEVEE_LightProbesInfo *pinfo = sldata->probes;
- EEVEE_PlanarReflection *eplanar = pinfo->planar_data + layer;
GPU_framebuffer_ensure_config(&fbl->planarref_fb,
{GPU_ATTACHMENT_TEXTURE_LAYER(txl->planar_depth, layer),
@@ -924,18 +954,10 @@ static void lightbake_render_scene_reflected(int layer, EEVEE_BakeRenderData *us
txl->planar_pool = e_data.planar_pool_placeholder;
txl->planar_depth = e_data.depth_array_placeholder;
- /* Be sure that cascaded shadow maps are updated. */
DRW_stats_group_start("Planar Reflection");
/* Be sure that cascaded shadow maps are updated. */
- EEVEE_draw_shadows(sldata, vedata);
-
- /* Compute offset plane equation (fix missing texels near reflection plane). */
- copy_v4_v4(sldata->clip_data.clip_planes[0], eplanar->plane_equation);
- sldata->clip_data.clip_planes[0][3] += eplanar->clipsta;
- /* Set clipping plane */
- DRW_uniformbuffer_update(sldata->clip_ubo, &sldata->clip_data);
- DRW_state_clip_planes_len_set(1);
+ EEVEE_draw_shadows(sldata, vedata, stl->g_data->planar_views[layer]);
GPU_framebuffer_bind(fbl->planarref_fb);
GPU_framebuffer_clear_depth(fbl->planarref_fb, 1.0);
@@ -972,8 +994,6 @@ static void lightbake_render_scene_reflected(int layer, EEVEE_BakeRenderData *us
}
DRW_draw_pass(psl->transparent_pass);
- DRW_state_clip_planes_reset();
-
DRW_stats_group_end();
/* Restore */
@@ -1033,7 +1053,7 @@ void EEVEE_lightbake_filter_glossy(EEVEE_ViewLayerData *sldata,
/* 3 - Render to probe array to the specified layer, do prefiltering. */
int mipsize = GPU_texture_width(light_cache->cube_tx.tex);
for (int i = 0; i < maxlevel + 1; i++) {
- float bias = (i == 0) ? -1.0f : 1.0f;
+ float bias = 0.0f;
pinfo->texel_size = 1.0f / (float)mipsize;
pinfo->padding_size = (i == maxlevel) ? 0 : (float)(1 << (maxlevel - i - 1));
pinfo->padding_size *= pinfo->texel_size;
@@ -1043,22 +1063,27 @@ void EEVEE_lightbake_filter_glossy(EEVEE_ViewLayerData *sldata,
pinfo->roughness *= pinfo->roughness; /* Distribute Roughness accros lod more evenly */
CLAMP(pinfo->roughness, 1e-8f, 0.99999f); /* Avoid artifacts */
-#if 1 /* Variable Sample count (fast) */
+#if 1 /* Variable Sample count and bias (fast) */
switch (i) {
case 0:
pinfo->samples_len = 1.0f;
+ bias = -1.0f;
break;
case 1:
- pinfo->samples_len = 16.0f;
+ pinfo->samples_len = 32.0f;
+ bias = 1.0f;
break;
case 2:
- pinfo->samples_len = 32.0f;
+ pinfo->samples_len = 40.0f;
+ bias = 2.0f;
break;
case 3:
pinfo->samples_len = 64.0f;
+ bias = 2.0f;
break;
default:
pinfo->samples_len = 128.0f;
+ bias = 2.0f;
break;
}
#else /* Constant Sample count (slow) */
@@ -1221,7 +1246,6 @@ void EEVEE_lightprobes_refresh_planar(EEVEE_ViewLayerData *sldata, EEVEE_Data *v
{
EEVEE_CommonUniformBuffer *common_data = &sldata->common_data;
EEVEE_LightProbesInfo *pinfo = sldata->probes;
- DRWMatrixState saved_mats;
if (pinfo->num_planar == 0) {
/* Disable SSR if we cannot read previous frame */
@@ -1230,9 +1254,6 @@ void EEVEE_lightprobes_refresh_planar(EEVEE_ViewLayerData *sldata, EEVEE_Data *v
return;
}
- /* We need to save the Matrices before overidding them */
- DRW_viewport_matrix_get_all(&saved_mats);
-
/* Temporary Remove all planar reflections (avoid lag effect). */
common_data->prb_num_planar = 0;
/* Turn off ssr to avoid black specular */
@@ -1261,8 +1282,6 @@ void EEVEE_lightprobes_refresh_planar(EEVEE_ViewLayerData *sldata, EEVEE_Data *v
EEVEE_lightbake_filter_planar(vedata);
}
- DRW_viewport_matrix_override_set_all(&saved_mats);
-
if (DRW_state_is_image_render()) {
/* Sort transparents because planar reflections could have re-sorted them. */
DRW_pass_sort_shgroup_z(vedata->psl->transparent_pass);
@@ -1280,10 +1299,7 @@ void EEVEE_lightprobes_refresh(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata)
if ((light_cache->flag & LIGHTCACHE_UPDATE_WORLD) &&
(light_cache->flag & LIGHTCACHE_BAKED) == 0) {
- DRWMatrixState saved_mats;
- DRW_viewport_matrix_get_all(&saved_mats);
EEVEE_lightbake_update_world_quick(sldata, vedata, scene_eval);
- DRW_viewport_matrix_override_set_all(&saved_mats);
}
}
diff --git a/source/blender/draw/engines/eevee/eevee_lights.c b/source/blender/draw/engines/eevee/eevee_lights.c
index 7106cf0249e..e966fadbcdb 100644
--- a/source/blender/draw/engines/eevee/eevee_lights.c
+++ b/source/blender/draw/engines/eevee/eevee_lights.c
@@ -970,7 +970,7 @@ static void frustum_min_bounding_sphere(const float corners[8][3],
static void eevee_shadow_cascade_setup(Object *ob,
EEVEE_LightsInfo *linfo,
EEVEE_LightEngineData *led,
- DRWMatrixState *saved_mats,
+ DRWView *view,
float view_near,
float view_far,
int sample_ofs)
@@ -978,9 +978,10 @@ static void eevee_shadow_cascade_setup(Object *ob,
Light *la = (Light *)ob->data;
/* Camera Matrices */
- float(*persinv)[4] = saved_mats->mat[DRW_MAT_PERSINV];
- float(*vp_projmat)[4] = saved_mats->mat[DRW_MAT_WIN];
- bool is_persp = DRW_viewport_is_persp_get();
+ float persinv[4][4], vp_projmat[4][4];
+ DRW_view_persmat_get(view, persinv, true);
+ DRW_view_winmat_get(view, vp_projmat, false);
+ bool is_persp = DRW_view_is_persp_get(view);
/* Lights Matrices */
int cascade_nbr = la->cascade_count;
@@ -1286,19 +1287,52 @@ void EEVEE_lights_update(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata)
}
}
+static void eevee_ensure_cube_views(float near, float far, const float pos[3], DRWView *view[6])
+{
+ float winmat[4][4], viewmat[4][4];
+ perspective_m4(winmat, -near, near, -near, near, near, far);
+
+ for (int i = 0; i < 6; i++) {
+ unit_m4(viewmat);
+ negate_v3_v3(viewmat[3], pos);
+ mul_m4_m4m4(viewmat, cubefacemat[i], viewmat);
+
+ if (view[i] == NULL) {
+ view[i] = DRW_view_create(viewmat, winmat, NULL, NULL, NULL);
+ }
+ else {
+ DRW_view_update(view[i], viewmat, winmat, NULL, NULL);
+ }
+ }
+}
+
+static void eevee_ensure_cascade_views(EEVEE_ShadowCascadeData *cascade_data,
+ int cascade_count,
+ DRWView *view[4])
+{
+ for (int i = 0; i < cascade_count; i++) {
+ if (view[i] == NULL) {
+ view[i] = DRW_view_create(cascade_data->viewmat, cascade_data->projmat[i], NULL, NULL, NULL);
+ }
+ else {
+ DRW_view_update(view[i], cascade_data->viewmat, cascade_data->projmat[i], NULL, NULL);
+ }
+ }
+}
+
/* this refresh lights shadow buffers */
-void EEVEE_draw_shadows(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata)
+void EEVEE_draw_shadows(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata, DRWView *view)
{
EEVEE_PassList *psl = vedata->psl;
EEVEE_StorageList *stl = vedata->stl;
EEVEE_EffectsInfo *effects = stl->effects;
+ EEVEE_PrivateData *g_data = stl->g_data;
EEVEE_LightsInfo *linfo = sldata->lights;
const DRWContextState *draw_ctx = DRW_context_state_get();
const float light_threshold = draw_ctx->scene->eevee.light_threshold;
Object *ob;
int i;
- DRWMatrixState saved_mats;
int saved_ray_type = sldata->common_data.ray_type;
/* TODO: make it optionnal if we don't draw shadows. */
@@ -1313,8 +1347,9 @@ void EEVEE_draw_shadows(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata)
.center = {ob->obmat[3][0], ob->obmat[3][1], ob->obmat[3][2]},
.radius = light_attenuation_radius_get(la, light_threshold),
};
- cube_visible[i] = DRW_culling_sphere_test(&bsphere);
+ cube_visible[i] = DRW_culling_sphere_test(view, &bsphere);
}
+
bool cascade_visible[MAX_SHADOW_CASCADE];
for (i = 0; (ob = linfo->shadow_cascade_ref[i]) && (i < MAX_SHADOW_CASCADE); i++) {
EEVEE_LightEngineData *led = EEVEE_light_data_get(ob);
@@ -1325,12 +1360,9 @@ void EEVEE_draw_shadows(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata)
plane_from_point_normal_v3(plane, sh_data->viewmat[3], sh_data->viewmat[2]);
/* TODO: check against near/far instead of "local Z = 0" plane.
* Or even the cascades AABB. */
- cascade_visible[i] = DRW_culling_plane_test(plane);
+ cascade_visible[i] = DRW_culling_plane_test(view, plane);
}
- /* We need to save the Matrices before overidding them */
- DRW_viewport_matrix_get_all(&saved_mats);
-
/* Cube Shadow Maps */
DRW_stats_group_start("Cube Shadow Maps");
/* Render each shadow to one layer of the array */
@@ -1342,11 +1374,6 @@ void EEVEE_draw_shadows(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata)
continue;
}
- DRWMatrixState render_mats;
- float(*winmat)[4] = render_mats.mat[DRW_MAT_WIN];
- float(*viewmat)[4] = render_mats.mat[DRW_MAT_VIEW];
- float(*persmat)[4] = render_mats.mat[DRW_MAT_PERS];
-
EEVEE_ShadowRender *srd = &linfo->shadow_render_data;
EEVEE_ShadowCubeData *evscd = &led->data.scd;
EEVEE_ShadowCube *cube_data = linfo->shadow_cube_data + evscd->cube_id;
@@ -1357,32 +1384,16 @@ void EEVEE_draw_shadows(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata)
srd->exponent = la->bleedexp;
copy_v3_v3(srd->position, cube_data->position);
- perspective_m4(winmat,
- -srd->clip_near,
- srd->clip_near,
- -srd->clip_near,
- srd->clip_near,
- srd->clip_near,
- srd->clip_far);
-
DRW_uniformbuffer_update(sldata->shadow_render_ubo, srd);
+ eevee_ensure_cube_views(srd->clip_near, srd->clip_far, srd->position, g_data->cube_views);
+
/* Render shadow cube */
/* Render 6 faces separately: seems to be faster for the general case.
* The only time it's more beneficial is when the CPU culling overhead
* outweigh the instancing overhead. which is rarely the case. */
for (int j = 0; j < 6; j++) {
- /* TODO optimize */
- float tmp[4][4];
- unit_m4(tmp);
- negate_v3_v3(tmp[3], srd->position);
- mul_m4_m4m4(viewmat, cubefacemat[j], tmp);
- mul_m4_m4m4(persmat, winmat, viewmat);
- invert_m4_m4(render_mats.mat[DRW_MAT_WININV], winmat);
- invert_m4_m4(render_mats.mat[DRW_MAT_VIEWINV], viewmat);
- invert_m4_m4(render_mats.mat[DRW_MAT_PERSINV], persmat);
-
- DRW_viewport_matrix_override_set_all(&render_mats);
+ DRW_view_set_active(g_data->cube_views[j]);
GPU_framebuffer_texture_cubeface_attach(
sldata->shadow_cube_target_fb, sldata->shadow_cube_target, 0, j, 0);
@@ -1448,9 +1459,8 @@ void EEVEE_draw_shadows(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata)
linfo->update_flag &= ~LIGHT_UPDATE_SHADOW_CUBE;
DRW_stats_group_end();
- DRW_viewport_matrix_override_set_all(&saved_mats);
- float near = DRW_viewport_near_distance_get();
- float far = DRW_viewport_far_distance_get();
+ float near = DRW_view_near_distance_get(view);
+ float far = DRW_view_far_distance_get(view);
/* Cascaded Shadow Maps */
DRW_stats_group_start("Cascaded Shadow Maps");
@@ -1465,34 +1475,24 @@ void EEVEE_draw_shadows(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata)
EEVEE_ShadowCascadeData *evscd = &led->data.scad;
EEVEE_ShadowRender *srd = &linfo->shadow_render_data;
- DRWMatrixState render_mats;
- float(*winmat)[4] = render_mats.mat[DRW_MAT_WIN];
- float(*viewmat)[4] = render_mats.mat[DRW_MAT_VIEW];
- float(*persmat)[4] = render_mats.mat[DRW_MAT_PERS];
-
- eevee_shadow_cascade_setup(
- ob, linfo, led, &saved_mats, near, far, effects->taa_current_sample - 1);
-
srd->clip_near = la->clipsta;
srd->clip_far = la->clipend;
srd->stored_texel_size = 1.0 / (float)linfo->shadow_cascade_size;
DRW_uniformbuffer_update(sldata->shadow_render_ubo, &linfo->shadow_render_data);
- copy_m4_m4(viewmat, evscd->viewmat);
- invert_m4_m4(render_mats.mat[DRW_MAT_VIEWINV], viewmat);
+ eevee_shadow_cascade_setup(ob, linfo, led, view, near, far, effects->taa_current_sample - 1);
+
+ /* Meh, Reusing the cube views. */
+ BLI_assert(MAX_CASCADE_NUM <= 6);
+ eevee_ensure_cascade_views(evscd, la->cascade_count, g_data->cube_views);
/* Render shadow cascades */
/* Render cascade separately: seems to be faster for the general case.
* The only time it's more beneficial is when the CPU culling overhead
* outweigh the instancing overhead. which is rarely the case. */
for (int j = 0; j < la->cascade_count; j++) {
- copy_m4_m4(winmat, evscd->projmat[j]);
- copy_m4_m4(persmat, evscd->viewprojmat[j]);
- invert_m4_m4(render_mats.mat[DRW_MAT_WININV], winmat);
- invert_m4_m4(render_mats.mat[DRW_MAT_PERSINV], persmat);
-
- DRW_viewport_matrix_override_set_all(&render_mats);
+ DRW_view_set_active(g_data->cube_views[j]);
GPU_framebuffer_texture_layer_attach(
sldata->shadow_cascade_target_fb, sldata->shadow_cascade_target, 0, j, 0);
@@ -1554,7 +1554,7 @@ void EEVEE_draw_shadows(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata)
DRW_stats_group_end();
- DRW_viewport_matrix_override_set_all(&saved_mats);
+ DRW_view_set_active(view);
DRW_uniformbuffer_update(sldata->light_ubo, &linfo->light_data);
DRW_uniformbuffer_update(sldata->shadow_ubo, &linfo->shadow_data); /* Update all data at once */
diff --git a/source/blender/draw/engines/eevee/eevee_lookdev.c b/source/blender/draw/engines/eevee/eevee_lookdev.c
index bd786c06e69..a998bd3a71b 100644
--- a/source/blender/draw/engines/eevee/eevee_lookdev.c
+++ b/source/blender/draw/engines/eevee/eevee_lookdev.c
@@ -223,20 +223,28 @@ void EEVEE_lookdev_draw(EEVEE_Data *vedata)
DRW_uniformbuffer_update(sldata->common_ubo, common);
/* override matrices */
- DRWMatrixState matstate;
- unit_m4(matstate.winmat);
+ float winmat[4][4], viewmat[4][4];
+ unit_m4(winmat);
+ /* Look through the negative Z. */
+ negate_v3(winmat[2]);
- eevee_lookdev_apply_taa(effects, effects->sphere_size, matstate.winmat);
+ eevee_lookdev_apply_taa(effects, effects->sphere_size, winmat);
/* "Remove" view matrix location. Leaving only rotation. */
- DRW_viewport_matrix_get(matstate.viewmat, DRW_MAT_VIEW);
- zero_v3(matstate.viewmat[3]);
- mul_m4_m4m4(matstate.persmat, matstate.winmat, matstate.viewmat);
- invert_m4_m4(matstate.wininv, matstate.winmat);
- invert_m4_m4(matstate.viewinv, matstate.viewmat);
- invert_m4_m4(matstate.persinv, matstate.persmat);
+ DRW_view_viewmat_get(NULL, viewmat, false);
+ zero_v3(viewmat[3]);
- DRW_viewport_matrix_override_set_all(&matstate);
+ if (effects->lookdev_view) {
+ /* When rendering just update the view. This avoids recomputing the culling. */
+ DRW_view_update_sub(effects->lookdev_view, viewmat, winmat);
+ }
+ else {
+ /* Using default view bypasses the culling. */
+ const DRWView *default_view = DRW_view_default_get();
+ effects->lookdev_view = DRW_view_create_sub(default_view, viewmat, winmat);
+ }
+
+ DRW_view_set_active(effects->lookdev_view);
/* Find the right framebuffers to render to. */
GPUFrameBuffer *fb = (effects->target_buffer == fbl->effect_color_fb) ? fbl->main_fb :
@@ -270,6 +278,6 @@ void EEVEE_lookdev_draw(EEVEE_Data *vedata)
DRW_stats_group_end();
- DRW_viewport_matrix_override_unset_all();
+ DRW_view_set_active(NULL);
}
}
diff --git a/source/blender/draw/engines/eevee/eevee_materials.c b/source/blender/draw/engines/eevee/eevee_materials.c
index 44e9b98e8e2..456f312f1df 100644
--- a/source/blender/draw/engines/eevee/eevee_materials.c
+++ b/source/blender/draw/engines/eevee/eevee_materials.c
@@ -386,7 +386,6 @@ 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, "clip_block", sldata->clip_ubo);
if (use_diffuse || use_glossy || use_refract) {
DRW_shgroup_uniform_texture(shgrp, "utilTex", e_data.util_tex);
@@ -599,8 +598,11 @@ void EEVEE_materials_init(EEVEE_ViewLayerData *sldata,
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.default_background = DRW_shader_create(
- datatoc_background_vert_glsl, NULL, datatoc_default_world_frag_glsl, 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);
char *vert_str = BLI_string_joinN(
datatoc_common_view_lib_glsl, datatoc_common_hair_lib_glsl, datatoc_prepass_vert_glsl);
@@ -642,8 +644,8 @@ void EEVEE_materials_init(EEVEE_ViewLayerData *sldata,
{
/* Update view_vecs */
float invproj[4][4], winmat[4][4];
- DRW_viewport_matrix_get(winmat, DRW_MAT_WIN);
- DRW_viewport_matrix_get(invproj, DRW_MAT_WININV);
+ DRW_view_winmat_get(NULL, winmat, false);
+ DRW_view_winmat_get(NULL, invproj, true);
EEVEE_update_viewvecs(invproj, winmat, sldata->common_data.view_vecs);
}
@@ -1024,14 +1026,12 @@ void EEVEE_materials_cache_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata)
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);
- DRW_shgroup_uniform_block(stl->g_data->depth_shgrp_clip, "clip_block", sldata->clip_ubo);
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);
- DRW_shgroup_uniform_block(stl->g_data->depth_shgrp_clip_cull, "clip_block", sldata->clip_ubo);
}
{
@@ -1055,16 +1055,12 @@ void EEVEE_materials_cache_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata)
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);
- DRW_shgroup_uniform_block(
- stl->g_data->refract_depth_shgrp_clip, "clip_block", sldata->clip_ubo);
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);
- DRW_shgroup_uniform_block(
- stl->g_data->refract_depth_shgrp_clip_cull, "clip_block", sldata->clip_ubo);
}
{
@@ -1130,11 +1126,10 @@ void EEVEE_materials_cache_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata)
#define ADD_SHGROUP_CALL(shgrp, ob, geom, oedata) \
do { \
if (oedata) { \
- DRW_shgroup_call_object_with_callback( \
- shgrp, geom, ob, EEVEE_lightprobes_obj_visibility_cb, oedata); \
+ DRW_shgroup_call_object_with_callback(shgrp, geom, ob, oedata); \
} \
else { \
- DRW_shgroup_call_object_ex(shgrp, geom, ob, false); \
+ DRW_shgroup_call_object(shgrp, geom, ob); \
} \
} while (0)
@@ -1510,7 +1505,6 @@ static void material_transparent(Material *ma,
/* Depth prepass */
if (use_prepass) {
*shgrp_depth = DRW_shgroup_create(e_data.default_prepass_clip_sh, psl->transparent_pass);
- DRW_shgroup_uniform_block(*shgrp_depth, "clip_block", sldata->clip_ubo);
cur_state = DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_LESS_EQUAL;
cur_state |= (do_cull) ? DRW_STATE_CULL_BACK : 0;
@@ -1748,7 +1742,6 @@ void EEVEE_hair_cache_populate(EEVEE_Data *vedata,
shgrp = DRW_shgroup_hair_create(
ob, psys, md, psl->depth_pass_clip, e_data.default_hair_prepass_clip_sh);
- DRW_shgroup_uniform_block(shgrp, "clip_block", sldata->clip_ubo);
shgrp = NULL;
if (ma->use_nodes && ma->nodetree) {
diff --git a/source/blender/draw/engines/eevee/eevee_motion_blur.c b/source/blender/draw/engines/eevee/eevee_motion_blur.c
index ad4f72d78dc..abd5bb82815 100644
--- a/source/blender/draw/engines/eevee/eevee_motion_blur.c
+++ b/source/blender/draw/engines/eevee/eevee_motion_blur.c
@@ -127,7 +127,7 @@ int EEVEE_motion_blur_init(EEVEE_ViewLayerData *UNUSED(sldata), EEVEE_Data *veda
/* Viewport Matrix */
/* Note: This does not have TAA jitter applied. */
- DRW_viewport_matrix_get(persmat, DRW_MAT_PERS);
+ DRW_view_persmat_get(NULL, persmat, false);
bool view_is_valid = (stl->g_data->view_updated == false);
diff --git a/source/blender/draw/engines/eevee/eevee_private.h b/source/blender/draw/engines/eevee/eevee_private.h
index e2130615b1d..2e652dff232 100644
--- a/source/blender/draw/engines/eevee/eevee_private.h
+++ b/source/blender/draw/engines/eevee/eevee_private.h
@@ -571,10 +571,7 @@ typedef struct EEVEE_EffectsInfo {
float taa_alpha;
bool prev_drw_support;
float prev_drw_persmat[4][4];
- float overide_persmat[4][4];
- float overide_persinv[4][4];
- float overide_winmat[4][4];
- float overide_wininv[4][4];
+ struct DRWView *taa_view;
/* Ambient Occlusion */
int ao_depth_layer;
struct GPUTexture *ao_src_depth; /* pointer copy */
@@ -604,11 +601,13 @@ typedef struct EEVEE_EffectsInfo {
/* Alpha Checker */
float color_checker_dark[4];
float color_checker_light[4];
+ struct DRWView *checker_view;
/* Other */
float prev_persmat[4][4];
/* Lookdev */
int sphere_size;
int anchor[2];
+ struct DRWView *lookdev_view;
/* Bloom */
int bloom_iteration_len;
float source_texel_size[2];
@@ -694,12 +693,6 @@ typedef struct EEVEE_CommonUniformBuffer {
#define EEVEE_RAY_DIFFUSE 2
#define EEVEE_RAY_GLOSSY 3
-/* ***************** CLIP PLANES DATA **************** */
-
-typedef struct EEVEE_ClipPlanesUniformBuffer {
- float clip_planes[1][4]; /* must be less than MAX_CLIP_PLANES */
-} EEVEE_ClipPlanesUniformBuffer;
-
/* ************** SCENE LAYER DATA ************** */
typedef struct EEVEE_ViewLayerData {
/* Lights */
@@ -735,9 +728,6 @@ typedef struct EEVEE_ViewLayerData {
struct EEVEE_CommonUniformBuffer common_data;
struct GPUUniformBuffer *common_ubo;
- struct EEVEE_ClipPlanesUniformBuffer clip_data;
- struct GPUUniformBuffer *clip_ubo;
-
struct LightCache *fallback_lightcache;
} EEVEE_ViewLayerData;
@@ -754,7 +744,7 @@ typedef struct EEVEE_ShadowCubeData {
typedef struct EEVEE_ShadowCascadeData {
short light_id, shadow_id, cascade_id, layer_id;
/* World->Light->NDC : used for rendering the shadow map. */
- float viewprojmat[MAX_CASCADE_NUM][4][4];
+ float viewprojmat[MAX_CASCADE_NUM][4][4]; /* Could be removed. */
float projmat[MAX_CASCADE_NUM][4][4];
float viewmat[4][4], viewinv[4][4];
float radius[MAX_CASCADE_NUM];
@@ -829,9 +819,6 @@ typedef struct EEVEE_PrivateData {
bool valid_double_buffer;
bool valid_taa_history;
/* Render Matrices */
- float persmat[4][4], persinv[4][4];
- float viewmat[4][4], viewinv[4][4];
- float winmat[4][4], wininv[4][4];
float studiolight_matrix[3][3];
float overscan, overscan_pixels;
float size_orig[2];
@@ -849,6 +836,14 @@ typedef struct EEVEE_PrivateData {
float studiolight_glossy_clamp;
float studiolight_filter_quality;
+ /** For rendering shadows. */
+ struct DRWView *cube_views[6];
+ /** For rendering probes. */
+ struct DRWView *bake_views[6];
+ /** Same as bake_views but does not generate culling infos. */
+ struct DRWView *world_views[6];
+ /** For rendering planar reflections. */
+ struct DRWView *planar_views[MAX_PLANAR];
} EEVEE_PrivateData; /* Transient data */
/* eevee_data.c */
@@ -919,7 +914,7 @@ void EEVEE_lights_cache_shcaster_material_add(EEVEE_ViewLayerData *sldata,
void EEVEE_lights_cache_shcaster_object_add(EEVEE_ViewLayerData *sldata, struct Object *ob);
void EEVEE_lights_cache_finish(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata);
void EEVEE_lights_update(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata);
-void EEVEE_draw_shadows(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata);
+void EEVEE_draw_shadows(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata, struct DRWView *view);
void EEVEE_lights_free(void);
/* eevee_shaders.c */
@@ -1055,10 +1050,7 @@ int EEVEE_temporal_sampling_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata
void EEVEE_temporal_sampling_offset_calc(const double ht_point[2],
const float filter_size,
float r_offset[2]);
-void EEVEE_temporal_sampling_matrices_calc(EEVEE_EffectsInfo *effects,
- float viewmat[4][4],
- float persmat[4][4],
- const double ht_point[2]);
+void EEVEE_temporal_sampling_matrices_calc(EEVEE_EffectsInfo *effects, const double ht_point[2]);
void EEVEE_temporal_sampling_update_matrices(EEVEE_Data *vedata);
void EEVEE_temporal_sampling_cache_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata);
void EEVEE_temporal_sampling_draw(EEVEE_Data *vedata);
diff --git a/source/blender/draw/engines/eevee/eevee_render.c b/source/blender/draw/engines/eevee/eevee_render.c
index 8e3857ae8a8..2afd0b1d313 100644
--- a/source/blender/draw/engines/eevee/eevee_render.c
+++ b/source/blender/draw/engines/eevee/eevee_render.c
@@ -53,6 +53,8 @@ void EEVEE_render_init(EEVEE_Data *ved, RenderEngine *engine, struct Depsgraph *
EEVEE_ViewLayerData *sldata = EEVEE_view_layer_data_ensure();
Scene *scene = DEG_get_evaluated_scene(depsgraph);
const float *size_orig = DRW_viewport_size_get();
+ float size_final[2];
+ float camtexcofac[4];
/* Init default FB and render targets:
* In render mode the default framebuffer is not generated
@@ -73,10 +75,20 @@ void EEVEE_render_init(EEVEE_Data *ved, RenderEngine *engine, struct Depsgraph *
if (scene->eevee.flag & SCE_EEVEE_OVERSCAN) {
g_data->overscan = scene->eevee.overscan / 100.0f;
g_data->overscan_pixels = roundf(max_ff(size_orig[0], size_orig[1]) * g_data->overscan);
+
+ madd_v2_v2v2fl(size_final, size_orig, (float[2]){2.0f, 2.0f}, g_data->overscan_pixels);
+
+ camtexcofac[0] = size_final[0] / size_orig[0];
+ camtexcofac[1] = size_final[1] / size_orig[1];
+
+ camtexcofac[2] = -camtexcofac[0] * g_data->overscan_pixels / size_final[0];
+ camtexcofac[3] = -camtexcofac[1] * g_data->overscan_pixels / size_final[1];
}
else {
+ copy_v2_v2(size_final, size_orig);
g_data->overscan = 0.0f;
g_data->overscan_pixels = 0.0f;
+ copy_v4_fl4(camtexcofac, 1.0f, 1.0f, 0.0f, 0.0f);
}
/* XXX overiding viewport size. Simplify things but is not really 100% safe. */
@@ -100,30 +112,23 @@ void EEVEE_render_init(EEVEE_Data *ved, RenderEngine *engine, struct Depsgraph *
sldata->common_ubo = DRW_uniformbuffer_create(sizeof(sldata->common_data),
&sldata->common_data);
}
- if (sldata->clip_ubo == NULL) {
- sldata->clip_ubo = DRW_uniformbuffer_create(sizeof(sldata->clip_data), &sldata->clip_data);
- }
/* Set the pers & view matrix. */
+ float winmat[4][4], viewmat[4][4], viewinv[4][4];
/* TODO(sergey): Shall render hold pointer to an evaluated camera instead? */
struct Object *ob_camera_eval = DEG_get_evaluated_object(depsgraph, RE_GetCamera(engine->re));
float frame = BKE_scene_frame_get(scene);
- RE_GetCameraWindow(engine->re, ob_camera_eval, frame, g_data->winmat);
- RE_GetCameraModelMatrix(engine->re, ob_camera_eval, g_data->viewinv);
- RE_GetCameraWindowWithOverscan(engine->re, g_data->winmat, g_data->overscan);
+ RE_GetCameraWindow(engine->re, ob_camera_eval, frame, winmat);
+ RE_GetCameraWindowWithOverscan(engine->re, winmat, g_data->overscan);
+ RE_GetCameraModelMatrix(engine->re, ob_camera_eval, viewinv);
- invert_m4_m4(g_data->viewmat, g_data->viewinv);
- mul_m4_m4m4(g_data->persmat, g_data->winmat, g_data->viewmat);
- invert_m4_m4(g_data->persinv, g_data->persmat);
- invert_m4_m4(g_data->wininv, g_data->winmat);
+ invert_m4_m4(viewmat, viewinv);
- DRW_viewport_matrix_override_set(g_data->persmat, DRW_MAT_PERS);
- DRW_viewport_matrix_override_set(g_data->persinv, DRW_MAT_PERSINV);
- DRW_viewport_matrix_override_set(g_data->winmat, DRW_MAT_WIN);
- DRW_viewport_matrix_override_set(g_data->wininv, DRW_MAT_WININV);
- DRW_viewport_matrix_override_set(g_data->viewmat, DRW_MAT_VIEW);
- DRW_viewport_matrix_override_set(g_data->viewinv, DRW_MAT_VIEWINV);
+ DRWView *view = DRW_view_create(viewmat, winmat, NULL, NULL, NULL);
+ DRW_view_camtexco_set(view, camtexcofac);
+ DRW_view_default_set(view);
+ DRW_view_set_active(view);
/* EEVEE_effects_init needs to go first for TAA */
EEVEE_effects_init(sldata, vedata, ob_camera_eval, false);
@@ -304,6 +309,9 @@ static void eevee_render_result_normal(RenderLayer *rl,
1,
rp->rect);
+ float viewinv[4][4];
+ DRW_view_viewmat_get(NULL, viewinv, true);
+
/* Convert Eevee encoded normals to Blender normals. */
for (int i = 0; i < rp->rectx * rp->recty * 3; i += 3) {
if (rp->rect[i] == 0.0f && rp->rect[i + 1] == 0.0f) {
@@ -322,7 +330,7 @@ static void eevee_render_result_normal(RenderLayer *rl,
rp->rect[i + 1] = fenc[1] * g;
rp->rect[i + 2] = 1.0f - f / 2.0f;
- mul_mat3_m4_v3(g_data->viewinv, &rp->rect[i]);
+ mul_mat3_m4_v3(viewinv, &rp->rect[i]);
}
}
}
@@ -355,7 +363,10 @@ static void eevee_render_result_z(RenderLayer *rl,
BLI_rcti_size_y(rect),
rp->rect);
- bool is_persp = DRW_viewport_is_persp_get();
+ bool is_persp = DRW_view_is_persp_get(NULL);
+
+ float winmat[4][4];
+ DRW_view_winmat_get(NULL, winmat, false);
/* Convert ogl depth [0..1] to view Z [near..far] */
for (int i = 0; i < rp->rectx * rp->recty; ++i) {
@@ -365,7 +376,7 @@ static void eevee_render_result_z(RenderLayer *rl,
else {
if (is_persp) {
rp->rect[i] = rp->rect[i] * 2.0f - 1.0f;
- rp->rect[i] = g_data->winmat[3][2] / (rp->rect[i] + g_data->winmat[2][2]);
+ rp->rect[i] = winmat[3][2] / (rp->rect[i] + winmat[2][2]);
}
else {
rp->rect[i] = -common_data->view_vecs[0][2] +
@@ -533,25 +544,15 @@ void EEVEE_render_draw(EEVEE_Data *vedata, RenderEngine *engine, RenderLayer *rl
double offset[3] = {0.0, 0.0, 0.0};
double r[3];
- /* Restore winmat before jittering again. */
- copy_m4_m4(stl->effects->overide_winmat, g_data->winmat);
/* Copy previous persmat to UBO data */
copy_m4_m4(sldata->common_data.prev_persmat, stl->effects->prev_persmat);
BLI_halton_3d(primes, offset, stl->effects->taa_current_sample, r);
EEVEE_update_noise(psl, fbl, r);
- EEVEE_temporal_sampling_matrices_calc(stl->effects, g_data->viewmat, g_data->persmat, 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);
- /* Set matrices. */
- DRW_viewport_matrix_override_set(stl->effects->overide_persmat, DRW_MAT_PERS);
- DRW_viewport_matrix_override_set(stl->effects->overide_persinv, DRW_MAT_PERSINV);
- DRW_viewport_matrix_override_set(stl->effects->overide_winmat, DRW_MAT_WIN);
- DRW_viewport_matrix_override_set(stl->effects->overide_wininv, DRW_MAT_WININV);
- DRW_viewport_matrix_override_set(g_data->viewmat, DRW_MAT_VIEW);
- DRW_viewport_matrix_override_set(g_data->viewinv, DRW_MAT_VIEWINV);
-
/* Refresh Probes */
EEVEE_lightprobes_refresh(sldata, vedata);
EEVEE_lightprobes_refresh_planar(sldata, vedata);
@@ -566,7 +567,10 @@ void EEVEE_render_draw(EEVEE_Data *vedata, RenderEngine *engine, RenderLayer *rl
/* Refresh Shadows */
EEVEE_lights_update(sldata, vedata);
- EEVEE_draw_shadows(sldata, vedata);
+ EEVEE_draw_shadows(sldata, vedata, stl->effects->taa_view);
+
+ /* Set matrices. */
+ DRW_view_set_active(stl->effects->taa_view);
/* Set ray type. */
sldata->common_data.ray_type = EEVEE_RAY_CAMERA;
diff --git a/source/blender/draw/engines/eevee/eevee_screen_raytrace.c b/source/blender/draw/engines/eevee/eevee_screen_raytrace.c
index ca6c9cdbe94..33a8383fe90 100644
--- a/source/blender/draw/engines/eevee/eevee_screen_raytrace.c
+++ b/source/blender/draw/engines/eevee/eevee_screen_raytrace.c
@@ -127,7 +127,7 @@ int EEVEE_screen_raytrace_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata)
&fbl->refract_fb, {GPU_ATTACHMENT_NONE, GPU_ATTACHMENT_TEXTURE(txl->refract_color)});
}
- const bool is_persp = DRW_viewport_is_persp_get();
+ const bool is_persp = DRW_view_is_persp_get(NULL);
if (effects->ssr_was_persp != is_persp) {
effects->ssr_was_persp = is_persp;
DRW_viewport_request_redraw();
diff --git a/source/blender/draw/engines/eevee/eevee_shaders.c b/source/blender/draw/engines/eevee/eevee_shaders.c
index dbb43e16385..34a3e723161 100644
--- a/source/blender/draw/engines/eevee/eevee_shaders.c
+++ b/source/blender/draw/engines/eevee/eevee_shaders.c
@@ -110,8 +110,11 @@ void EEVEE_shaders_lightprobe_shaders_init(void)
e_data.probe_filter_glossy_sh = DRW_shader_create(
datatoc_lightprobe_vert_glsl, datatoc_lightprobe_geom_glsl, shader_str, filter_defines);
- e_data.probe_default_sh = DRW_shader_create(
- datatoc_background_vert_glsl, NULL, datatoc_default_world_frag_glsl, NULL);
+ e_data.probe_default_sh = DRW_shader_create_with_lib(datatoc_background_vert_glsl,
+ NULL,
+ datatoc_default_world_frag_glsl,
+ datatoc_common_view_lib_glsl,
+ NULL);
MEM_freeN(shader_str);
@@ -178,8 +181,12 @@ GPUShader *EEVEE_shaders_probe_planar_downsample_sh_get(void)
GPUShader *EEVEE_shaders_default_studiolight_sh_get(void)
{
if (e_data.probe_default_studiolight_sh == NULL) {
- e_data.probe_default_studiolight_sh = DRW_shader_create(
- datatoc_background_vert_glsl, NULL, datatoc_default_world_frag_glsl, "#define LOOKDEV\n");
+ e_data.probe_default_studiolight_sh = DRW_shader_create_with_lib(
+ datatoc_background_vert_glsl,
+ NULL,
+ datatoc_default_world_frag_glsl,
+ datatoc_common_view_lib_glsl,
+ "#define LOOKDEV\n");
}
return e_data.probe_default_studiolight_sh;
}
diff --git a/source/blender/draw/engines/eevee/eevee_temporal_sampling.c b/source/blender/draw/engines/eevee/eevee_temporal_sampling.c
index a488e16093a..099147a82dd 100644
--- a/source/blender/draw/engines/eevee/eevee_temporal_sampling.c
+++ b/source/blender/draw/engines/eevee/eevee_temporal_sampling.c
@@ -139,25 +139,27 @@ void EEVEE_temporal_sampling_offset_calc(const double ht_point[2],
r_offset[1] = eval_table(e_data.inverted_cdf, (float)(ht_point[1])) * filter_size;
}
-void EEVEE_temporal_sampling_matrices_calc(EEVEE_EffectsInfo *effects,
- float viewmat[4][4],
- float persmat[4][4],
- const double ht_point[2])
+void EEVEE_temporal_sampling_matrices_calc(EEVEE_EffectsInfo *effects, const double ht_point[2])
{
const float *viewport_size = DRW_viewport_size_get();
const DRWContextState *draw_ctx = DRW_context_state_get();
Scene *scene = draw_ctx->scene;
RenderData *rd = &scene->r;
+ float persmat[4][4], viewmat[4][4], winmat[4][4];
+ DRW_view_persmat_get(NULL, persmat, false);
+ DRW_view_viewmat_get(NULL, viewmat, false);
+ DRW_view_winmat_get(NULL, winmat, false);
+
float ofs[2];
EEVEE_temporal_sampling_offset_calc(ht_point, rd->gauss, ofs);
- window_translate_m4(
- effects->overide_winmat, persmat, ofs[0] / viewport_size[0], ofs[1] / viewport_size[1]);
+ window_translate_m4(winmat, persmat, ofs[0] / viewport_size[0], ofs[1] / viewport_size[1]);
+
+ BLI_assert(effects->taa_view != NULL);
- mul_m4_m4m4(effects->overide_persmat, effects->overide_winmat, viewmat);
- invert_m4_m4(effects->overide_persinv, effects->overide_persmat);
- invert_m4_m4(effects->overide_wininv, effects->overide_winmat);
+ /* When rendering just update the view. This avoids recomputing the culling. */
+ DRW_view_update_sub(effects->taa_view, viewmat, winmat);
}
/* Update the matrices based on the current sample.
@@ -167,23 +169,15 @@ void EEVEE_temporal_sampling_update_matrices(EEVEE_Data *vedata)
EEVEE_StorageList *stl = ((EEVEE_Data *)vedata)->stl;
EEVEE_EffectsInfo *effects = stl->effects;
- float persmat[4][4], viewmat[4][4];
double ht_point[2];
double ht_offset[2] = {0.0, 0.0};
uint ht_primes[2] = {2, 3};
- DRW_viewport_matrix_get(persmat, DRW_MAT_PERS);
- DRW_viewport_matrix_get(viewmat, DRW_MAT_VIEW);
- DRW_viewport_matrix_get(effects->overide_winmat, DRW_MAT_WIN);
-
BLI_halton_2d(ht_primes, ht_offset, effects->taa_current_sample - 1, ht_point);
- EEVEE_temporal_sampling_matrices_calc(effects, viewmat, persmat, ht_point);
+ EEVEE_temporal_sampling_matrices_calc(effects, ht_point);
- DRW_viewport_matrix_override_set(effects->overide_persmat, DRW_MAT_PERS);
- DRW_viewport_matrix_override_set(effects->overide_persinv, DRW_MAT_PERSINV);
- DRW_viewport_matrix_override_set(effects->overide_winmat, DRW_MAT_WIN);
- DRW_viewport_matrix_override_set(effects->overide_wininv, DRW_MAT_WININV);
+ DRW_view_set_active(effects->taa_view);
}
void EEVEE_temporal_sampling_reset(EEVEE_Data *vedata)
@@ -195,8 +189,6 @@ void EEVEE_temporal_sampling_reset(EEVEE_Data *vedata)
int EEVEE_temporal_sampling_init(EEVEE_ViewLayerData *UNUSED(sldata), EEVEE_Data *vedata)
{
EEVEE_StorageList *stl = vedata->stl;
- // EEVEE_FramebufferList *fbl = vedata->fbl;
- // EEVEE_TextureList *txl = vedata->txl;
EEVEE_EffectsInfo *effects = stl->effects;
int repro_flag = 0;
@@ -204,17 +196,26 @@ int EEVEE_temporal_sampling_init(EEVEE_ViewLayerData *UNUSED(sldata), EEVEE_Data
eevee_create_cdf_table_temporal_sampling();
}
- /* Reset for each "redraw". When rendering using ogl render,
+ /**
+ * Reset for each "redraw". When rendering using ogl render,
* we accumulate the redraw inside the drawing loop in eevee_draw_background().
- * But we do NOT accumulate between "redraw" (as in full draw manager drawloop)
- * because the opengl render already does that. */
+ **/
effects->taa_render_sample = 1;
+ effects->taa_view = NULL;
+
+ /* Create a sub view to disable clipping planes (if any). */
+ const DRWView *default_view = DRW_view_default_get();
+ float viewmat[4][4], winmat[4][4];
+ DRW_view_viewmat_get(default_view, viewmat, false);
+ DRW_view_winmat_get(default_view, winmat, false);
+ effects->taa_view = DRW_view_create_sub(default_view, viewmat, winmat);
+ DRW_view_clip_planes_set(effects->taa_view, NULL, 0);
const DRWContextState *draw_ctx = DRW_context_state_get();
const Scene *scene_eval = DEG_get_evaluated_scene(draw_ctx->depsgraph);
if ((scene_eval->eevee.taa_samples != 1) || DRW_state_is_image_render()) {
- float persmat[4][4], viewmat[4][4];
+ float persmat[4][4];
if (!DRW_state_is_image_render() && (scene_eval->eevee.flag & SCE_EEVEE_TAA_REPROJECTION)) {
repro_flag = EFFECT_TAA_REPROJECT | EFFECT_VELOCITY_BUFFER | EFFECT_DEPTH_DOUBLE_BUFFER |
@@ -236,8 +237,7 @@ int EEVEE_temporal_sampling_init(EEVEE_ViewLayerData *UNUSED(sldata), EEVEE_Data
effects->taa_total_sample = scene_eval->eevee.taa_samples;
MAX2(effects->taa_total_sample, 0);
- DRW_viewport_matrix_get(persmat, DRW_MAT_PERS);
- DRW_viewport_matrix_get(viewmat, DRW_MAT_VIEW);
+ DRW_view_persmat_get(NULL, persmat, false);
view_is_valid = view_is_valid && compare_m4m4(persmat, effects->prev_drw_persmat, FLT_MIN);
copy_m4_m4(effects->prev_drw_persmat, persmat);
diff --git a/source/blender/draw/engines/eevee/eevee_volumes.c b/source/blender/draw/engines/eevee/eevee_volumes.c
index 9a59b95b2e8..61277628859 100644
--- a/source/blender/draw/engines/eevee/eevee_volumes.c
+++ b/source/blender/draw/engines/eevee/eevee_volumes.c
@@ -221,7 +221,7 @@ void EEVEE_volumes_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata)
current_sample = effects->taa_current_sample - 1;
effects->volume_current_sample = -1;
}
- else {
+ else if (DRW_state_is_image_render()) {
const uint max_sample = (ht_primes[0] * ht_primes[1] * ht_primes[2]);
current_sample = effects->volume_current_sample = (effects->volume_current_sample + 1) %
max_sample;
@@ -242,11 +242,11 @@ void EEVEE_volumes_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata)
/* Update view_vecs */
float invproj[4][4], winmat[4][4];
- DRW_viewport_matrix_get(winmat, DRW_MAT_WIN);
- DRW_viewport_matrix_get(invproj, DRW_MAT_WININV);
+ DRW_view_winmat_get(NULL, winmat, false);
+ DRW_view_winmat_get(NULL, invproj, true);
EEVEE_update_viewvecs(invproj, winmat, sldata->common_data.view_vecs);
- if (DRW_viewport_is_persp_get()) {
+ if (DRW_view_is_persp_get(NULL)) {
float sample_distribution = scene_eval->eevee.volumetric_sample_distribution;
sample_distribution = 4.0f * (1.00001f - sample_distribution);
diff --git a/source/blender/draw/engines/eevee/shaders/default_world_frag.glsl b/source/blender/draw/engines/eevee/shaders/default_world_frag.glsl
index 0be2a8d6a12..70466479a29 100644
--- a/source/blender/draw/engines/eevee/shaders/default_world_frag.glsl
+++ b/source/blender/draw/engines/eevee/shaders/default_world_frag.glsl
@@ -5,9 +5,6 @@ uniform vec3 color;
out vec4 FragColor;
#ifdef LOOKDEV
-uniform mat4 ProjectionMatrix;
-uniform mat4 ProjectionMatrixInverse;
-uniform mat4 ViewMatrixInverse;
uniform mat3 StudioLightMatrix;
uniform sampler2D image;
uniform float studioLightBackground = 1.0;
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 2b9a325e313..cf20b3ff5b9 100644
--- a/source/blender/draw/engines/eevee/shaders/lit_surface_vert.glsl
+++ b/source/blender/draw/engines/eevee/shaders/lit_surface_vert.glsl
@@ -7,13 +7,6 @@ in vec3 nor;
out vec3 worldPosition;
out vec3 viewPosition;
-/* Used for planar reflections */
-/* keep in sync with EEVEE_ClipPlanesUniformBuffer */
-layout(std140) uniform clip_block
-{
- vec4 ClipPlanes[1];
-};
-
out vec3 worldNormal;
out vec3 viewNormal;
@@ -61,7 +54,7 @@ void main()
gl_Position = point_world_to_ndc(worldPosition);
/* Used for planar reflections */
- gl_ClipDistance[0] = dot(vec4(worldPosition, 1.0), ClipPlanes[0]);
+ gl_ClipDistance[0] = dot(vec4(worldPosition, 1.0), clipPlanes[0]);
#ifdef USE_ATTR
pass_attr(pos);
diff --git a/source/blender/draw/engines/eevee/shaders/prepass_vert.glsl b/source/blender/draw/engines/eevee/shaders/prepass_vert.glsl
index d133889e725..2c7e0aca3fb 100644
--- a/source/blender/draw/engines/eevee/shaders/prepass_vert.glsl
+++ b/source/blender/draw/engines/eevee/shaders/prepass_vert.glsl
@@ -1,12 +1,4 @@
-#ifdef CLIP_PLANES
-/* keep in sync with DRWManager.view_data */
-layout(std140) uniform clip_block
-{
- vec4 ClipPlanes[1];
-};
-#endif
-
#ifndef HAIR_SHADER
in vec3 pos;
#endif
@@ -40,7 +32,7 @@ void main()
gl_Position = point_world_to_ndc(worldPosition);
#ifdef CLIP_PLANES
- gl_ClipDistance[0] = dot(vec4(worldPosition.xyz, 1.0), ClipPlanes[0]);
+ gl_ClipDistance[0] = dot(vec4(worldPosition.xyz, 1.0), clipPlanes[0]);
#endif
/* TODO motion vectors */
}
diff --git a/source/blender/draw/engines/external/external_engine.c b/source/blender/draw/engines/external/external_engine.c
index 1223e31b891..d8748b05f96 100644
--- a/source/blender/draw/engines/external/external_engine.c
+++ b/source/blender/draw/engines/external/external_engine.c
@@ -90,8 +90,7 @@ typedef struct EXTERNAL_PrivateData {
bool update_depth;
bool view_updated;
- float last_mat[4][4];
- float curr_mat[4][4];
+ float last_persmat[4][4];
} EXTERNAL_PrivateData; /* Transient data */
/* Functions */
@@ -126,13 +125,11 @@ static void external_engine_init(void *vedata)
}
{
- float view[4][4];
- float win[4][4];
- DRW_viewport_matrix_get(view, DRW_MAT_VIEW);
- DRW_viewport_matrix_get(win, DRW_MAT_WIN);
- mul_m4_m4m4(stl->g_data->curr_mat, view, win);
- if (!equals_m4m4(stl->g_data->curr_mat, stl->g_data->last_mat)) {
+ float persmat[4][4];
+ DRW_view_persmat_get(NULL, persmat, false);
+ if (!equals_m4m4(persmat, stl->g_data->last_persmat)) {
stl->g_data->update_depth = true;
+ copy_m4_m4(stl->g_data->last_persmat, persmat);
}
}
}
@@ -227,12 +224,14 @@ static void external_draw_scene_do(void *vedata)
/* Rendered draw. */
GPU_matrix_push_projection();
+ GPU_matrix_push();
ED_region_pixelspace(ar);
/* Render result draw. */
type = rv3d->render_engine->type;
type->view_draw(rv3d->render_engine, draw_ctx->evil_C, draw_ctx->depsgraph);
+ GPU_matrix_pop();
GPU_matrix_pop_projection();
/* Set render info. */
@@ -270,8 +269,6 @@ static void external_draw_scene(void *vedata)
// copy tmp buffer to default
GPU_framebuffer_blit(fbl->depth_buffer_fb, 0, dfbl->depth_only_fb, 0, GPU_DEPTH_BIT);
}
-
- copy_m4_m4(stl->g_data->last_mat, stl->g_data->curr_mat);
}
static void external_view_update(void *vedata)
diff --git a/source/blender/draw/engines/gpencil/gpencil_engine.h b/source/blender/draw/engines/gpencil/gpencil_engine.h
index 9ebd168bc4c..5dab0a56b63 100644
--- a/source/blender/draw/engines/gpencil/gpencil_engine.h
+++ b/source/blender/draw/engines/gpencil/gpencil_engine.h
@@ -187,9 +187,7 @@ typedef struct GPENCIL_Storage {
float mix_stroke_factor;
/* Render Matrices and data */
- float persmat[4][4], persinv[4][4];
- float viewmat[4][4], viewinv[4][4];
- float winmat[4][4], wininv[4][4];
+ DRWView *view;
float view_vecs[2][4]; /* vec4[2] */
float grid_matrix[4][4];
diff --git a/source/blender/draw/engines/gpencil/gpencil_render.c b/source/blender/draw/engines/gpencil/gpencil_render.c
index e6a3f45d60d..301c29af335 100644
--- a/source/blender/draw/engines/gpencil/gpencil_render.c
+++ b/source/blender/draw/engines/gpencil/gpencil_render.c
@@ -94,26 +94,26 @@ void GPENCIL_render_init(GPENCIL_Data *ved, RenderEngine *engine, struct Depsgra
}
/* Set the pers & view matrix. */
+ float winmat[4][4], viewmat[4][4], viewinv[4][4], persmat[4][4];
+
struct Object *camera = DEG_get_evaluated_object(depsgraph, RE_GetCamera(engine->re));
float frame = BKE_scene_frame_get(scene);
- RE_GetCameraWindow(engine->re, camera, frame, stl->storage->winmat);
- RE_GetCameraModelMatrix(engine->re, camera, stl->storage->viewinv);
+ RE_GetCameraWindow(engine->re, camera, frame, winmat);
+ RE_GetCameraModelMatrix(engine->re, camera, viewinv);
+
+ invert_m4_m4(viewmat, viewinv);
- invert_m4_m4(stl->storage->viewmat, stl->storage->viewinv);
- mul_m4_m4m4(stl->storage->persmat, stl->storage->winmat, stl->storage->viewmat);
- invert_m4_m4(stl->storage->persinv, stl->storage->persmat);
- invert_m4_m4(stl->storage->wininv, stl->storage->winmat);
+ DRWView *view = DRW_view_create(viewmat, winmat, NULL, NULL, NULL);
+ DRW_view_default_set(view);
+ DRW_view_set_active(view);
- DRW_viewport_matrix_override_set(stl->storage->persmat, DRW_MAT_PERS);
- DRW_viewport_matrix_override_set(stl->storage->persinv, DRW_MAT_PERSINV);
- DRW_viewport_matrix_override_set(stl->storage->winmat, DRW_MAT_WIN);
- DRW_viewport_matrix_override_set(stl->storage->wininv, DRW_MAT_WININV);
- DRW_viewport_matrix_override_set(stl->storage->viewmat, DRW_MAT_VIEW);
- DRW_viewport_matrix_override_set(stl->storage->viewinv, DRW_MAT_VIEWINV);
+ DRW_view_persmat_get(view, persmat, false);
/* calculate pixel size for render */
- stl->storage->render_pixsize = get_render_pixelsize(
- stl->storage->persmat, viewport_size[0], viewport_size[1]);
+ stl->storage->render_pixsize = get_render_pixelsize(persmat, viewport_size[0], viewport_size[1]);
+
+ stl->storage->view = view;
+
/* INIT CACHE */
GPENCIL_cache_init(vedata);
}
@@ -180,8 +180,8 @@ static void GPENCIL_render_update_vecs(GPENCIL_Data *vedata)
GPENCIL_StorageList *stl = vedata->stl;
float invproj[4][4], winmat[4][4];
- DRW_viewport_matrix_get(winmat, DRW_MAT_WIN);
- DRW_viewport_matrix_get(invproj, DRW_MAT_WININV);
+ DRW_view_winmat_get(NULL, winmat, false);
+ DRW_view_winmat_get(NULL, invproj, true);
/* this is separated to keep function equal to Eevee for future reuse of same code */
GPENCIL_render_update_viewvecs(invproj, winmat, stl->storage->view_vecs);
@@ -207,10 +207,13 @@ static void GPENCIL_render_result_z(struct RenderLayer *rl,
BLI_rcti_size_y(rect),
rp->rect);
- bool is_persp = DRW_viewport_is_persp_get();
+ bool is_persp = DRW_view_is_persp_get(NULL);
GPENCIL_render_update_vecs(vedata);
+ float winmat[4][4];
+ DRW_view_winmat_get(stl->storage->view, winmat, false);
+
/* Convert ogl depth [0..1] to view Z [near..far] */
for (int i = 0; i < BLI_rcti_size_x(rect) * BLI_rcti_size_y(rect); i++) {
if (rp->rect[i] == 1.0f) {
@@ -219,7 +222,7 @@ static void GPENCIL_render_result_z(struct RenderLayer *rl,
else {
if (is_persp) {
rp->rect[i] = rp->rect[i] * 2.0f - 1.0f;
- rp->rect[i] = stl->storage->winmat[3][2] / (rp->rect[i] + stl->storage->winmat[2][2]);
+ rp->rect[i] = winmat[3][2] / (rp->rect[i] + winmat[2][2]);
}
else {
rp->rect[i] = -stl->storage->view_vecs[0][2] +
diff --git a/source/blender/draw/engines/gpencil/gpencil_shader_fx.c b/source/blender/draw/engines/gpencil/gpencil_shader_fx.c
index d46e850ba82..9eb4123e5bc 100644
--- a/source/blender/draw/engines/gpencil/gpencil_shader_fx.c
+++ b/source/blender/draw/engines/gpencil/gpencil_shader_fx.c
@@ -110,22 +110,13 @@ static void GPENCIL_dof_nearfar(Object *camera, float coc, float nearfar[2])
if (camera == NULL) {
return;
}
-
- const DRWContextState *draw_ctx = DRW_context_state_get();
- Scene *scene = draw_ctx->scene;
- Camera *cam = (Camera *)camera->data;
+ Camera *cam = camera->data;
float fstop = cam->dof.aperture_fstop;
float focus_dist = BKE_camera_object_dof_distance(camera);
float focal_len = cam->lens;
- /* This is factor that converts to the scene scale. focal length and sensor are expressed in mm
- * unit.scale_length is how many meters per blender unit we have. We want to convert to blender
- * units though because the shader reads coordinates in world space, which is in blender units.
- * Note however that focus_distance is already in blender units and shall not be scaled here
- * (see T48157). */
- float scale = (scene->unit.system) ? scene->unit.scale_length : 1.0f;
- float scale_camera = 0.001f / scale;
+ const float scale_camera = 0.001f;
/* we want radius here for the aperture number */
float aperture_scaled = 0.5f * scale_camera * focal_len / fstop;
float focal_len_scaled = scale_camera * focal_len;
diff --git a/source/blender/draw/engines/workbench/shaders/workbench_effect_fxaa_frag.glsl b/source/blender/draw/engines/workbench/shaders/workbench_effect_fxaa_frag.glsl
index 46b0361245b..092878e43aa 100644
--- a/source/blender/draw/engines/workbench/shaders/workbench_effect_fxaa_frag.glsl
+++ b/source/blender/draw/engines/workbench/shaders/workbench_effect_fxaa_frag.glsl
@@ -8,6 +8,9 @@ uniform vec2 invertedViewportSize;
void main()
{
+ ivec2 texel = ivec2(gl_FragCoord.xy);
+ float alpha = texelFetch(colorBuffer, texel, 0).a;
FragColor = FxaaPixelShader(
uvcoordsvar.st, colorBuffer, invertedViewportSize, 1.0, 0.166, 0.0833);
+ FragColor.a = alpha;
}
diff --git a/source/blender/draw/engines/workbench/shaders/workbench_volume_frag.glsl b/source/blender/draw/engines/workbench/shaders/workbench_volume_frag.glsl
index 848cd49bf53..fd06c85747f 100644
--- a/source/blender/draw/engines/workbench/shaders/workbench_volume_frag.glsl
+++ b/source/blender/draw/engines/workbench/shaders/workbench_volume_frag.glsl
@@ -216,8 +216,8 @@ void main()
vs_ray_dir /= abs(vs_ray_dir.z);
/* TODO(fclem) Precompute the matrix/ */
- vec3 ls_ray_dir = vs_ray_dir * OrcoTexCoFactors[1] * 2.0;
- ls_ray_dir = mat3(ModelMatrixInverse) * (mat3(ViewMatrixInverse) * ls_ray_dir);
+ vec3 ls_ray_dir = mat3(ViewMatrixInverse) * vs_ray_dir * OrcoTexCoFactors[1] * 2.0;
+ ls_ray_dir = mat3(ModelMatrixInverse) * ls_ray_dir;
vec3 ls_ray_ori = point_view_to_object(vs_ray_ori);
vec3 ls_ray_end = point_view_to_object(vs_ray_end);
diff --git a/source/blender/draw/engines/workbench/workbench_data.c b/source/blender/draw/engines/workbench/workbench_data.c
index 7728b3f998b..fce1d725133 100644
--- a/source/blender/draw/engines/workbench/workbench_data.c
+++ b/source/blender/draw/engines/workbench/workbench_data.c
@@ -127,7 +127,6 @@ void workbench_private_data_init(WORKBENCH_PrivateData *wpd)
RegionView3D *rv3d = draw_ctx->rv3d;
if (rv3d->rflag & RV3D_CLIPPING) {
wpd->world_clip_planes = rv3d->clip;
- DRW_state_clip_planes_set_from_rv3d(rv3d);
UI_GetThemeColor4fv(TH_V3D_CLIPPING_BORDER, wpd->world_clip_planes_color);
if (wpd->use_color_management) {
srgb_to_linearrgb_v3_v3(wpd->world_clip_planes_color, wpd->world_clip_planes_color);
@@ -148,7 +147,7 @@ void workbench_private_data_init(WORKBENCH_PrivateData *wpd)
const int ssao_samples = scene->display.matcap_ssao_samples;
float invproj[4][4];
- const bool is_persp = DRW_viewport_is_persp_get();
+ const bool is_persp = DRW_view_is_persp_get(NULL);
/* view vectors for the corners of the view frustum.
* Can be used to recreate the world space position easily */
float viewvecs[3][4] = {
@@ -171,9 +170,8 @@ void workbench_private_data_init(WORKBENCH_PrivateData *wpd)
wpd->shading.cavity_ridge_factor,
scene->display.matcap_ssao_attenuation);
- /* invert the view matrix */
- DRW_viewport_matrix_get(wpd->winmat, DRW_MAT_WIN);
- invert_m4_m4(invproj, wpd->winmat);
+ DRW_view_winmat_get(NULL, wpd->winmat, false);
+ DRW_view_winmat_get(NULL, invproj, true);
/* convert the view vectors to view space */
for (i = 0; i < 3; i++) {
@@ -213,7 +211,7 @@ void workbench_private_data_get_light_direction(WORKBENCH_PrivateData *wpd,
Scene *scene = draw_ctx->scene;
WORKBENCH_UBO_World *wd = &wpd->world_data;
float view_matrix[4][4];
- DRW_viewport_matrix_get(view_matrix, DRW_MAT_VIEW);
+ DRW_view_viewmat_get(NULL, view_matrix, false);
copy_v3_v3(r_light_direction, scene->display.light_direction);
SWAP(float, r_light_direction[2], r_light_direction[1]);
diff --git a/source/blender/draw/engines/workbench/workbench_deferred.c b/source/blender/draw/engines/workbench/workbench_deferred.c
index eacd319cc4a..28104a87b9a 100644
--- a/source/blender/draw/engines/workbench/workbench_deferred.c
+++ b/source/blender/draw/engines/workbench/workbench_deferred.c
@@ -983,6 +983,8 @@ void workbench_deferred_solid_cache_populate(WORKBENCH_Data *vedata, Object *ob)
workbench_material_get_image_and_mat(ob, i + 1, &image, &iuser, &interp, &mat);
int color_type = workbench_material_determine_color_type(wpd, image, ob, is_sculpt_mode);
if (color_type == V3D_SHADING_MATERIAL_COLOR && mat && mat->a < 1.0) {
+ /* Hack */
+ wpd->shading.xray_alpha = mat->a;
material = workbench_forward_get_or_create_material_data(
vedata, ob, mat, image, iuser, color_type, 0, is_sculpt_mode);
has_transp_mat = true;
diff --git a/source/blender/draw/engines/workbench/workbench_effect_aa.c b/source/blender/draw/engines/workbench/workbench_effect_aa.c
index b4cdcfcfc99..965f5a5ca4f 100644
--- a/source/blender/draw/engines/workbench/workbench_effect_aa.c
+++ b/source/blender/draw/engines/workbench/workbench_effect_aa.c
@@ -49,6 +49,7 @@ void workbench_aa_create_pass(WORKBENCH_Data *vedata, GPUTexture **tx)
}
else {
psl->effect_aa_pass = NULL;
+ effect_info->jitter_index = 0;
}
}
diff --git a/source/blender/draw/engines/workbench/workbench_effect_dof.c b/source/blender/draw/engines/workbench/workbench_effect_dof.c
index 6886b73650c..e24536759db 100644
--- a/source/blender/draw/engines/workbench/workbench_effect_dof.c
+++ b/source/blender/draw/engines/workbench/workbench_effect_dof.c
@@ -231,7 +231,6 @@ void workbench_dof_engine_init(WORKBENCH_Data *vedata, Object *camera)
{
const DRWContextState *draw_ctx = DRW_context_state_get();
- const Scene *scene_eval = DEG_get_evaluated_scene(draw_ctx->depsgraph);
RegionView3D *rv3d = draw_ctx->rv3d;
/* Parameters */
@@ -242,14 +241,7 @@ void workbench_dof_engine_init(WORKBENCH_Data *vedata, Object *camera)
float focal_len = cam->lens;
/* TODO(fclem) deduplicate with eevee */
-
- /* this is factor that converts to the scene scale. focal length and sensor are expressed in mm
- * unit.scale_length is how many meters per blender unit we have. We want to convert to blender
- * units though because the shader reads coordinates in world space, which is in blender units.
- * Note however that focus_distance is already in blender units and shall not be scaled here
- * (see T48157). */
- float scale = (scene_eval->unit.system) ? scene_eval->unit.scale_length : 1.0f;
- float scale_camera = 0.001f / scale;
+ const float scale_camera = 0.001f;
/* we want radius here for the aperture number */
float aperture = 0.5f * scale_camera * focal_len / fstop;
float focal_len_scaled = scale_camera * focal_len;
diff --git a/source/blender/draw/engines/workbench/workbench_effect_taa.c b/source/blender/draw/engines/workbench/workbench_effect_taa.c
index 7b2faf0ddcd..7fd68babc13 100644
--- a/source/blender/draw/engines/workbench/workbench_effect_taa.c
+++ b/source/blender/draw/engines/workbench/workbench_effect_taa.c
@@ -135,6 +135,8 @@ void workbench_taa_engine_init(WORKBENCH_Data *vedata)
workbench_taa_jitter_init();
}
+ effect_info->view = NULL;
+
/* reset complete drawing when navigating. */
if (effect_info->jitter_index != 0) {
if (rv3d && rv3d->rflag & RV3D_NAVIGATING) {
@@ -148,12 +150,10 @@ void workbench_taa_engine_init(WORKBENCH_Data *vedata)
}
{
- float view[4][4];
- float win[4][4];
- DRW_viewport_matrix_get(view, DRW_MAT_VIEW);
- DRW_viewport_matrix_get(win, DRW_MAT_WIN);
- mul_m4_m4m4(effect_info->curr_mat, view, win);
- if (!equals_m4m4(effect_info->curr_mat, effect_info->last_mat)) {
+ float persmat[4][4];
+ DRW_view_persmat_get(NULL, persmat, false);
+ if (!equals_m4m4(persmat, effect_info->last_mat)) {
+ copy_m4_m4(effect_info->last_mat, persmat);
effect_info->jitter_index = 0;
}
}
@@ -217,9 +217,9 @@ void workbench_taa_draw_scene_start(WORKBENCH_Data *vedata)
WORKBENCH_StorageList *stl = vedata->stl;
WORKBENCH_EffectInfo *effect_info = stl->effects;
const float *viewport_size = DRW_viewport_size_get();
+ const DRWView *default_view = DRW_view_default_get();
int num_samples = 8;
float(*samples)[2];
- float mix_factor;
num_samples = workbench_taa_calculate_num_iterations(vedata);
switch (num_samples) {
@@ -241,41 +241,38 @@ void workbench_taa_draw_scene_start(WORKBENCH_Data *vedata)
break;
}
- mix_factor = 1.0f / (effect_info->jitter_index + 1);
-
const int jitter_index = effect_info->jitter_index;
const float *transform_offset = samples[jitter_index];
+ effect_info->taa_mix_factor = 1.0f / (jitter_index + 1);
effect_info->jitter_index = (jitter_index + 1) % num_samples;
/* construct new matrices from transform delta */
- float viewmat[4][4];
- float persmat[4][4];
- DRW_viewport_matrix_get(viewmat, DRW_MAT_VIEW);
- DRW_viewport_matrix_get(persmat, DRW_MAT_PERS);
- DRW_viewport_matrix_get(effect_info->override_winmat, DRW_MAT_WIN);
+ float winmat[4][4], viewmat[4][4], persmat[4][4];
+ DRW_view_winmat_get(default_view, winmat, false);
+ DRW_view_viewmat_get(default_view, viewmat, false);
+ DRW_view_persmat_get(default_view, persmat, false);
- window_translate_m4(effect_info->override_winmat,
+ window_translate_m4(winmat,
persmat,
transform_offset[0] / viewport_size[0],
transform_offset[1] / viewport_size[1]);
- mul_m4_m4m4(effect_info->override_persmat, effect_info->override_winmat, viewmat);
- invert_m4_m4(effect_info->override_persinv, effect_info->override_persmat);
- invert_m4_m4(effect_info->override_wininv, effect_info->override_winmat);
-
- DRW_viewport_matrix_override_set(effect_info->override_persmat, DRW_MAT_PERS);
- DRW_viewport_matrix_override_set(effect_info->override_persinv, DRW_MAT_PERSINV);
- DRW_viewport_matrix_override_set(effect_info->override_winmat, DRW_MAT_WIN);
- DRW_viewport_matrix_override_set(effect_info->override_wininv, DRW_MAT_WININV);
-
- /* weight the mix factor by the jitter index */
- effect_info->taa_mix_factor = mix_factor;
+ if (effect_info->view) {
+ /* When rendering just update the view. This avoids recomputing the culling. */
+ DRW_view_update_sub(effect_info->view, viewmat, winmat);
+ }
+ else {
+ /* TAA is not making a big change to the matrices.
+ * Reuse the main view culling by creating a subview. */
+ effect_info->view = DRW_view_create_sub(default_view, viewmat, winmat);
+ }
+ DRW_view_set_active(effect_info->view);
}
void workbench_taa_draw_scene_end(WORKBENCH_Data *vedata)
{
/*
- * If first frame than the offset is 0.0 and its depth is the depth buffer to use
+ * If first frame then the offset is 0.0 and its depth is the depth buffer to use
* for the rest of the draw engines. We store it in a persistent buffer.
*
* If it is not the first frame we copy the persistent buffer back to the
@@ -296,10 +293,9 @@ void workbench_taa_draw_scene_end(WORKBENCH_Data *vedata)
GPU_framebuffer_blit(dfbl->color_only_fb, 0, fbl->effect_taa_fb, 0, GPU_COLOR_BIT);
if (!DRW_state_is_image_render()) {
- DRW_viewport_matrix_override_unset_all();
+ DRW_view_set_active(NULL);
}
- copy_m4_m4(effect_info->last_mat, effect_info->curr_mat);
if (effect_info->jitter_index != 0 && !DRW_state_is_image_render()) {
DRW_viewport_request_redraw();
}
diff --git a/source/blender/draw/engines/workbench/workbench_forward.c b/source/blender/draw/engines/workbench/workbench_forward.c
index f12902b6801..5f15fb3f19e 100644
--- a/source/blender/draw/engines/workbench/workbench_forward.c
+++ b/source/blender/draw/engines/workbench/workbench_forward.c
@@ -212,7 +212,7 @@ WORKBENCH_MaterialData *workbench_forward_get_or_create_material_data(WORKBENCH_
material->object_id = engine_object_data->object_id;
DRW_shgroup_uniform_int(material->shgrp_object_outline, "object_id", &material->object_id, 1);
if (draw_ctx->sh_cfg == GPU_SHADER_CFG_CLIPPED) {
- DRW_shgroup_world_clip_planes_from_rv3d(material->shgrp_object_outline, draw_ctx->rv3d);
+ DRW_shgroup_state_enable(material->shgrp_object_outline, DRW_STATE_CLIP_PLANES);
}
BLI_ghash_insert(wpd->material_transp_hash, POINTER_FROM_UINT(hash), material);
}
diff --git a/source/blender/draw/engines/workbench/workbench_materials.c b/source/blender/draw/engines/workbench/workbench_materials.c
index b280b6fd01a..02fbbe0b042 100644
--- a/source/blender/draw/engines/workbench/workbench_materials.c
+++ b/source/blender/draw/engines/workbench/workbench_materials.c
@@ -52,7 +52,7 @@ void workbench_material_update_data(WORKBENCH_PrivateData *wpd,
copy_v3_v3(data->base_color, data->diffuse_color);
copy_v3_fl3(data->specular_color, 0.05f, 0.05f, 0.05f); /* Dielectric: 5% reflective. */
data->metallic = 0.0f;
- data->roughness = 0.5f; /* sqrtf(0.25f); */
+ data->roughness = 0.632455532f; /* sqrtf(0.4f); */
if (color_type == V3D_SHADING_SINGLE_COLOR) {
copy_v3_v3(data->diffuse_color, wpd->shading.single_color);
@@ -316,7 +316,6 @@ void workbench_material_shgroup_uniform(WORKBENCH_PrivateData *wpd,
}
if (WORLD_CLIPPING_ENABLED(wpd)) {
- DRW_shgroup_uniform_vec4(grp, "WorldClipPlanes", wpd->world_clip_planes[0], 6);
DRW_shgroup_state_enable(grp, DRW_STATE_CLIP_PLANES);
}
}
diff --git a/source/blender/draw/engines/workbench/workbench_private.h b/source/blender/draw/engines/workbench/workbench_private.h
index 09d9ad65717..240d06c1e79 100644
--- a/source/blender/draw/engines/workbench/workbench_private.h
+++ b/source/blender/draw/engines/workbench/workbench_private.h
@@ -273,12 +273,10 @@ typedef struct WORKBENCH_PrivateData {
} WORKBENCH_PrivateData; /* Transient data */
typedef struct WORKBENCH_EffectInfo {
- float override_persmat[4][4];
- float override_persinv[4][4];
- float override_winmat[4][4];
- float override_wininv[4][4];
+ /** View */
+ struct DRWView *view;
+ /** Last projection matrix to see if view is still valid. */
float last_mat[4][4];
- float curr_mat[4][4];
int jitter_index;
float taa_mix_factor;
bool view_updated;
@@ -328,7 +326,8 @@ BLI_INLINE bool workbench_is_taa_enabled(WORKBENCH_PrivateData *wpd)
}
}
else {
- return wpd->preferences->viewport_aa > SCE_DISPLAY_AA_FXAA && !wpd->is_playback;
+ return !(IS_NAVIGATING(wpd) || wpd->is_playback) &&
+ wpd->preferences->viewport_aa > SCE_DISPLAY_AA_FXAA;
}
}
@@ -348,8 +347,9 @@ BLI_INLINE bool workbench_is_fxaa_enabled(WORKBENCH_PrivateData *wpd)
return true;
}
- /* when navigating or animation playback use FXAA. */
- return (IS_NAVIGATING(wpd) || wpd->is_playback) && workbench_is_taa_enabled(wpd);
+ /* when navigating or animation playback use FXAA if scene uses TAA. */
+ return (IS_NAVIGATING(wpd) || wpd->is_playback) &&
+ wpd->preferences->viewport_aa > SCE_DISPLAY_AA_FXAA;
}
}
diff --git a/source/blender/draw/engines/workbench/workbench_render.c b/source/blender/draw/engines/workbench/workbench_render.c
index 1497ef493cf..46d78ca0e37 100644
--- a/source/blender/draw/engines/workbench/workbench_render.c
+++ b/source/blender/draw/engines/workbench/workbench_render.c
@@ -63,24 +63,16 @@ static void workbench_render_matrices_init(RenderEngine *engine, Depsgraph *deps
float frame = BKE_scene_frame_get(scene);
/* Set the persective, view and window matrix. */
- float winmat[4][4], wininv[4][4];
- float viewmat[4][4], viewinv[4][4];
- float persmat[4][4], persinv[4][4];
+ float winmat[4][4], viewmat[4][4], viewinv[4][4];
RE_GetCameraWindow(engine->re, ob_camera_eval, frame, winmat);
RE_GetCameraModelMatrix(engine->re, ob_camera_eval, viewinv);
invert_m4_m4(viewmat, viewinv);
- mul_m4_m4m4(persmat, winmat, viewmat);
- invert_m4_m4(persinv, persmat);
- invert_m4_m4(wininv, winmat);
-
- DRW_viewport_matrix_override_set(persmat, DRW_MAT_PERS);
- DRW_viewport_matrix_override_set(persinv, DRW_MAT_PERSINV);
- DRW_viewport_matrix_override_set(winmat, DRW_MAT_WIN);
- DRW_viewport_matrix_override_set(wininv, DRW_MAT_WININV);
- DRW_viewport_matrix_override_set(viewmat, DRW_MAT_VIEW);
- DRW_viewport_matrix_override_set(viewinv, DRW_MAT_VIEWINV);
+
+ DRWView *view = DRW_view_create(viewmat, winmat, NULL, NULL, NULL);
+ DRW_view_default_set(view);
+ DRW_view_set_active(view);
}
static bool workbench_render_framebuffers_init(void)
@@ -159,9 +151,6 @@ void workbench_render(WORKBENCH_Data *data,
if (RE_engine_test_break(engine)) {
break;
}
- /* TODO: Save matrices instead of recomputing them for each samples. */
- workbench_render_matrices_init(engine, depsgraph);
-
workbench_deferred_draw_background(data);
workbench_deferred_draw_scene(data);
}
diff --git a/source/blender/draw/engines/workbench/workbench_studiolight.c b/source/blender/draw/engines/workbench/workbench_studiolight.c
index 3fc83fea7c6..944bca73993 100644
--- a/source/blender/draw/engines/workbench/workbench_studiolight.c
+++ b/source/blender/draw/engines/workbench/workbench_studiolight.c
@@ -32,7 +32,7 @@ void studiolight_update_world(WORKBENCH_PrivateData *wpd,
WORKBENCH_UBO_World *wd)
{
float view_matrix[4][4], rot_matrix[4][4];
- DRW_viewport_matrix_get(view_matrix, DRW_MAT_VIEW);
+ DRW_view_viewmat_get(NULL, view_matrix, false);
if (USE_WORLD_ORIENTATION(wpd)) {
axis_angle_to_mat4_single(rot_matrix, 'Z', -wpd->shading.studiolight_rot_z);
@@ -165,12 +165,12 @@ void studiolight_update_light(WORKBENCH_PrivateData *wpd, const float light_dire
}
float planes[6][4];
- DRW_culling_frustum_planes_get(planes);
+ DRW_culling_frustum_planes_get(NULL, planes);
/* we only need the far plane. */
copy_v4_v4(wpd->shadow_far_plane, planes[2]);
BoundBox frustum_corners;
- DRW_culling_frustum_corners_get(&frustum_corners);
+ DRW_culling_frustum_corners_get(NULL, &frustum_corners);
mul_v3_mat3_m4v3(wpd->shadow_near_corners[0], wpd->shadow_inv, frustum_corners.vec[0]);
mul_v3_mat3_m4v3(wpd->shadow_near_corners[1], wpd->shadow_inv, frustum_corners.vec[3]);
@@ -230,7 +230,8 @@ bool studiolight_object_cast_visible_shadow(WORKBENCH_PrivateData *wpd,
WORKBENCH_ObjectData *oed)
{
BoundBox *shadow_bbox = studiolight_object_shadow_bbox_get(wpd, ob, oed);
- return DRW_culling_box_test(shadow_bbox);
+ const DRWView *default_view = DRW_view_default_get();
+ return DRW_culling_box_test(default_view, shadow_bbox);
}
float studiolight_object_shadow_distance(WORKBENCH_PrivateData *wpd,
diff --git a/source/blender/draw/engines/workbench/workbench_volume.c b/source/blender/draw/engines/workbench/workbench_volume.c
index 1620584dc06..2b5fc8c0e47 100644
--- a/source/blender/draw/engines/workbench/workbench_volume.c
+++ b/source/blender/draw/engines/workbench/workbench_volume.c
@@ -154,7 +154,7 @@ void workbench_volume_cache_populate(WORKBENCH_Data *vedata,
if (use_slice) {
float invviewmat[4][4];
- DRW_viewport_matrix_get(invviewmat, DRW_MAT_VIEWINV);
+ DRW_view_viewmat_get(NULL, invviewmat, true);
const int axis = (sds->slice_axis == SLICE_AXIS_AUTO) ?
axis_dominant_v3_single(invviewmat[2]) :
diff --git a/source/blender/draw/intern/DRW_render.h b/source/blender/draw/intern/DRW_render.h
index 98e974a09b5..a33060bfbbe 100644
--- a/source/blender/draw/intern/DRW_render.h
+++ b/source/blender/draw/intern/DRW_render.h
@@ -81,6 +81,7 @@ struct rcti;
typedef struct DRWInterface DRWInterface;
typedef struct DRWPass DRWPass;
+typedef struct DRWView DRWView;
typedef struct DRWShadingGroup DRWShadingGroup;
typedef struct DRWUniform DRWUniform;
@@ -353,10 +354,6 @@ typedef enum {
DRW_STATE_CLIP_PLANES = (1 << 22),
DRW_STATE_WIRE_SMOOTH = (1 << 23),
DRW_STATE_FIRST_VERTEX_CONVENTION = (1 << 24),
- /** Polygon offset. Does not work with lines and points. */
- DRW_STATE_OFFSET_POSITIVE = (1 << 25),
- /** Polygon offset. Does not work with lines and points. */
- DRW_STATE_OFFSET_NEGATIVE = (1 << 26),
} DRWState;
#define DRW_STATE_DEFAULT \
@@ -397,7 +394,6 @@ DRWShadingGroup *DRW_shgroup_transform_feedback_create(struct GPUShader *shader,
/* return final visibility */
typedef bool(DRWCallVisibilityFn)(bool vis_in, void *user_data);
-/* TODO(fclem): Remove the _add suffix. */
void DRW_shgroup_call(DRWShadingGroup *sh, struct GPUBatch *geom, float (*obmat)[4]);
void DRW_shgroup_call_range(
DRWShadingGroup *sh, struct GPUBatch *geom, float (*obmat)[4], uint v_sta, uint v_ct);
@@ -416,10 +412,10 @@ void DRW_shgroup_call_object_ex(DRWShadingGroup *shgroup,
DRW_shgroup_call_object_ex(shgroup, geom, ob, true)
/* TODO(fclem) remove this when we have DRWView */
+/* user_data is used by DRWCallVisibilityFn defined in DRWView. */
void DRW_shgroup_call_object_with_callback(DRWShadingGroup *shgroup,
struct GPUBatch *geom,
struct Object *ob,
- DRWCallVisibilityFn *callback,
void *user_data);
void DRW_shgroup_call_instances(DRWShadingGroup *shgroup,
@@ -484,14 +480,6 @@ void DRW_shgroup_uniform_vec4(DRWShadingGroup *shgroup,
const char *name,
const float *value,
int arraysize);
-void DRW_shgroup_uniform_short_to_int(DRWShadingGroup *shgroup,
- const char *name,
- const short *value,
- int arraysize);
-void DRW_shgroup_uniform_short_to_float(DRWShadingGroup *shgroup,
- const char *name,
- const short *value,
- int arraysize);
/* Boolean are expected to be 4bytes longs for opengl! */
void DRW_shgroup_uniform_bool(DRWShadingGroup *shgroup,
const char *name,
@@ -525,6 +513,7 @@ bool DRW_shgroup_is_empty(DRWShadingGroup *shgroup);
/* Passes */
DRWPass *DRW_pass_create(const char *name, DRWState state);
+/* TODO Replace with passes inheritance. */
void DRW_pass_state_set(DRWPass *pass, DRWState state);
void DRW_pass_state_add(DRWPass *pass, DRWState state);
void DRW_pass_state_remove(DRWPass *pass, DRWState state);
@@ -537,51 +526,59 @@ bool DRW_pass_is_empty(DRWPass *pass);
#define DRW_PASS_CREATE(pass, state) (pass = DRW_pass_create(#pass, state))
-/* Viewport */
-typedef enum {
- /* keep in sync with the union struct DRWMatrixState. */
- DRW_MAT_PERS = 0,
- DRW_MAT_PERSINV,
- DRW_MAT_VIEW,
- DRW_MAT_VIEWINV,
- DRW_MAT_WIN,
- DRW_MAT_WININV,
-
- DRW_MAT_COUNT, // Don't use this.
-} DRWViewportMatrixType;
-
-typedef struct DRWMatrixState {
- union {
- float mat[DRW_MAT_COUNT][4][4];
- struct {
- /* keep in sync with the enum DRWViewportMatrixType. */
- float persmat[4][4];
- float persinv[4][4];
- float viewmat[4][4];
- float viewinv[4][4];
- float winmat[4][4];
- float wininv[4][4];
- };
- };
-} DRWMatrixState;
-
-void DRW_viewport_matrix_get(float mat[4][4], DRWViewportMatrixType type);
-void DRW_viewport_matrix_get_all(DRWMatrixState *state);
-void DRW_viewport_matrix_override_set(const float mat[4][4], DRWViewportMatrixType type);
-void DRW_viewport_matrix_override_set_all(DRWMatrixState *state);
-void DRW_viewport_matrix_override_unset(DRWViewportMatrixType type);
-void DRW_viewport_matrix_override_unset_all(void);
-
-/* These are in view-space so negative if in perspective.
+/* Views */
+DRWView *DRW_view_create(const float viewmat[4][4],
+ const float winmat[4][4],
+ const float (*culling_viewmat)[4],
+ const float (*culling_winmat)[4],
+ DRWCallVisibilityFn *visibility_fn);
+DRWView *DRW_view_create_sub(const DRWView *parent_view,
+ const float viewmat[4][4],
+ const float winmat[4][4]);
+
+void DRW_view_update(DRWView *view,
+ const float viewmat[4][4],
+ const float winmat[4][4],
+ const float (*culling_viewmat)[4],
+ const float (*culling_winmat)[4]);
+void DRW_view_update_sub(DRWView *view, const float viewmat[4][4], const float winmat[4][4]);
+
+const DRWView *DRW_view_default_get(void);
+void DRW_view_default_set(DRWView *view);
+
+void DRW_view_set_active(DRWView *view);
+
+void DRW_view_clip_planes_set(DRWView *view, float (*planes)[4], int plane_len);
+void DRW_view_camtexco_set(DRWView *view, float texco[4]);
+
+/* For all getters, if view is NULL, default view is assumed. */
+void DRW_view_winmat_get(const DRWView *view, float mat[4][4], bool inverse);
+void DRW_view_viewmat_get(const DRWView *view, float mat[4][4], bool inverse);
+void DRW_view_persmat_get(const DRWView *view, float mat[4][4], bool inverse);
+
+void DRW_view_frustum_corners_get(const DRWView *view, BoundBox *corners);
+void DRW_view_frustum_planes_get(const DRWView *view, float planes[6][4]);
+
+/* These are in view-space, so negative if in perspective.
* Extract near and far clip distance from the projection matrix. */
-float DRW_viewport_near_distance_get(void);
-float DRW_viewport_far_distance_get(void);
+float DRW_view_near_distance_get(const DRWView *view);
+float DRW_view_far_distance_get(const DRWView *view);
+bool DRW_view_is_persp_get(const DRWView *view);
+
+/* Culling, return true if object is inside view frustum. */
+bool DRW_culling_sphere_test(const DRWView *view, const BoundSphere *bsphere);
+bool DRW_culling_box_test(const DRWView *view, const BoundBox *bbox);
+bool DRW_culling_plane_test(const DRWView *view, const float plane[4]);
+
+void DRW_culling_frustum_corners_get(const DRWView *view, BoundBox *corners);
+void DRW_culling_frustum_planes_get(const DRWView *view, float planes[6][4]);
+
+/* Viewport */
const float *DRW_viewport_size_get(void);
const float *DRW_viewport_invert_size_get(void);
const float *DRW_viewport_screenvecs_get(void);
const float *DRW_viewport_pixelsize_get(void);
-bool DRW_viewport_is_persp_get(void);
struct DefaultFramebufferList *DRW_viewport_framebuffer_list_get(void);
struct DefaultTextureList *DRW_viewport_texture_list_get(void);
@@ -645,18 +642,6 @@ void DRW_state_reset_ex(DRWState state);
void DRW_state_reset(void);
void DRW_state_lock(DRWState state);
-void DRW_state_clip_planes_len_set(uint plane_len);
-void DRW_state_clip_planes_reset(void);
-void DRW_state_clip_planes_set_from_rv3d(struct RegionView3D *rv3d);
-
-/* Culling, return true if object is inside view frustum. */
-bool DRW_culling_sphere_test(BoundSphere *bsphere);
-bool DRW_culling_box_test(BoundBox *bbox);
-bool DRW_culling_plane_test(float plane[4]);
-
-void DRW_culling_frustum_corners_get(BoundBox *corners);
-void DRW_culling_frustum_planes_get(float planes[6][4]);
-
/* Selection */
void DRW_select_load_id(uint id);
diff --git a/source/blender/draw/intern/draw_common.c b/source/blender/draw/intern/draw_common.c
index e1c86790cdc..bcca660f861 100644
--- a/source/blender/draw/intern/draw_common.c
+++ b/source/blender/draw/intern/draw_common.c
@@ -31,6 +31,8 @@
#include "BKE_global.h"
#include "BKE_colorband.h"
+#include "BIF_glutil.h"
+
#include "draw_common.h"
#if 0
@@ -304,13 +306,6 @@ void DRW_globals_free(void)
}
}
-void DRW_shgroup_world_clip_planes_from_rv3d(DRWShadingGroup *shgrp, const RegionView3D *rv3d)
-{
- int world_clip_planes_len = (rv3d->viewlock & RV3D_BOXCLIP) ? 4 : 6;
- DRW_shgroup_uniform_vec4(shgrp, "WorldClipPlanes", rv3d->clip[0], world_clip_planes_len);
- DRW_shgroup_state_enable(shgrp, DRW_STATE_CLIP_PLANES);
-}
-
struct DRWCallBuffer *buffer_dynlines_flat_color(DRWPass *pass, eGPUShaderConfig sh_cfg)
{
GPUShader *sh = GPU_shader_get_builtin_shader_with_config(GPU_SHADER_3D_FLAT_COLOR, sh_cfg);
@@ -323,7 +318,7 @@ struct DRWCallBuffer *buffer_dynlines_flat_color(DRWPass *pass, eGPUShaderConfig
DRWShadingGroup *grp = DRW_shgroup_create(sh, pass);
if (sh_cfg == GPU_SHADER_CFG_CLIPPED) {
- DRW_shgroup_world_clip_planes_from_rv3d(grp, DRW_context_state_get()->rv3d);
+ DRW_shgroup_state_enable(grp, DRW_STATE_CLIP_PLANES);
}
return DRW_shgroup_call_buffer(grp, g_formats.pos_color, GPU_PRIM_LINES);
}
@@ -347,7 +342,7 @@ struct DRWCallBuffer *buffer_dynlines_dashed_uniform_color(DRWPass *pass,
DRW_shgroup_uniform_float(grp, "dash_factor", &dash_factor, 1);
DRW_shgroup_uniform_int_copy(grp, "colors_len", 0); /* "simple" mode */
if (sh_cfg == GPU_SHADER_CFG_CLIPPED) {
- DRW_shgroup_world_clip_planes_from_rv3d(grp, DRW_context_state_get()->rv3d);
+ DRW_shgroup_state_enable(grp, DRW_STATE_CLIP_PLANES);
}
return DRW_shgroup_call_buffer(grp, g_formats.pos, GPU_PRIM_LINES);
}
@@ -370,7 +365,7 @@ struct DRWCallBuffer *buffer_groundlines_uniform_color(DRWPass *pass,
DRWShadingGroup *grp = DRW_shgroup_create(sh, pass);
DRW_shgroup_uniform_vec4(grp, "color", color, 1);
if (sh_cfg == GPU_SHADER_CFG_CLIPPED) {
- DRW_shgroup_world_clip_planes_from_rv3d(grp, DRW_context_state_get()->rv3d);
+ DRW_shgroup_state_enable(grp, DRW_STATE_CLIP_PLANES);
}
return DRW_shgroup_call_buffer(grp, g_formats.pos, GPU_PRIM_POINTS);
}
@@ -386,7 +381,7 @@ struct DRWCallBuffer *buffer_groundpoints_uniform_color(DRWPass *pass,
DRWShadingGroup *grp = DRW_shgroup_create(sh, pass);
DRW_shgroup_uniform_vec4(grp, "color", color, 1);
if (sh_cfg == GPU_SHADER_CFG_CLIPPED) {
- DRW_shgroup_world_clip_planes_from_rv3d(grp, DRW_context_state_get()->rv3d);
+ DRW_shgroup_state_enable(grp, DRW_STATE_CLIP_PLANES);
}
return DRW_shgroup_call_buffer(grp, g_formats.pos, GPU_PRIM_POINTS);
}
@@ -410,7 +405,7 @@ struct DRWCallBuffer *buffer_instance_screenspace(DRWPass *pass,
DRW_shgroup_uniform_float(grp, "pixel_size", DRW_viewport_pixelsize_get(), 1);
DRW_shgroup_uniform_vec3(grp, "screen_vecs[0]", DRW_viewport_screenvecs_get(), 2);
if (sh_cfg == GPU_SHADER_CFG_CLIPPED) {
- DRW_shgroup_world_clip_planes_from_rv3d(grp, DRW_context_state_get()->rv3d);
+ DRW_shgroup_state_enable(grp, DRW_STATE_CLIP_PLANES);
}
return DRW_shgroup_call_buffer_instance(grp, g_formats.instance_screenspace, geom);
}
@@ -465,7 +460,7 @@ struct DRWCallBuffer *buffer_instance_screen_aligned(DRWPass *pass,
DRWShadingGroup *grp = DRW_shgroup_create(sh, pass);
DRW_shgroup_uniform_vec3(grp, "screen_vecs[0]", DRW_viewport_screenvecs_get(), 2);
if (sh_cfg == GPU_SHADER_CFG_CLIPPED) {
- DRW_shgroup_world_clip_planes_from_rv3d(grp, DRW_context_state_get()->rv3d);
+ DRW_shgroup_state_enable(grp, DRW_STATE_CLIP_PLANES);
}
return DRW_shgroup_call_buffer_instance(grp, g_formats.instance_screen_aligned, geom);
}
@@ -486,7 +481,7 @@ struct DRWCallBuffer *buffer_instance_scaled(DRWPass *pass,
DRWShadingGroup *grp = DRW_shgroup_create(sh_inst, pass);
if (sh_cfg == GPU_SHADER_CFG_CLIPPED) {
- DRW_shgroup_world_clip_planes_from_rv3d(grp, DRW_context_state_get()->rv3d);
+ DRW_shgroup_state_enable(grp, DRW_STATE_CLIP_PLANES);
}
return DRW_shgroup_call_buffer_instance(grp, g_formats.instance_scaled, geom);
}
@@ -508,7 +503,7 @@ struct DRWCallBuffer *buffer_instance(DRWPass *pass,
DRWShadingGroup *grp = DRW_shgroup_create(sh_inst, pass);
DRW_shgroup_state_disable(grp, DRW_STATE_BLEND);
if (sh_cfg == GPU_SHADER_CFG_CLIPPED) {
- DRW_shgroup_world_clip_planes_from_rv3d(grp, DRW_context_state_get()->rv3d);
+ DRW_shgroup_state_enable(grp, DRW_STATE_CLIP_PLANES);
}
return DRW_shgroup_call_buffer_instance(grp, g_formats.instance_sized, geom);
}
@@ -549,7 +544,7 @@ struct DRWCallBuffer *buffer_instance_empty_axes(DRWPass *pass,
DRWShadingGroup *grp = DRW_shgroup_create(sh_data->empty_axes_sh, pass);
DRW_shgroup_uniform_vec3(grp, "screenVecs[0]", DRW_viewport_screenvecs_get(), 2);
if (sh_cfg == GPU_SHADER_CFG_CLIPPED) {
- DRW_shgroup_world_clip_planes_from_rv3d(grp, DRW_context_state_get()->rv3d);
+ DRW_shgroup_state_enable(grp, DRW_STATE_CLIP_PLANES);
}
return DRW_shgroup_call_buffer_instance(grp, g_formats.instance_sized, geom);
}
@@ -589,7 +584,7 @@ struct DRWCallBuffer *buffer_camera_instance(DRWPass *pass,
DRWShadingGroup *grp = DRW_shgroup_create(sh_inst, pass);
if (sh_cfg == GPU_SHADER_CFG_CLIPPED) {
- DRW_shgroup_world_clip_planes_from_rv3d(grp, DRW_context_state_get()->rv3d);
+ DRW_shgroup_state_enable(grp, DRW_STATE_CLIP_PLANES);
}
return DRW_shgroup_call_buffer_instance(grp, g_formats.instance_camera, geom);
}
@@ -613,7 +608,7 @@ struct DRWCallBuffer *buffer_distance_lines_instance(DRWPass *pass,
DRWShadingGroup *grp = DRW_shgroup_create(sh_inst, pass);
DRW_shgroup_uniform_float(grp, "size", &point_size, 1);
if (sh_cfg == GPU_SHADER_CFG_CLIPPED) {
- DRW_shgroup_world_clip_planes_from_rv3d(grp, DRW_context_state_get()->rv3d);
+ DRW_shgroup_state_enable(grp, DRW_STATE_CLIP_PLANES);
}
return DRW_shgroup_call_buffer_instance(grp, g_formats.instance_distance_lines, geom);
}
@@ -638,7 +633,7 @@ struct DRWCallBuffer *buffer_spot_instance(DRWPass *pass,
DRW_shgroup_uniform_bool(grp, "drawBack", &False, 1);
DRW_shgroup_uniform_bool(grp, "drawSilhouette", &True, 1);
if (sh_cfg == GPU_SHADER_CFG_CLIPPED) {
- DRW_shgroup_world_clip_planes_from_rv3d(grp, DRW_context_state_get()->rv3d);
+ DRW_shgroup_state_enable(grp, DRW_STATE_CLIP_PLANES);
}
return DRW_shgroup_call_buffer_instance(grp, g_formats.instance_spot, geom);
}
@@ -664,7 +659,7 @@ struct DRWCallBuffer *buffer_instance_bone_axes(DRWPass *pass, eGPUShaderConfig
DRWShadingGroup *grp = DRW_shgroup_create(sh_data->bone_axes, pass);
DRW_shgroup_uniform_vec3(grp, "screenVecs[0]", DRW_viewport_screenvecs_get(), 2);
if (sh_cfg == GPU_SHADER_CFG_CLIPPED) {
- DRW_shgroup_world_clip_planes_from_rv3d(grp, DRW_context_state_get()->rv3d);
+ DRW_shgroup_state_enable(grp, DRW_STATE_CLIP_PLANES);
}
return DRW_shgroup_call_buffer_instance(
grp, g_formats.instance_color, DRW_cache_bone_arrows_get());
@@ -694,7 +689,7 @@ struct DRWCallBuffer *buffer_instance_bone_envelope_outline(DRWPass *pass, eGPUS
DRWShadingGroup *grp = DRW_shgroup_create(sh_data->bone_envelope_outline, pass);
DRW_shgroup_uniform_vec2(grp, "viewportSize", DRW_viewport_size_get(), 1);
if (sh_cfg == GPU_SHADER_CFG_CLIPPED) {
- DRW_shgroup_world_clip_planes_from_rv3d(grp, DRW_context_state_get()->rv3d);
+ DRW_shgroup_state_enable(grp, DRW_STATE_CLIP_PLANES);
}
return DRW_shgroup_call_buffer_instance(
grp, g_formats.instance_bone_envelope_outline, DRW_cache_bone_envelope_outline_get());
@@ -723,7 +718,7 @@ struct DRWCallBuffer *buffer_instance_bone_envelope_distance(DRWPass *pass,
DRWShadingGroup *grp = DRW_shgroup_create(sh_data->bone_envelope_distance, pass);
if (sh_cfg == GPU_SHADER_CFG_CLIPPED) {
- DRW_shgroup_world_clip_planes_from_rv3d(grp, DRW_context_state_get()->rv3d);
+ DRW_shgroup_state_enable(grp, DRW_STATE_CLIP_PLANES);
}
return DRW_shgroup_call_buffer_instance(
grp, g_formats.instance_bone_envelope_distance, DRW_cache_bone_envelope_solid_get());
@@ -759,7 +754,7 @@ struct DRWCallBuffer *buffer_instance_bone_envelope_solid(DRWPass *pass,
DRW_shgroup_state_enable(grp, DRW_STATE_CULL_BACK);
DRW_shgroup_uniform_float_copy(grp, "alpha", transp ? 0.6f : 1.0f);
if (sh_cfg == GPU_SHADER_CFG_CLIPPED) {
- DRW_shgroup_world_clip_planes_from_rv3d(grp, DRW_context_state_get()->rv3d);
+ DRW_shgroup_state_enable(grp, DRW_STATE_CLIP_PLANES);
}
return DRW_shgroup_call_buffer_instance(
grp, g_formats.instance_bone_envelope, DRW_cache_bone_envelope_solid_get());
@@ -787,7 +782,7 @@ struct DRWCallBuffer *buffer_instance_mball_handles(DRWPass *pass, eGPUShaderCon
DRWShadingGroup *grp = DRW_shgroup_create(sh_data->mball_handles, pass);
DRW_shgroup_uniform_vec3(grp, "screen_vecs[0]", DRW_viewport_screenvecs_get(), 2);
if (sh_cfg == GPU_SHADER_CFG_CLIPPED) {
- DRW_shgroup_world_clip_planes_from_rv3d(grp, DRW_context_state_get()->rv3d);
+ DRW_shgroup_state_enable(grp, DRW_STATE_CLIP_PLANES);
}
return DRW_shgroup_call_buffer_instance(
grp, g_formats.instance_mball_handles, DRW_cache_screenspace_circle_get());
@@ -824,7 +819,7 @@ struct DRWCallBuffer *buffer_instance_bone_shape_outline(DRWPass *pass,
DRWShadingGroup *grp = DRW_shgroup_create(sh_data->shape_outline, pass);
DRW_shgroup_uniform_vec2(grp, "viewportSize", DRW_viewport_size_get(), 1);
if (sh_cfg == GPU_SHADER_CFG_CLIPPED) {
- DRW_shgroup_world_clip_planes_from_rv3d(grp, DRW_context_state_get()->rv3d);
+ DRW_shgroup_state_enable(grp, DRW_STATE_CLIP_PLANES);
}
return DRW_shgroup_call_buffer_instance(grp, g_formats.instance_bone_outline, geom);
}
@@ -857,7 +852,7 @@ struct DRWCallBuffer *buffer_instance_bone_shape_solid(DRWPass *pass,
DRWShadingGroup *grp = DRW_shgroup_create(sh_data->shape_solid, pass);
DRW_shgroup_uniform_float_copy(grp, "alpha", transp ? 0.6f : 1.0f);
if (sh_cfg == GPU_SHADER_CFG_CLIPPED) {
- DRW_shgroup_world_clip_planes_from_rv3d(grp, DRW_context_state_get()->rv3d);
+ DRW_shgroup_state_enable(grp, DRW_STATE_CLIP_PLANES);
}
return DRW_shgroup_call_buffer_instance(grp, g_formats.instance_bone, geom);
}
@@ -887,7 +882,7 @@ struct DRWCallBuffer *buffer_instance_bone_sphere_solid(DRWPass *pass,
/* More transparent than the shape to be less distractive. */
DRW_shgroup_uniform_float_copy(grp, "alpha", transp ? 0.4f : 1.0f);
if (sh_cfg == GPU_SHADER_CFG_CLIPPED) {
- DRW_shgroup_world_clip_planes_from_rv3d(grp, DRW_context_state_get()->rv3d);
+ DRW_shgroup_state_enable(grp, DRW_STATE_CLIP_PLANES);
}
return DRW_shgroup_call_buffer_instance(
grp, g_formats.instance_bone, DRW_cache_bone_point_get());
@@ -915,7 +910,7 @@ struct DRWCallBuffer *buffer_instance_bone_sphere_outline(DRWPass *pass, eGPUSha
DRWShadingGroup *grp = DRW_shgroup_create(sh_data->bone_sphere_outline, pass);
DRW_shgroup_uniform_vec2(grp, "viewportSize", DRW_viewport_size_get(), 1);
if (sh_cfg == GPU_SHADER_CFG_CLIPPED) {
- DRW_shgroup_world_clip_planes_from_rv3d(grp, DRW_context_state_get()->rv3d);
+ DRW_shgroup_state_enable(grp, DRW_STATE_CLIP_PLANES);
}
return DRW_shgroup_call_buffer_instance(
grp, g_formats.instance_bone_outline, DRW_cache_bone_point_wire_outline_get());
@@ -948,7 +943,7 @@ struct DRWCallBuffer *buffer_instance_bone_stick(DRWPass *pass, eGPUShaderConfig
DRW_shgroup_uniform_vec2(grp, "viewportSize", DRW_viewport_size_get(), 1);
DRW_shgroup_uniform_float_copy(grp, "stickSize", 5.0f * U.pixelsize);
if (sh_cfg == GPU_SHADER_CFG_CLIPPED) {
- DRW_shgroup_world_clip_planes_from_rv3d(grp, DRW_context_state_get()->rv3d);
+ DRW_shgroup_state_enable(grp, DRW_STATE_CLIP_PLANES);
}
return DRW_shgroup_call_buffer_instance(
grp, g_formats.instance_bone_stick, DRW_cache_bone_stick_get());
@@ -1035,6 +1030,26 @@ struct GPUShader *volume_velocity_shader_get(bool use_needle)
}
}
+DRWView *DRW_view_create_with_zoffset(const RegionView3D *rv3d, float offset)
+{
+ /* Create view with depth offset */
+ const DRWView *default_view = DRW_view_default_get();
+ float viewmat[4][4], winmat[4][4];
+ DRW_view_viewmat_get(default_view, viewmat, false);
+ DRW_view_winmat_get(default_view, winmat, false);
+
+ float viewdist = rv3d->dist;
+
+ /* special exception for ortho camera (viewdist isnt used for perspective cameras) */
+ if (rv3d->persp == RV3D_CAMOB && rv3d->is_persp == false) {
+ viewdist = 1.0f / max_ff(fabsf(winmat[0][0]), fabsf(winmat[1][1]));
+ }
+
+ winmat[3][2] -= bglPolygonOffsetCalc((float *)winmat, viewdist, offset);
+
+ return DRW_view_create_sub(default_view, viewmat, winmat);
+}
+
/* ******************************************** COLOR UTILS ************************************ */
/* TODO FINISH */
@@ -1212,7 +1227,7 @@ bool DRW_object_is_flat(Object *ob, int *axis)
bool DRW_object_axis_orthogonal_to_view(Object *ob, int axis)
{
float ob_rot[3][3], invviewmat[4][4];
- DRW_viewport_matrix_get(invviewmat, DRW_MAT_VIEWINV);
+ DRW_view_viewmat_get(NULL, invviewmat, true);
BKE_object_rot_to_mat3(ob, ob_rot, true);
float dot = dot_v3v3(ob_rot[axis], invviewmat[2]);
if (fabsf(dot) < 1e-3) {
diff --git a/source/blender/draw/intern/draw_common.h b/source/blender/draw/intern/draw_common.h
index df7220c0d2a..d0717888525 100644
--- a/source/blender/draw/intern/draw_common.h
+++ b/source/blender/draw/intern/draw_common.h
@@ -123,9 +123,6 @@ BLI_STATIC_ASSERT_ALIGN(GlobalsUboStorage, 16)
void DRW_globals_update(void);
void DRW_globals_free(void);
-void DRW_shgroup_world_clip_planes_from_rv3d(struct DRWShadingGroup *shgrp,
- const RegionView3D *rv3d);
-
/* TODO(fclem) ideally, most of the DRWCallBuffer functions shouldn't create a shgroup. */
struct DRWCallBuffer *buffer_dynlines_flat_color(struct DRWPass *pass, eGPUShaderConfig sh_cfg);
struct DRWCallBuffer *buffer_dynlines_dashed_uniform_color(struct DRWPass *pass,
@@ -200,6 +197,8 @@ struct GPUShader *mpath_points_shader_get(void);
struct GPUShader *volume_velocity_shader_get(bool use_needle);
+struct DRWView *DRW_view_create_with_zoffset(const RegionView3D *rv3d, float offset);
+
int DRW_object_wire_theme_get(struct Object *ob, struct ViewLayer *view_layer, float **r_color);
float *DRW_color_background_blend_get(int theme_id);
diff --git a/source/blender/draw/intern/draw_instance_data.c b/source/blender/draw/intern/draw_instance_data.c
index b88ad936c28..e7a41ee3e43 100644
--- a/source/blender/draw/intern/draw_instance_data.c
+++ b/source/blender/draw/intern/draw_instance_data.c
@@ -284,9 +284,9 @@ DRWInstanceDataList *DRW_instance_data_list_create(void)
{
DRWInstanceDataList *idatalist = MEM_callocN(sizeof(DRWInstanceDataList), "DRWInstanceDataList");
- idatalist->pool_batching = BLI_memblock_create(sizeof(GPUBatch), true);
- idatalist->pool_instancing = BLI_memblock_create(sizeof(GPUBatch), true);
- idatalist->pool_buffers = BLI_memblock_create(sizeof(DRWTempBufferHandle), true);
+ idatalist->pool_batching = BLI_memblock_create(sizeof(GPUBatch));
+ idatalist->pool_instancing = BLI_memblock_create(sizeof(GPUBatch));
+ idatalist->pool_buffers = BLI_memblock_create(sizeof(DRWTempBufferHandle));
BLI_addtail(&g_idatalists, idatalist);
diff --git a/source/blender/draw/intern/draw_manager.c b/source/blender/draw/intern/draw_manager.c
index 677e117c602..c0a695adbc2 100644
--- a/source/blender/draw/intern/draw_manager.c
+++ b/source/blender/draw/intern/draw_manager.c
@@ -366,7 +366,8 @@ void DRW_transform_none(GPUTexture *tex)
GPU_batch_uniform_mat4(geom, "ModelViewProjectionMatrix", mat);
GPU_batch_program_use_begin(geom);
- GPU_batch_draw_range_ex(geom, 0, 0, false);
+ GPU_batch_bind(geom);
+ GPU_batch_draw_advanced(geom, 0, 0, 0, 0);
GPU_batch_program_use_end(geom);
GPU_texture_unbind(tex);
@@ -457,7 +458,8 @@ void DRW_multisamples_resolve(GPUTexture *src_depth, GPUTexture *src_color, bool
/* avoid gpuMatrix calls */
GPU_batch_program_use_begin(geom);
- GPU_batch_draw_range_ex(geom, 0, 0, false);
+ GPU_batch_bind(geom);
+ GPU_batch_draw_advanced(geom, 0, 0, 0, 0);
GPU_batch_program_use_end(geom);
}
@@ -539,9 +541,11 @@ static void drw_viewport_cache_resize(void)
BLI_memblock_clear(DST.vmempool->calls, NULL);
BLI_memblock_clear(DST.vmempool->states, NULL);
+ BLI_memblock_clear(DST.vmempool->cullstates, NULL);
BLI_memblock_clear(DST.vmempool->shgroups, NULL);
BLI_memblock_clear(DST.vmempool->uniforms, NULL);
BLI_memblock_clear(DST.vmempool->passes, NULL);
+ BLI_memblock_clear(DST.vmempool->views, NULL);
BLI_memblock_clear(DST.vmempool->images, NULL);
}
@@ -607,22 +611,28 @@ static void drw_viewport_var_init(void)
DST.vmempool = GPU_viewport_mempool_get(DST.viewport);
if (DST.vmempool->calls == NULL) {
- DST.vmempool->calls = BLI_memblock_create(sizeof(DRWCall), false);
+ DST.vmempool->calls = BLI_memblock_create(sizeof(DRWCall));
}
if (DST.vmempool->states == NULL) {
- DST.vmempool->states = BLI_memblock_create(sizeof(DRWCallState), false);
+ DST.vmempool->states = BLI_memblock_create(sizeof(DRWCallState));
+ }
+ if (DST.vmempool->cullstates == NULL) {
+ DST.vmempool->cullstates = BLI_memblock_create(sizeof(DRWCullingState));
}
if (DST.vmempool->shgroups == NULL) {
- DST.vmempool->shgroups = BLI_memblock_create(sizeof(DRWShadingGroup), false);
+ DST.vmempool->shgroups = BLI_memblock_create(sizeof(DRWShadingGroup));
}
if (DST.vmempool->uniforms == NULL) {
- DST.vmempool->uniforms = BLI_memblock_create(sizeof(DRWUniform), false);
+ DST.vmempool->uniforms = BLI_memblock_create(sizeof(DRWUniform));
+ }
+ if (DST.vmempool->views == NULL) {
+ DST.vmempool->views = BLI_memblock_create(sizeof(DRWView));
}
if (DST.vmempool->passes == NULL) {
- DST.vmempool->passes = BLI_memblock_create(sizeof(DRWPass), false);
+ DST.vmempool->passes = BLI_memblock_create(sizeof(DRWPass));
}
if (DST.vmempool->images == NULL) {
- DST.vmempool->images = BLI_memblock_create(sizeof(GPUTexture *), false);
+ DST.vmempool->images = BLI_memblock_create(sizeof(GPUTexture *));
}
DST.idatalist = GPU_viewport_instance_data_list_get(DST.viewport);
@@ -639,36 +649,35 @@ static void drw_viewport_var_init(void)
DST.vmempool = NULL;
}
+ DST.primary_view_ct = 0;
+
if (rv3d != NULL) {
- /* Refresh DST.screenvecs */
- copy_v3_v3(DST.screenvecs[0], rv3d->viewinv[0]);
- copy_v3_v3(DST.screenvecs[1], rv3d->viewinv[1]);
- normalize_v3(DST.screenvecs[0]);
- normalize_v3(DST.screenvecs[1]);
+ normalize_v3_v3(DST.screenvecs[0], rv3d->viewinv[0]);
+ normalize_v3_v3(DST.screenvecs[1], rv3d->viewinv[1]);
- /* Refresh DST.pixelsize */
DST.pixsize = rv3d->pixsize;
+ DST.view_default = DRW_view_create(rv3d->viewmat, rv3d->winmat, NULL, NULL, NULL);
+ DRW_view_camtexco_set(DST.view_default, rv3d->viewcamtexcofac);
- copy_m4_m4(DST.original_mat.mat[DRW_MAT_PERS], rv3d->persmat);
- copy_m4_m4(DST.original_mat.mat[DRW_MAT_PERSINV], rv3d->persinv);
- copy_m4_m4(DST.original_mat.mat[DRW_MAT_VIEW], rv3d->viewmat);
- copy_m4_m4(DST.original_mat.mat[DRW_MAT_VIEWINV], rv3d->viewinv);
- copy_m4_m4(DST.original_mat.mat[DRW_MAT_WIN], rv3d->winmat);
- invert_m4_m4(DST.original_mat.mat[DRW_MAT_WININV], rv3d->winmat);
-
- memcpy(DST.view_data.matstate.mat, DST.original_mat.mat, sizeof(DST.original_mat.mat));
+ if (DST.draw_ctx.sh_cfg == GPU_SHADER_CFG_CLIPPED) {
+ int plane_len = (rv3d->viewlock & RV3D_BOXCLIP) ? 4 : 6;
+ DRW_view_clip_planes_set(DST.view_default, rv3d->clip, plane_len);
+ }
- copy_v4_v4(DST.view_data.viewcamtexcofac, rv3d->viewcamtexcofac);
+ DST.view_active = DST.view_default;
+ DST.view_previous = NULL;
}
else {
- copy_v4_fl4(DST.view_data.viewcamtexcofac, 1.0f, 1.0f, 0.0f, 0.0f);
- }
+ zero_v3(DST.screenvecs[0]);
+ zero_v3(DST.screenvecs[1]);
- /* Reset facing */
- DST.frontface = GL_CCW;
- DST.backface = GL_CW;
- glFrontFace(DST.frontface);
+ DST.pixsize = 1.0f;
+ DST.view_default = NULL;
+ DST.view_active = NULL;
+ DST.view_previous = NULL;
+ }
+ /* fclem: Is this still needed ? */
if (DST.draw_ctx.object_edit) {
ED_view3d_init_mats_rv3d(DST.draw_ctx.object_edit, rv3d);
}
@@ -677,103 +686,12 @@ static void drw_viewport_var_init(void)
memset(&DST.RST, 0x0, sizeof(DST.RST));
if (G_draw.view_ubo == NULL) {
- G_draw.view_ubo = DRW_uniformbuffer_create(sizeof(ViewUboStorage), NULL);
+ G_draw.view_ubo = DRW_uniformbuffer_create(sizeof(DRWViewUboStorage), NULL);
}
- DST.override_mat = 0;
- DST.dirty_mat = true;
- DST.state_cache_id = 1;
-
- DST.clipping.updated = false;
-
memset(DST.object_instance_data, 0x0, sizeof(DST.object_instance_data));
}
-void DRW_viewport_matrix_get(float mat[4][4], DRWViewportMatrixType type)
-{
- BLI_assert(type >= 0 && type < DRW_MAT_COUNT);
- /* Can't use this in render mode. */
- BLI_assert(((DST.override_mat & (1 << type)) != 0) || DST.draw_ctx.rv3d != NULL);
-
- copy_m4_m4(mat, DST.view_data.matstate.mat[type]);
-}
-
-void DRW_viewport_matrix_get_all(DRWMatrixState *state)
-{
- memcpy(state, DST.view_data.matstate.mat, sizeof(DRWMatrixState));
-}
-
-void DRW_viewport_matrix_override_set(const float mat[4][4], DRWViewportMatrixType type)
-{
- BLI_assert(type < DRW_MAT_COUNT);
- copy_m4_m4(DST.view_data.matstate.mat[type], mat);
- DST.override_mat |= (1 << type);
- DST.dirty_mat = true;
- DST.clipping.updated = false;
-}
-
-void DRW_viewport_matrix_override_unset(DRWViewportMatrixType type)
-{
- BLI_assert(type < DRW_MAT_COUNT);
- copy_m4_m4(DST.view_data.matstate.mat[type], DST.original_mat.mat[type]);
- DST.override_mat &= ~(1 << type);
- DST.dirty_mat = true;
- DST.clipping.updated = false;
-}
-
-void DRW_viewport_matrix_override_set_all(DRWMatrixState *state)
-{
- memcpy(DST.view_data.matstate.mat, state, sizeof(DRWMatrixState));
- DST.override_mat = 0xFFFFFF;
- DST.dirty_mat = true;
- DST.clipping.updated = false;
-}
-
-void DRW_viewport_matrix_override_unset_all(void)
-{
- memcpy(DST.view_data.matstate.mat, DST.original_mat.mat, sizeof(DRWMatrixState));
- DST.override_mat = 0;
- DST.dirty_mat = true;
- DST.clipping.updated = false;
-}
-
-bool DRW_viewport_is_persp_get(void)
-{
- RegionView3D *rv3d = DST.draw_ctx.rv3d;
- if (rv3d) {
- return rv3d->is_persp;
- }
- else {
- return DST.view_data.matstate.mat[DRW_MAT_WIN][3][3] == 0.0f;
- }
-}
-
-float DRW_viewport_near_distance_get(void)
-{
- float projmat[4][4];
- DRW_viewport_matrix_get(projmat, DRW_MAT_WIN);
-
- if (DRW_viewport_is_persp_get()) {
- return -projmat[3][2] / (projmat[2][2] - 1.0f);
- }
- else {
- return -(projmat[3][2] + 1.0f) / projmat[2][2];
- }
-}
-
-float DRW_viewport_far_distance_get(void)
-{
- float projmat[4][4];
- DRW_viewport_matrix_get(projmat, DRW_MAT_WIN);
-
- if (DRW_viewport_is_persp_get()) {
- return -projmat[3][2] / (projmat[2][2] + 1.0f);
- }
- else {
- return -(projmat[3][2] - 1.0f) / projmat[2][2];
- }
-}
-
DefaultFramebufferList *DRW_viewport_framebuffer_list_get(void)
{
return GPU_viewport_framebuffer_list_get(DST.viewport);
@@ -1580,7 +1498,8 @@ void DRW_draw_view(const bContext *C)
drw_state_prepare_clean_for_draw(&DST);
DST.options.draw_text = ((v3d->flag2 & V3D_HIDE_OVERLAYS) == 0 &&
(v3d->overlay.flag & V3D_OVERLAY_HIDE_TEXT) != 0);
- DST.options.draw_background = scene->r.alphamode == R_ADDSKY;
+ DST.options.draw_background = (scene->r.alphamode == R_ADDSKY) ||
+ (v3d->shading.type != OB_RENDER);
DRW_draw_render_loop_ex(depsgraph, engine_type, ar, v3d, viewport, C);
}
@@ -2058,6 +1977,11 @@ void DRW_render_to_image(RenderEngine *engine, struct Depsgraph *depsgraph)
/* grease pencil: render result is merged in the previous render result. */
if (DRW_render_check_grease_pencil(depsgraph)) {
DRW_state_reset();
+ /* HACK: this is just for sanity and not trigger asserts. */
+ DST.view_default = NULL;
+ DST.view_active = NULL;
+ DST.view_previous = NULL;
+
DRW_render_gpencil_to_image(engine, render_layer, &render_rect);
}
DST.buffer_finish_called = false;
@@ -2619,7 +2543,7 @@ void DRW_draw_depth_loop_gpencil(struct Depsgraph *depsgraph,
/** See #DRW_shgroup_world_clip_planes_from_rv3d. */
static void draw_world_clip_planes_from_rv3d(GPUBatch *batch, const float world_clip_planes[6][4])
{
- GPU_batch_uniform_4fv_array(batch, "WorldClipPlanes", 6, world_clip_planes[0]);
+ GPU_batch_uniform_4fv_array(batch, "clipPlanes", 6, world_clip_planes[0]);
}
/**
@@ -2685,7 +2609,7 @@ void DRW_draw_depth_object(ARegion *ar, GPUViewport *viewport, Object *object)
DRW_opengl_context_disable();
}
-static void draw_mesh_verts(GPUBatch *batch, int offset, const float world_clip_planes[6][4])
+static void draw_mesh_verts(GPUBatch *batch, uint offset, const float world_clip_planes[6][4])
{
GPU_point_size(UI_GetThemeValuef(TH_VERTEX_SIZE));
@@ -2699,7 +2623,7 @@ static void draw_mesh_verts(GPUBatch *batch, int offset, const float world_clip_
GPU_batch_draw(batch);
}
-static void draw_mesh_edges(GPUBatch *batch, int offset, const float world_clip_planes[6][4])
+static void draw_mesh_edges(GPUBatch *batch, uint offset, const float world_clip_planes[6][4])
{
GPU_line_width(1.0f);
glProvokingVertex(GL_FIRST_VERTEX_CONVENTION);
@@ -2718,7 +2642,7 @@ static void draw_mesh_edges(GPUBatch *batch, int offset, const float world_clip_
/* two options, facecolors or black */
static void draw_mesh_face(GPUBatch *batch,
- int offset,
+ uint offset,
const bool use_select,
const float world_clip_planes[6][4])
{
@@ -2744,7 +2668,7 @@ static void draw_mesh_face(GPUBatch *batch,
}
}
-static void draw_mesh_face_dot(GPUBatch *batch, int offset, const float world_clip_planes[6][4])
+static void draw_mesh_face_dot(GPUBatch *batch, uint offset, const float world_clip_planes[6][4])
{
const eGPUShaderConfig sh_cfg = world_clip_planes ? GPU_SHADER_CFG_CLIPPED :
GPU_SHADER_CFG_DEFAULT;
@@ -2772,7 +2696,6 @@ void DRW_draw_select_id_object(Scene *scene,
}
GPU_matrix_mul(ob->obmat);
- GPU_depth_test(true);
const float(*world_clip_planes)[4] = NULL;
if (rv3d->rflag & RV3D_CLIPPING) {
@@ -2780,7 +2703,7 @@ void DRW_draw_select_id_object(Scene *scene,
world_clip_planes = rv3d->clip_local;
}
- initial_offset += 1;
+ BLI_assert(initial_offset > 0);
switch (ob->type) {
case OB_MESH:
@@ -2862,6 +2785,7 @@ void DRW_draw_select_id_object(Scene *scene,
draw_mesh_face(geom_faces, 0, false, world_clip_planes);
draw_mesh_verts(geom_verts, 1, world_clip_planes);
+ *r_face_offset = *r_edge_offset = initial_offset;
*r_vert_offset = me_eval->totvert + 1;
}
else {
@@ -2870,7 +2794,8 @@ void DRW_draw_select_id_object(Scene *scene,
draw_mesh_face(geom_faces, initial_offset, true, world_clip_planes);
- *r_face_offset = initial_offset + me_eval->totface;
+ *r_face_offset = initial_offset + me_eval->totpoly;
+ *r_edge_offset = *r_vert_offset = *r_face_offset;
}
}
break;
@@ -2898,7 +2823,7 @@ void DRW_framebuffer_select_id_setup(ARegion *ar, const bool clear)
glDisable(GL_DITHER);
GPU_depth_test(true);
- glDisable(GL_SCISSOR_TEST);
+ GPU_disable_program_point_size();
if (clear) {
GPU_framebuffer_clear_color_depth(
diff --git a/source/blender/draw/intern/draw_manager.h b/source/blender/draw/intern/draw_manager.h
index b5dc88205db..6cf70f555eb 100644
--- a/source/blender/draw/intern/draw_manager.h
+++ b/source/blender/draw/intern/draw_manager.h
@@ -43,9 +43,9 @@
/* Use draw manager to call GPU_select, see: DRW_draw_select_loop */
#define USE_GPU_SELECT
+// #define DRW_DEBUG_CULLING
#define DRW_DEBUG_USE_UNIFORM_NAME 0
#define DRW_UNIFORM_BUFFER_NAME 64
-#define DRW_UNIFORM_BUFFER_NAME_INC 1024
/* ------------ Profiling --------------- */
@@ -92,9 +92,7 @@
/* Used by DRWCallState.flag */
enum {
- DRW_CALL_CULLED = (1 << 0),
DRW_CALL_NEGSCALE = (1 << 1),
- DRW_CALL_BYPASS_CULLING = (1 << 2),
};
/* Used by DRWCallState.matflag */
@@ -105,22 +103,24 @@ enum {
DRW_CALL_OBJECTINFO = (1 << 3),
};
-typedef struct DRWCallState {
- DRWCallVisibilityFn *visibility_cb;
+typedef struct DRWCullingState {
+ uint32_t mask;
+ /* Culling: Using Bounding Sphere for now for faster culling.
+ * Not ideal for planes. Could be extended. */
+ BoundSphere bsphere;
+ /* Grrr only used by EEVEE. */
void *user_data;
+} DRWCullingState;
+typedef struct DRWCallState {
+ DRWCullingState *culling;
uchar flag;
- uchar cache_id; /* Compared with DST.state_cache_id to see if matrices are still valid. */
- uchar matflag; /* Which matrices to compute. */
+ uchar matflag; /* Which matrices to compute. */
short ob_index;
- /* Culling: Using Bounding Sphere for now for faster culling.
- * Not ideal for planes. */
- BoundSphere bsphere;
/* Matrices */
float model[4][4];
float modelinverse[4][4];
- float modelviewprojection[4][4];
- float orcotexfac[2][3]; /* Not view dependent */
+ float orcotexfac[2][3];
float ob_random;
} DRWCallState;
@@ -214,24 +214,50 @@ struct DRWPass {
char name[MAX_PASS_NAME];
};
+/* keep in sync with viewBlock */
+typedef struct DRWViewUboStorage {
+ /* View matrices */
+ float persmat[4][4];
+ float persinv[4][4];
+ float viewmat[4][4];
+ float viewinv[4][4];
+ float winmat[4][4];
+ float wininv[4][4];
+
+ float clipplanes[6][4];
+ /* Should not be here. Not view dependant (only main view). */
+ float viewcamtexcofac[4];
+} DRWViewUboStorage;
+
+#define MAX_CULLED_VIEWS 32
+
+struct DRWView {
+ /** Parent view if this is a sub view. NULL otherwise. */
+ struct DRWView *parent;
+
+ DRWViewUboStorage storage;
+ /** Number of active clipplanes. */
+ int clip_planes_len;
+ /** Does culling result needs to be updated. */
+ bool is_dirty;
+ /** Culling */
+ uint32_t culling_mask;
+ BoundBox frustum_corners;
+ BoundSphere frustum_bsphere;
+ float frustum_planes[6][4];
+ /** Custom visibility function. */
+ DRWCallVisibilityFn *visibility_fn;
+ void *user_data;
+};
+
/* TODO(fclem): Future awaits */
#if 0
-typedef struct DRWView {
- /* Culling function, culling result etc...*/
-} DRWView;
-
typedef struct ModelUboStorage {
float model[4][4];
float modelinverse[4][4];
} ModelUboStorage;
#endif
-typedef struct ViewUboStorage {
- DRWMatrixState matstate;
- float viewcamtexcofac[4];
- float clipplanes[2][4];
-} ViewUboStorage;
-
/* ------------- DRAW DEBUG ------------ */
typedef struct DRWDebugLine {
@@ -259,7 +285,6 @@ typedef struct DRWManager {
DRWInstanceData *object_instance_data[MAX_INSTANCE_DATA_SIZE];
/* State of the object being evaluated if already allocated. */
DRWCallState *ob_state;
- uchar state_cache_id; /* Could be larger but 254 view changes is already a lot! */
struct DupliObject *dupli_source;
struct Object *dupli_parent;
struct Object *dupli_origin;
@@ -268,6 +293,7 @@ typedef struct DRWManager {
/* Rendering state */
GPUShader *shader;
+ GPUBatch *batch;
/* Managed by `DRW_state_set`, `DRW_state_reset` */
DRWState state;
@@ -282,8 +308,6 @@ typedef struct DRWManager {
float screenvecs[2][3];
float pixsize;
- GLenum backface, frontface;
-
struct {
uint is_select : 1;
uint is_depth : 1;
@@ -305,21 +329,13 @@ typedef struct DRWManager {
bool buffer_finish_called; /* Avoid bad usage of DRW_render_instance_buffer_finish */
- /* View dependent uniforms. */
- DRWMatrixState original_mat; /* Original rv3d matrices. */
- int override_mat; /* Bitflag of which matrices are overridden. */
- int clip_planes_len; /* Number of active clipplanes. */
- bool dirty_mat;
-
- /* keep in sync with viewBlock */
- ViewUboStorage view_data;
-
- struct {
- float frustum_planes[6][4];
- BoundBox frustum_corners;
- BoundSphere frustum_bsphere;
- bool updated;
- } clipping;
+ DRWView *view_default;
+ DRWView *view_active;
+ DRWView *view_previous;
+ uint primary_view_ct;
+ /** TODO(fclem) Remove this. Only here to support
+ * shaders without common_view_lib.glsl */
+ DRWViewUboStorage view_storage_cpy;
#ifdef USE_GPU_SELECT
uint select_id;
diff --git a/source/blender/draw/intern/draw_manager_data.c b/source/blender/draw/intern/draw_manager_data.c
index f8ef1bcf065..c3b905323cc 100644
--- a/source/blender/draw/intern/draw_manager_data.c
+++ b/source/blender/draw/intern/draw_manager_data.c
@@ -39,6 +39,10 @@
#include "BLI_mempool.h"
#include "BLI_memblock.h"
+#ifdef DRW_DEBUG_CULLING
+# include "BLI_math_bits.h"
+#endif
+
#include "GPU_buffers.h"
#include "intern/gpu_codegen.h"
@@ -142,7 +146,7 @@ static void drw_shgroup_uniform(DRWShadingGroup *shgroup,
size_t len = strlen(name) + 1;
if (len >= max_len) {
- DST.uniform_names.buffer_len += DRW_UNIFORM_BUFFER_NAME_INC;
+ 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);
}
@@ -389,8 +393,6 @@ static DRWCallState *drw_call_state_create(DRWShadingGroup *shgroup, float (*obm
{
DRWCallState *state = BLI_memblock_alloc(DST.vmempool->states);
state->flag = 0;
- state->cache_id = 0;
- state->visibility_cb = NULL;
state->matflag = 0;
/* Matrices */
@@ -407,18 +409,23 @@ static DRWCallState *drw_call_state_create(DRWShadingGroup *shgroup, float (*obm
drw_call_state_update_matflag(state, shgroup, ob);
+ DRWCullingState *cull = BLI_memblock_alloc(DST.vmempool->cullstates);
+ state->culling = cull;
+
if (ob != NULL) {
float corner[3];
BoundBox *bbox = BKE_object_boundbox_get(ob);
/* Get BoundSphere center and radius from the BoundBox. */
- mid_v3_v3v3(state->bsphere.center, bbox->vec[0], bbox->vec[6]);
+ mid_v3_v3v3(cull->bsphere.center, bbox->vec[0], bbox->vec[6]);
mul_v3_m4v3(corner, obmat, bbox->vec[0]);
- mul_m4_v3(obmat, state->bsphere.center);
- state->bsphere.radius = len_v3v3(state->bsphere.center, corner);
+ mul_m4_v3(obmat, cull->bsphere.center);
+ cull->bsphere.radius = len_v3v3(cull->bsphere.center, corner);
}
else {
+ /* TODO(fclem) Bypass alloc if we can (see if eevee's
+ * probe visibility collection still works). */
/* Bypass test. */
- state->bsphere.radius = -1.0f;
+ cull->bsphere.radius = -1.0f;
}
return state;
@@ -531,8 +538,6 @@ void DRW_shgroup_call_object_ex(DRWShadingGroup *shgroup,
BLI_LINKS_APPEND(&shgroup->calls, call);
call->state = drw_call_state_object(shgroup, ob->obmat, ob);
- /* NOTE this will disable culling for the whole object. */
- call->state->flag |= (bypass_culling) ? DRW_CALL_BYPASS_CULLING : 0;
call->batch = geom;
call->vert_first = 0;
call->vert_count = 0; /* Auto from batch. */
@@ -541,12 +546,15 @@ void DRW_shgroup_call_object_ex(DRWShadingGroup *shgroup,
call->select_id = DST.select_id;
call->inst_selectid = NULL;
#endif
+ if (bypass_culling) {
+ /* NOTE this will disable culling for the whole object. */
+ call->state->culling->bsphere.radius = -1.0f;
+ }
}
void DRW_shgroup_call_object_with_callback(DRWShadingGroup *shgroup,
GPUBatch *geom,
Object *ob,
- DRWCallVisibilityFn *callback,
void *user_data)
{
BLI_assert(geom != NULL);
@@ -555,8 +563,7 @@ void DRW_shgroup_call_object_with_callback(DRWShadingGroup *shgroup,
BLI_LINKS_APPEND(&shgroup->calls, call);
call->state = drw_call_state_object(shgroup, ob->obmat, ob);
- call->state->visibility_cb = callback;
- call->state->user_data = user_data;
+ call->state->culling->user_data = user_data;
call->batch = geom;
call->vert_first = 0;
call->vert_count = 0; /* Auto from batch. */
@@ -859,23 +866,15 @@ static void drw_shgroup_init(DRWShadingGroup *shgroup, GPUShader *shader)
}
else {
/* Only here to support builtin shaders. This should not be used by engines. */
- drw_shgroup_builtin_uniform(
- shgroup, GPU_UNIFORM_VIEW, DST.view_data.matstate.mat[DRW_MAT_VIEW], 16, 1);
- drw_shgroup_builtin_uniform(
- shgroup, GPU_UNIFORM_VIEW_INV, DST.view_data.matstate.mat[DRW_MAT_VIEWINV], 16, 1);
- drw_shgroup_builtin_uniform(
- shgroup, GPU_UNIFORM_VIEWPROJECTION, DST.view_data.matstate.mat[DRW_MAT_PERS], 16, 1);
- drw_shgroup_builtin_uniform(shgroup,
- GPU_UNIFORM_VIEWPROJECTION_INV,
- DST.view_data.matstate.mat[DRW_MAT_PERSINV],
- 16,
- 1);
- drw_shgroup_builtin_uniform(
- shgroup, GPU_UNIFORM_PROJECTION, DST.view_data.matstate.mat[DRW_MAT_WIN], 16, 1);
- drw_shgroup_builtin_uniform(
- shgroup, GPU_UNIFORM_PROJECTION_INV, DST.view_data.matstate.mat[DRW_MAT_WININV], 16, 1);
- drw_shgroup_builtin_uniform(
- shgroup, GPU_UNIFORM_CAMERATEXCO, DST.view_data.viewcamtexcofac, 3, 2);
+ /* 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);
}
/* Not supported. */
@@ -1050,7 +1049,6 @@ bool DRW_shgroup_is_empty(DRWShadingGroup *shgroup)
DRWShadingGroup *DRW_shgroup_create_sub(DRWShadingGroup *shgroup)
{
- /* Remove this assertion if needed but implement the other cases first! */
DRWShadingGroup *shgroup_new = BLI_memblock_alloc(DST.vmempool->shgroups);
*shgroup_new = *shgroup;
@@ -1066,6 +1064,477 @@ DRWShadingGroup *DRW_shgroup_create_sub(DRWShadingGroup *shgroup)
/** \} */
/* -------------------------------------------------------------------- */
+/** \name View (DRW_view)
+ * \{ */
+
+/* Extract the 8 corners from a Projection Matrix.
+ * Although less accurate, this solution can be simplified as follows:
+ * BKE_boundbox_init_from_minmax(&bbox, (const float[3]){-1.0f, -1.0f, -1.0f}, (const
+ * float[3]){1.0f, 1.0f, 1.0f}); for (int i = 0; i < 8; i++) {mul_project_m4_v3(projinv,
+ * bbox.vec[i]);}
+ */
+static void draw_frustum_boundbox_calc(const float (*viewinv)[4],
+ const float (*projmat)[4],
+ BoundBox *r_bbox)
+{
+ float left, right, bottom, top, near, far;
+ bool is_persp = projmat[3][3] == 0.0f;
+
+#if 0 /* Equivalent to this but it has accuracy problems. */
+ BKE_boundbox_init_from_minmax(
+ &bbox, (const float[3]){-1.0f, -1.0f, -1.0f}, (const float[3]){1.0f, 1.0f, 1.0f});
+ for (int i = 0; i < 8; i++) {
+ mul_project_m4_v3(projinv, bbox.vec[i]);
+ }
+#endif
+
+ projmat_dimensions(projmat, &left, &right, &bottom, &top, &near, &far);
+
+ if (is_persp) {
+ left *= near;
+ right *= near;
+ bottom *= near;
+ top *= near;
+ }
+
+ r_bbox->vec[0][2] = r_bbox->vec[3][2] = r_bbox->vec[7][2] = r_bbox->vec[4][2] = -near;
+ r_bbox->vec[0][0] = r_bbox->vec[3][0] = left;
+ r_bbox->vec[4][0] = r_bbox->vec[7][0] = right;
+ r_bbox->vec[0][1] = r_bbox->vec[4][1] = bottom;
+ r_bbox->vec[7][1] = r_bbox->vec[3][1] = top;
+
+ /* Get the coordinates of the far plane. */
+ if (is_persp) {
+ float sca_far = far / near;
+ left *= sca_far;
+ right *= sca_far;
+ bottom *= sca_far;
+ top *= sca_far;
+ }
+
+ r_bbox->vec[1][2] = r_bbox->vec[2][2] = r_bbox->vec[6][2] = r_bbox->vec[5][2] = -far;
+ r_bbox->vec[1][0] = r_bbox->vec[2][0] = left;
+ r_bbox->vec[6][0] = r_bbox->vec[5][0] = right;
+ r_bbox->vec[1][1] = r_bbox->vec[5][1] = bottom;
+ r_bbox->vec[2][1] = r_bbox->vec[6][1] = top;
+
+ /* Transform into world space. */
+ for (int i = 0; i < 8; i++) {
+ mul_m4_v3(viewinv, r_bbox->vec[i]);
+ }
+}
+
+static void draw_frustum_culling_planes_calc(const BoundBox *bbox, float (*frustum_planes)[4])
+{
+ /* TODO See if planes_from_projmat cannot do the job. */
+
+ /* Compute clip planes using the world space frustum corners. */
+ for (int p = 0; p < 6; p++) {
+ int q, r, s;
+ switch (p) {
+ case 0:
+ q = 1;
+ r = 2;
+ s = 3;
+ break; /* -X */
+ case 1:
+ q = 0;
+ r = 4;
+ s = 5;
+ break; /* -Y */
+ case 2:
+ q = 1;
+ r = 5;
+ s = 6;
+ break; /* +Z (far) */
+ case 3:
+ q = 2;
+ r = 6;
+ s = 7;
+ break; /* +Y */
+ case 4:
+ q = 0;
+ r = 3;
+ s = 7;
+ break; /* -Z (near) */
+ default:
+ q = 4;
+ r = 7;
+ s = 6;
+ break; /* +X */
+ }
+
+ normal_quad_v3(frustum_planes[p], bbox->vec[p], bbox->vec[q], bbox->vec[r], bbox->vec[s]);
+ /* Increase precision and use the mean of all 4 corners. */
+ frustum_planes[p][3] = -dot_v3v3(frustum_planes[p], bbox->vec[p]);
+ frustum_planes[p][3] += -dot_v3v3(frustum_planes[p], bbox->vec[q]);
+ frustum_planes[p][3] += -dot_v3v3(frustum_planes[p], bbox->vec[r]);
+ frustum_planes[p][3] += -dot_v3v3(frustum_planes[p], bbox->vec[s]);
+ frustum_planes[p][3] *= 0.25f;
+ }
+}
+
+static void draw_frustum_bound_sphere_calc(const BoundBox *bbox,
+ const float (*viewinv)[4],
+ const float (*projmat)[4],
+ const float (*projinv)[4],
+ BoundSphere *bsphere)
+{
+ /* Extract Bounding Sphere */
+ if (projmat[3][3] != 0.0f) {
+ /* Orthographic */
+ /* The most extreme points on the near and far plane. (normalized device coords). */
+ const float *nearpoint = bbox->vec[0];
+ const float *farpoint = bbox->vec[6];
+
+ /* just use median point */
+ mid_v3_v3v3(bsphere->center, farpoint, nearpoint);
+ bsphere->radius = len_v3v3(bsphere->center, farpoint);
+ }
+ else if (projmat[2][0] == 0.0f && projmat[2][1] == 0.0f) {
+ /* Perspective with symmetrical frustum. */
+
+ /* We obtain the center and radius of the circumscribed circle of the
+ * isosceles trapezoid composed by the diagonals of the near and far clipping plane */
+
+ /* center of each clipping plane */
+ float mid_min[3], mid_max[3];
+ mid_v3_v3v3(mid_min, bbox->vec[3], bbox->vec[4]);
+ mid_v3_v3v3(mid_max, bbox->vec[2], bbox->vec[5]);
+
+ /* square length of the diagonals of each clipping plane */
+ float a_sq = len_squared_v3v3(bbox->vec[3], bbox->vec[4]);
+ float b_sq = len_squared_v3v3(bbox->vec[2], bbox->vec[5]);
+
+ /* distance squared between clipping planes */
+ float h_sq = len_squared_v3v3(mid_min, mid_max);
+
+ float fac = (4 * h_sq + b_sq - a_sq) / (8 * h_sq);
+
+ /* The goal is to get the smallest sphere,
+ * not the sphere that passes through each corner */
+ CLAMP(fac, 0.0f, 1.0f);
+
+ interp_v3_v3v3(bsphere->center, mid_min, mid_max, fac);
+
+ /* distance from the center to one of the points of the far plane (1, 2, 5, 6) */
+ bsphere->radius = len_v3v3(bsphere->center, bbox->vec[1]);
+ }
+ else {
+ /* Perspective with asymmetrical frustum. */
+
+ /* We put the sphere center on the line that goes from origin
+ * to the center of the far clipping plane. */
+
+ /* Detect which of the corner of the far clipping plane is the farthest to the origin */
+ float nfar[4]; /* most extreme far point in NDC space */
+ float farxy[2]; /* farpoint projection onto the near plane */
+ float farpoint[3] = {0.0f}; /* most extreme far point in camera coordinate */
+ float nearpoint[3]; /* most extreme near point in camera coordinate */
+ float farcenter[3] = {0.0f}; /* center of far cliping plane in camera coordinate */
+ float F = -1.0f, N; /* square distance of far and near point to origin */
+ float f, n; /* distance of far and near point to z axis. f is always > 0 but n can be < 0 */
+ float e, s; /* far and near clipping distance (<0) */
+ float c; /* slope of center line = distance of far clipping center
+ * to z axis / far clipping distance. */
+ float z; /* projection of sphere center on z axis (<0) */
+
+ /* Find farthest corner and center of far clip plane. */
+ float corner[3] = {1.0f, 1.0f, 1.0f}; /* in clip space */
+ for (int i = 0; i < 4; i++) {
+ float point[3];
+ mul_v3_project_m4_v3(point, projinv, corner);
+ float len = len_squared_v3(point);
+ if (len > F) {
+ copy_v3_v3(nfar, corner);
+ copy_v3_v3(farpoint, point);
+ F = len;
+ }
+ add_v3_v3(farcenter, point);
+ /* rotate by 90 degree to walk through the 4 points of the far clip plane */
+ float tmp = corner[0];
+ corner[0] = -corner[1];
+ corner[1] = tmp;
+ }
+
+ /* the far center is the average of the far clipping points */
+ mul_v3_fl(farcenter, 0.25f);
+ /* the extreme near point is the opposite point on the near clipping plane */
+ copy_v3_fl3(nfar, -nfar[0], -nfar[1], -1.0f);
+ mul_v3_project_m4_v3(nearpoint, projinv, nfar);
+ /* this is a frustum projection */
+ N = len_squared_v3(nearpoint);
+ e = farpoint[2];
+ s = nearpoint[2];
+ /* distance to view Z axis */
+ f = len_v2(farpoint);
+ /* get corresponding point on the near plane */
+ mul_v2_v2fl(farxy, farpoint, s / e);
+ /* this formula preserve the sign of n */
+ sub_v2_v2(nearpoint, farxy);
+ n = f * s / e - len_v2(nearpoint);
+ c = len_v2(farcenter) / e;
+ /* the big formula, it simplifies to (F-N)/(2(e-s)) for the symmetric case */
+ z = (F - N) / (2.0f * (e - s + c * (f - n)));
+
+ bsphere->center[0] = farcenter[0] * z / e;
+ bsphere->center[1] = farcenter[1] * z / e;
+ bsphere->center[2] = z;
+ bsphere->radius = len_v3v3(bsphere->center, farpoint);
+
+ /* Transform to world space. */
+ mul_m4_v3(viewinv, bsphere->center);
+ }
+}
+
+static void draw_view_matrix_state_update(DRWViewUboStorage *storage,
+ const float viewmat[4][4],
+ const float winmat[4][4])
+{
+ /* If only one the matrices is negative, then the
+ * polygon winding changes and we don't want that. */
+ BLI_assert(is_negative_m4(viewmat) != is_negative_m4(winmat));
+
+ copy_m4_m4(storage->viewmat, viewmat);
+ invert_m4_m4(storage->viewinv, storage->viewmat);
+
+ copy_m4_m4(storage->winmat, winmat);
+ invert_m4_m4(storage->wininv, storage->winmat);
+
+ mul_m4_m4m4(storage->persmat, winmat, viewmat);
+ invert_m4_m4(storage->persinv, storage->persmat);
+}
+
+/* Create a view with culling. */
+DRWView *DRW_view_create(const float viewmat[4][4],
+ const float winmat[4][4],
+ const float (*culling_viewmat)[4],
+ const float (*culling_winmat)[4],
+ DRWCallVisibilityFn *visibility_fn)
+{
+ DRWView *view = BLI_memblock_alloc(DST.vmempool->views);
+
+ if (DST.primary_view_ct < MAX_CULLED_VIEWS) {
+ view->culling_mask = 1u << DST.primary_view_ct++;
+ }
+ else {
+ BLI_assert(0);
+ view->culling_mask = 0u;
+ }
+ view->clip_planes_len = 0;
+ view->visibility_fn = visibility_fn;
+ view->parent = NULL;
+
+ copy_v4_fl4(view->storage.viewcamtexcofac, 1.0f, 1.0f, 0.0f, 0.0f);
+
+ DRW_view_update(view, viewmat, winmat, culling_viewmat, culling_winmat);
+
+ return view;
+}
+
+/* Create a view with culling done by another view. */
+DRWView *DRW_view_create_sub(const DRWView *parent_view,
+ const float viewmat[4][4],
+ const float winmat[4][4])
+{
+ BLI_assert(parent_view && parent_view->parent == NULL);
+
+ DRWView *view = BLI_memblock_alloc(DST.vmempool->views);
+
+ /* Perform copy. */
+ *view = *parent_view;
+ view->parent = (DRWView *)parent_view;
+
+ DRW_view_update_sub(view, viewmat, winmat);
+
+ return view;
+}
+
+/**
+ * DRWView Update:
+ * This is meant to be done on existing views when rendering in a loop and there is no
+ * need to allocate more DRWViews.
+ **/
+
+/* Update matrices of a view created with DRW_view_create_sub. */
+void DRW_view_update_sub(DRWView *view, const float viewmat[4][4], const float winmat[4][4])
+{
+ BLI_assert(view->parent != NULL);
+
+ view->is_dirty = true;
+
+ draw_view_matrix_state_update(&view->storage, viewmat, winmat);
+}
+
+/* Update matrices of a view created with DRW_view_create. */
+void DRW_view_update(DRWView *view,
+ const float viewmat[4][4],
+ const float winmat[4][4],
+ const float (*culling_viewmat)[4],
+ const float (*culling_winmat)[4])
+{
+ /* DO NOT UPDATE THE DEFAULT VIEW.
+ * Create subviews instead, or a copy. */
+ BLI_assert(view != DST.view_default);
+ BLI_assert(view->parent == NULL);
+
+ view->is_dirty = true;
+
+ draw_view_matrix_state_update(&view->storage, viewmat, winmat);
+
+ /* Prepare frustum culling. */
+
+#ifdef DRW_DEBUG_CULLING
+ static float mv[MAX_CULLED_VIEWS][4][4], mw[MAX_CULLED_VIEWS][4][4];
+
+ /* Select view here. */
+ if (view->culling_mask != 0) {
+ uint index = bitscan_forward_uint(view->culling_mask);
+
+ if (G.debug_value == 0) {
+ copy_m4_m4(mv[index], culling_viewmat ? culling_viewmat : viewmat);
+ copy_m4_m4(mw[index], culling_winmat ? culling_winmat : winmat);
+ }
+ else {
+ culling_winmat = mw[index];
+ culling_viewmat = mv[index];
+ }
+ }
+#endif
+
+ float wininv[4][4];
+ if (culling_winmat) {
+ winmat = culling_winmat;
+ invert_m4_m4(wininv, winmat);
+ }
+ else {
+ copy_m4_m4(wininv, view->storage.wininv);
+ }
+
+ float viewinv[4][4];
+ if (culling_viewmat) {
+ viewmat = culling_viewmat;
+ invert_m4_m4(viewinv, viewmat);
+ }
+ else {
+ copy_m4_m4(viewinv, view->storage.viewinv);
+ }
+
+ draw_frustum_boundbox_calc(viewinv, winmat, &view->frustum_corners);
+ draw_frustum_culling_planes_calc(&view->frustum_corners, view->frustum_planes);
+ draw_frustum_bound_sphere_calc(
+ &view->frustum_corners, viewinv, winmat, wininv, &view->frustum_bsphere);
+
+#ifdef DRW_DEBUG_CULLING
+ if (G.debug_value != 0) {
+ DRW_debug_sphere(
+ view->frustum_bsphere.center, view->frustum_bsphere.radius, (const float[4]){1, 1, 0, 1});
+ DRW_debug_bbox(&view->frustum_corners, (const float[4]){1, 1, 0, 1});
+ }
+#endif
+}
+
+/* Return default view if it is a viewport render. */
+const DRWView *DRW_view_default_get(void)
+{
+ return DST.view_default;
+}
+
+/* MUST only be called once per render and only in render mode. Sets default view. */
+void DRW_view_default_set(DRWView *view)
+{
+ BLI_assert(DST.view_default == NULL);
+ DST.view_default = view;
+}
+
+/**
+ * This only works if DRWPasses have been tagged with DRW_STATE_CLIP_PLANES,
+ * and if the shaders have support for it (see usage of gl_ClipDistance).
+ * NOTE: planes must be in world space.
+ */
+void DRW_view_clip_planes_set(DRWView *view, float (*planes)[4], int plane_len)
+{
+ BLI_assert(plane_len <= MAX_CLIP_PLANES);
+ view->clip_planes_len = plane_len;
+ if (plane_len > 0) {
+ memcpy(view->storage.clipplanes, planes, sizeof(float) * 4 * plane_len);
+ }
+}
+
+void DRW_view_camtexco_set(DRWView *view, float texco[4])
+{
+ copy_v4_v4(view->storage.viewcamtexcofac, texco);
+}
+
+/* Return world space frustum corners. */
+void DRW_view_frustum_corners_get(const DRWView *view, BoundBox *corners)
+{
+ memcpy(corners, &view->frustum_corners, sizeof(view->frustum_corners));
+}
+
+/* Return world space frustum sides as planes.
+ * See draw_frustum_culling_planes_calc() for the plane order. */
+void DRW_view_frustum_planes_get(const DRWView *view, float planes[6][4])
+{
+ memcpy(planes, &view->frustum_planes, sizeof(view->frustum_planes));
+}
+
+bool DRW_view_is_persp_get(const DRWView *view)
+{
+ view = (view) ? view : DST.view_default;
+ return view->storage.winmat[3][3] == 0.0f;
+}
+
+float DRW_view_near_distance_get(const DRWView *view)
+{
+ view = (view) ? view : DST.view_default;
+ const float(*projmat)[4] = view->storage.winmat;
+
+ if (DRW_view_is_persp_get(view)) {
+ return -projmat[3][2] / (projmat[2][2] - 1.0f);
+ }
+ else {
+ return -(projmat[3][2] + 1.0f) / projmat[2][2];
+ }
+}
+
+float DRW_view_far_distance_get(const DRWView *view)
+{
+ view = (view) ? view : DST.view_default;
+ const float(*projmat)[4] = view->storage.winmat;
+
+ if (DRW_view_is_persp_get(view)) {
+ return -projmat[3][2] / (projmat[2][2] + 1.0f);
+ }
+ else {
+ return -(projmat[3][2] - 1.0f) / projmat[2][2];
+ }
+}
+
+void DRW_view_viewmat_get(const DRWView *view, float mat[4][4], bool inverse)
+{
+ view = (view) ? view : DST.view_default;
+ const DRWViewUboStorage *storage = &view->storage;
+ copy_m4_m4(mat, (inverse) ? storage->viewinv : storage->viewmat);
+}
+
+void DRW_view_winmat_get(const DRWView *view, float mat[4][4], bool inverse)
+{
+ view = (view) ? view : DST.view_default;
+ const DRWViewUboStorage *storage = &view->storage;
+ copy_m4_m4(mat, (inverse) ? storage->wininv : storage->winmat);
+}
+
+void DRW_view_persmat_get(const DRWView *view, float mat[4][4], bool inverse)
+{
+ view = (view) ? view : DST.view_default;
+ const DRWViewUboStorage *storage = &view->storage;
+ copy_m4_m4(mat, (inverse) ? storage->persinv : storage->persmat);
+}
+
+/** \} */
+
+/* -------------------------------------------------------------------- */
/** \name Passes (DRW_pass)
* \{ */
@@ -1118,8 +1587,8 @@ void DRW_pass_foreach_shgroup(DRWPass *pass,
}
typedef struct ZSortData {
- float *axis;
- float *origin;
+ const float *axis;
+ const float *origin;
} ZSortData;
static int pass_shgroup_dist_sort(void *thunk, const void *a, const void *b)
@@ -1182,8 +1651,7 @@ static int pass_shgroup_dist_sort(void *thunk, const void *a, const void *b)
*/
void DRW_pass_sort_shgroup_z(DRWPass *pass)
{
- float(*viewinv)[4];
- viewinv = DST.view_data.matstate.mat[DRW_MAT_VIEWINV];
+ const float(*viewinv)[4] = DST.view_active->storage.viewinv;
ZSortData zsortdata = {viewinv[2], viewinv[3]};
diff --git a/source/blender/draw/intern/draw_manager_exec.c b/source/blender/draw/intern/draw_manager_exec.c
index 2c29ce343dd..b232cfd01ad 100644
--- a/source/blender/draw/intern/draw_manager_exec.c
+++ b/source/blender/draw/intern/draw_manager_exec.c
@@ -238,7 +238,7 @@ void drw_state_set(DRWState state)
int test;
if ((test = CHANGED_TO(DRW_STATE_CLIP_PLANES))) {
if (test == 1) {
- for (int i = 0; i < DST.clip_planes_len; ++i) {
+ for (int i = 0; i < DST.view_active->clip_planes_len; ++i) {
glEnable(GL_CLIP_DISTANCE0 + i);
}
}
@@ -306,33 +306,6 @@ void drw_state_set(DRWState state)
}
}
- /* Polygon Offset */
- {
- int test;
- if (CHANGED_ANY_STORE_VAR(DRW_STATE_OFFSET_POSITIVE | DRW_STATE_OFFSET_NEGATIVE, test)) {
- if (test) {
- glEnable(GL_POLYGON_OFFSET_FILL);
- glEnable(GL_POLYGON_OFFSET_LINE);
- glEnable(GL_POLYGON_OFFSET_POINT);
- /* Stencil Write */
- if ((state & DRW_STATE_OFFSET_POSITIVE) != 0) {
- glPolygonOffset(1.0f, 1.0f);
- }
- else if ((state & DRW_STATE_OFFSET_NEGATIVE) != 0) {
- glPolygonOffset(-1.0f, -1.0f);
- }
- else {
- BLI_assert(0);
- }
- }
- else {
- glDisable(GL_POLYGON_OFFSET_FILL);
- glDisable(GL_POLYGON_OFFSET_LINE);
- glDisable(GL_POLYGON_OFFSET_POINT);
- }
- }
- }
-
#undef CHANGED_TO
#undef CHANGED_ANY
#undef CHANGED_ANY_STORE_VAR
@@ -387,282 +360,34 @@ void DRW_state_reset(void)
glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
}
-/**
- * This only works if DRWPasses have been tagged with DRW_STATE_CLIP_PLANES,
- * and if the shaders have support for it (see usage of gl_ClipDistance).
- * Be sure to call DRW_state_clip_planes_reset() after you finish drawing.
- */
-void DRW_state_clip_planes_len_set(uint plane_len)
-{
- BLI_assert(plane_len <= MAX_CLIP_PLANES);
- DST.clip_planes_len = plane_len;
-}
-
-void DRW_state_clip_planes_reset(void)
-{
- DST.clip_planes_len = 0;
-}
-
-void DRW_state_clip_planes_set_from_rv3d(RegionView3D *rv3d)
-{
- int max_len = 6;
- int real_len = (rv3d->viewlock & RV3D_BOXCLIP) ? 4 : max_len;
- while (real_len < max_len) {
- /* Fill in dummy values that wont change results (6 is hard coded in shaders). */
- copy_v4_v4(rv3d->clip[real_len], rv3d->clip[3]);
- real_len++;
- }
-
- DRW_state_clip_planes_len_set(max_len);
-}
-
/** \} */
/* -------------------------------------------------------------------- */
-/** \name Clipping (DRW_clipping)
+/** \name Culling (DRW_culling)
* \{ */
-/* Extract the 8 corners from a Projection Matrix.
- * Although less accurate, this solution can be simplified as follows:
- * BKE_boundbox_init_from_minmax(&bbox, (const float[3]){-1.0f, -1.0f, -1.0f}, (const
- * float[3]){1.0f, 1.0f, 1.0f}); for (int i = 0; i < 8; i++) {mul_project_m4_v3(projinv,
- * bbox.vec[i]);}
- */
-static void draw_frustum_boundbox_calc(const float (*projmat)[4], BoundBox *r_bbox)
+static bool draw_call_is_culled(DRWCall *call, DRWView *view)
{
- float left, right, bottom, top, near, far;
- bool is_persp = projmat[3][3] == 0.0f;
-
- projmat_dimensions(projmat, &left, &right, &bottom, &top, &near, &far);
-
- if (is_persp) {
- left *= near;
- right *= near;
- bottom *= near;
- top *= near;
- }
-
- r_bbox->vec[0][2] = r_bbox->vec[3][2] = r_bbox->vec[7][2] = r_bbox->vec[4][2] = -near;
- r_bbox->vec[0][0] = r_bbox->vec[3][0] = left;
- r_bbox->vec[4][0] = r_bbox->vec[7][0] = right;
- r_bbox->vec[0][1] = r_bbox->vec[4][1] = bottom;
- r_bbox->vec[7][1] = r_bbox->vec[3][1] = top;
-
- /* Get the coordinates of the far plane. */
- if (is_persp) {
- float sca_far = far / near;
- left *= sca_far;
- right *= sca_far;
- bottom *= sca_far;
- top *= sca_far;
- }
-
- r_bbox->vec[1][2] = r_bbox->vec[2][2] = r_bbox->vec[6][2] = r_bbox->vec[5][2] = -far;
- r_bbox->vec[1][0] = r_bbox->vec[2][0] = left;
- r_bbox->vec[6][0] = r_bbox->vec[5][0] = right;
- r_bbox->vec[1][1] = r_bbox->vec[5][1] = bottom;
- r_bbox->vec[2][1] = r_bbox->vec[6][1] = top;
+ return (call->state->culling->mask & view->culling_mask) != 0;
}
-static void draw_clipping_setup_from_view(void)
+/* Set active view for rendering. */
+void DRW_view_set_active(DRWView *view)
{
- if (DST.clipping.updated) {
- return;
- }
-
- float(*viewinv)[4] = DST.view_data.matstate.mat[DRW_MAT_VIEWINV];
- float(*projmat)[4] = DST.view_data.matstate.mat[DRW_MAT_WIN];
- float(*projinv)[4] = DST.view_data.matstate.mat[DRW_MAT_WININV];
- BoundSphere *bsphere = &DST.clipping.frustum_bsphere;
-
- /* Extract Clipping Planes */
- BoundBox bbox;
-#if 0 /* It has accuracy problems. */
- BKE_boundbox_init_from_minmax(
- &bbox, (const float[3]){-1.0f, -1.0f, -1.0f}, (const float[3]){1.0f, 1.0f, 1.0f});
- for (int i = 0; i < 8; i++) {
- mul_project_m4_v3(projinv, bbox.vec[i]);
- }
-#else
- draw_frustum_boundbox_calc(projmat, &bbox);
-#endif
- /* Transform into world space. */
- for (int i = 0; i < 8; i++) {
- mul_m4_v3(viewinv, bbox.vec[i]);
- }
-
- memcpy(&DST.clipping.frustum_corners, &bbox, sizeof(BoundBox));
-
- /* Compute clip planes using the world space frustum corners. */
- for (int p = 0; p < 6; p++) {
- int q, r, s;
- switch (p) {
- case 0:
- q = 1;
- r = 2;
- s = 3;
- break; /* -X */
- case 1:
- q = 0;
- r = 4;
- s = 5;
- break; /* -Y */
- case 2:
- q = 1;
- r = 5;
- s = 6;
- break; /* +Z (far) */
- case 3:
- q = 2;
- r = 6;
- s = 7;
- break; /* +Y */
- case 4:
- q = 0;
- r = 3;
- s = 7;
- break; /* -Z (near) */
- default:
- q = 4;
- r = 7;
- s = 6;
- break; /* +X */
- }
- if (DST.frontface == GL_CW) {
- SWAP(int, q, s);
- }
-
- normal_quad_v3(
- DST.clipping.frustum_planes[p], bbox.vec[p], bbox.vec[q], bbox.vec[r], bbox.vec[s]);
- /* Increase precision and use the mean of all 4 corners. */
- DST.clipping.frustum_planes[p][3] = -dot_v3v3(DST.clipping.frustum_planes[p], bbox.vec[p]);
- DST.clipping.frustum_planes[p][3] += -dot_v3v3(DST.clipping.frustum_planes[p], bbox.vec[q]);
- DST.clipping.frustum_planes[p][3] += -dot_v3v3(DST.clipping.frustum_planes[p], bbox.vec[r]);
- DST.clipping.frustum_planes[p][3] += -dot_v3v3(DST.clipping.frustum_planes[p], bbox.vec[s]);
- DST.clipping.frustum_planes[p][3] *= 0.25f;
- }
-
- /* Extract Bounding Sphere */
- if (projmat[3][3] != 0.0f) {
- /* Orthographic */
- /* The most extreme points on the near and far plane. (normalized device coords). */
- float *nearpoint = bbox.vec[0];
- float *farpoint = bbox.vec[6];
-
- /* just use median point */
- mid_v3_v3v3(bsphere->center, farpoint, nearpoint);
- bsphere->radius = len_v3v3(bsphere->center, farpoint);
- }
- else if (projmat[2][0] == 0.0f && projmat[2][1] == 0.0f) {
- /* Perspective with symmetrical frustum. */
-
- /* We obtain the center and radius of the circumscribed circle of the
- * isosceles trapezoid composed by the diagonals of the near and far clipping plane */
-
- /* center of each clipping plane */
- float mid_min[3], mid_max[3];
- mid_v3_v3v3(mid_min, bbox.vec[3], bbox.vec[4]);
- mid_v3_v3v3(mid_max, bbox.vec[2], bbox.vec[5]);
-
- /* square length of the diagonals of each clipping plane */
- float a_sq = len_squared_v3v3(bbox.vec[3], bbox.vec[4]);
- float b_sq = len_squared_v3v3(bbox.vec[2], bbox.vec[5]);
-
- /* distance squared between clipping planes */
- float h_sq = len_squared_v3v3(mid_min, mid_max);
-
- float fac = (4 * h_sq + b_sq - a_sq) / (8 * h_sq);
-
- /* The goal is to get the smallest sphere,
- * not the sphere that passes through each corner */
- CLAMP(fac, 0.0f, 1.0f);
-
- interp_v3_v3v3(bsphere->center, mid_min, mid_max, fac);
-
- /* distance from the center to one of the points of the far plane (1, 2, 5, 6) */
- bsphere->radius = len_v3v3(bsphere->center, bbox.vec[1]);
- }
- else {
- /* Perspective with asymmetrical frustum. */
-
- /* We put the sphere center on the line that goes from origin
- * to the center of the far clipping plane. */
-
- /* Detect which of the corner of the far clipping plane is the farthest to the origin */
- float nfar[4]; /* most extreme far point in NDC space */
- float farxy[2]; /* farpoint projection onto the near plane */
- float farpoint[3] = {0.0f}; /* most extreme far point in camera coordinate */
- float nearpoint[3]; /* most extreme near point in camera coordinate */
- float farcenter[3] = {0.0f}; /* center of far cliping plane in camera coordinate */
- float F = -1.0f, N; /* square distance of far and near point to origin */
- float f, n; /* distance of far and near point to z axis. f is always > 0 but n can be < 0 */
- float e, s; /* far and near clipping distance (<0) */
- float c; /* slope of center line = distance of far clipping center
- * to z axis / far clipping distance. */
- float z; /* projection of sphere center on z axis (<0) */
-
- /* Find farthest corner and center of far clip plane. */
- float corner[3] = {1.0f, 1.0f, 1.0f}; /* in clip space */
- for (int i = 0; i < 4; i++) {
- float point[3];
- mul_v3_project_m4_v3(point, projinv, corner);
- float len = len_squared_v3(point);
- if (len > F) {
- copy_v3_v3(nfar, corner);
- copy_v3_v3(farpoint, point);
- F = len;
- }
- add_v3_v3(farcenter, point);
- /* rotate by 90 degree to walk through the 4 points of the far clip plane */
- float tmp = corner[0];
- corner[0] = -corner[1];
- corner[1] = tmp;
- }
-
- /* the far center is the average of the far clipping points */
- mul_v3_fl(farcenter, 0.25f);
- /* the extreme near point is the opposite point on the near clipping plane */
- copy_v3_fl3(nfar, -nfar[0], -nfar[1], -1.0f);
- mul_v3_project_m4_v3(nearpoint, projinv, nfar);
- /* this is a frustum projection */
- N = len_squared_v3(nearpoint);
- e = farpoint[2];
- s = nearpoint[2];
- /* distance to view Z axis */
- f = len_v2(farpoint);
- /* get corresponding point on the near plane */
- mul_v2_v2fl(farxy, farpoint, s / e);
- /* this formula preserve the sign of n */
- sub_v2_v2(nearpoint, farxy);
- n = f * s / e - len_v2(nearpoint);
- c = len_v2(farcenter) / e;
- /* the big formula, it simplifies to (F-N)/(2(e-s)) for the symmetric case */
- z = (F - N) / (2.0f * (e - s + c * (f - n)));
-
- bsphere->center[0] = farcenter[0] * z / e;
- bsphere->center[1] = farcenter[1] * z / e;
- bsphere->center[2] = z;
- bsphere->radius = len_v3v3(bsphere->center, farpoint);
-
- /* Transform to world space. */
- mul_m4_v3(viewinv, bsphere->center);
- }
-
- DST.clipping.updated = true;
+ DST.view_active = (view) ? view : DST.view_default;
}
/* Return True if the given BoundSphere intersect the current view frustum */
-bool DRW_culling_sphere_test(BoundSphere *bsphere)
+static bool draw_culling_sphere_test(const BoundSphere *frustum_bsphere,
+ const float (*frustum_planes)[4],
+ const BoundSphere *bsphere)
{
- draw_clipping_setup_from_view();
-
/* Bypass test if radius is negative. */
if (bsphere->radius < 0.0f) {
return true;
}
/* Do a rough test first: Sphere VS Sphere intersect. */
- BoundSphere *frustum_bsphere = &DST.clipping.frustum_bsphere;
float center_dist_sq = len_squared_v3v3(bsphere->center, frustum_bsphere->center);
float radius_sum = bsphere->radius + frustum_bsphere->radius;
if (center_dist_sq > SQUARE(radius_sum)) {
@@ -674,26 +399,21 @@ bool DRW_culling_sphere_test(BoundSphere *bsphere)
/* TODO order planes with sides first then far then near clip. Should be better culling
* heuristic when sculpting. */
for (int p = 0; p < 6; p++) {
- float dist = plane_point_side_v3(DST.clipping.frustum_planes[p], bsphere->center);
+ float dist = plane_point_side_v3(frustum_planes[p], bsphere->center);
if (dist < -bsphere->radius) {
return false;
}
}
-
return true;
}
-/* Return True if the given BoundBox intersect the current view frustum.
- * bbox must be in world space. */
-bool DRW_culling_box_test(BoundBox *bbox)
+static bool draw_culling_box_test(const float (*frustum_planes)[4], const BoundBox *bbox)
{
- draw_clipping_setup_from_view();
-
/* 6 view frustum planes */
for (int p = 0; p < 6; p++) {
/* 8 box vertices. */
for (int v = 0; v < 8; v++) {
- float dist = plane_point_side_v3(DST.clipping.frustum_planes[p], bbox->vec[v]);
+ float dist = plane_point_side_v3(frustum_planes[p], bbox->vec[v]);
if (dist > 0.0f) {
/* At least one point in front of this plane.
* Go to next plane. */
@@ -705,152 +425,162 @@ bool DRW_culling_box_test(BoundBox *bbox)
}
}
}
-
return true;
}
-/* Return True if the current view frustum is inside or intersect the given plane */
-bool DRW_culling_plane_test(float plane[4])
+static bool draw_culling_plane_test(const BoundBox *corners, const float plane[4])
{
- draw_clipping_setup_from_view();
-
/* Test against the 8 frustum corners. */
for (int c = 0; c < 8; c++) {
- float dist = plane_point_side_v3(plane, DST.clipping.frustum_corners.vec[c]);
+ float dist = plane_point_side_v3(plane, corners->vec[c]);
if (dist < 0.0f) {
return true;
}
}
-
return false;
}
-void DRW_culling_frustum_corners_get(BoundBox *corners)
+/* Return True if the given BoundSphere intersect the current view frustum.
+ * bsphere must be in world space. */
+bool DRW_culling_sphere_test(const DRWView *view, const BoundSphere *bsphere)
{
- draw_clipping_setup_from_view();
- memcpy(corners, &DST.clipping.frustum_corners, sizeof(BoundBox));
+ view = view ? view : DST.view_default;
+ return draw_culling_sphere_test(&view->frustum_bsphere, view->frustum_planes, bsphere);
}
-/* See draw_clipping_setup_from_view() for the plane order. */
-void DRW_culling_frustum_planes_get(float planes[6][4])
+/* Return True if the given BoundBox intersect the current view frustum.
+ * bbox must be in world space. */
+bool DRW_culling_box_test(const DRWView *view, const BoundBox *bbox)
{
- draw_clipping_setup_from_view();
- memcpy(planes, &DST.clipping.frustum_planes, sizeof(DST.clipping.frustum_planes));
+ view = view ? view : DST.view_default;
+ return draw_culling_box_test(view->frustum_planes, bbox);
}
-/** \} */
+/* Return True if the view frustum is inside or intersect the given plane.
+ * plane must be in world space. */
+bool DRW_culling_plane_test(const DRWView *view, const float plane[4])
+{
+ view = view ? view : DST.view_default;
+ return draw_culling_plane_test(&view->frustum_corners, plane);
+}
-/* -------------------------------------------------------------------- */
-/** \name Draw (DRW_draw)
- * \{ */
+void DRW_culling_frustum_corners_get(const DRWView *view, BoundBox *corners)
+{
+ view = view ? view : DST.view_default;
+ *corners = view->frustum_corners;
+}
+
+void DRW_culling_frustum_planes_get(const DRWView *view, float planes[6][4])
+{
+ view = view ? view : DST.view_default;
+ memcpy(planes, view->frustum_planes, sizeof(float) * 6 * 4);
+}
-static void draw_visibility_eval(DRWCallState *st)
+static void draw_compute_culling(DRWView *view)
{
- bool culled = st->flag & DRW_CALL_CULLED;
+ view = view->parent ? view->parent : view;
- if (st->cache_id != DST.state_cache_id) {
- /* Update culling result for this view. */
- culled = !DRW_culling_sphere_test(&st->bsphere);
+ /* TODO(fclem) multithread this. */
+ /* TODO(fclem) compute all dirty views at once. */
+ if (!view->is_dirty) {
+ return;
}
- if (st->visibility_cb) {
- culled = !st->visibility_cb(!culled, st->user_data);
+ BLI_memblock_iter iter;
+ BLI_memblock_iternew(DST.vmempool->cullstates, &iter);
+ DRWCullingState *cull;
+ while ((cull = BLI_memblock_iterstep(&iter))) {
+ if (cull->bsphere.radius < 0.0) {
+ cull->mask = 0;
+ }
+ else {
+ bool culled = !draw_culling_sphere_test(
+ &view->frustum_bsphere, view->frustum_planes, &cull->bsphere);
+
+#ifdef DRW_DEBUG_CULLING
+ if (G.debug_value != 0) {
+ if (culled) {
+ DRW_debug_sphere(
+ cull->bsphere.center, cull->bsphere.radius, (const float[4]){1, 0, 0, 1});
+ }
+ else {
+ DRW_debug_sphere(
+ cull->bsphere.center, cull->bsphere.radius, (const float[4]){0, 1, 0, 1});
+ }
+ }
+#endif
+
+ if (view->visibility_fn) {
+ culled = !view->visibility_fn(!culled, cull->user_data);
+ }
+
+ SET_FLAG_FROM_TEST(cull->mask, culled, view->culling_mask);
+ }
}
- SET_FLAG_FROM_TEST(st->flag, culled, DRW_CALL_CULLED);
+ view->is_dirty = false;
}
-static void draw_matrices_model_prepare(DRWCallState *st)
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Draw (DRW_draw)
+ * \{ */
+
+static void draw_geometry_prepare(DRWShadingGroup *shgroup, DRWCall *call)
{
- if (st->cache_id == DST.state_cache_id) {
- /* Values are already updated for this view. */
- return;
+ BLI_assert(call);
+ DRWCallState *state = call->state;
+
+ if (shgroup->model != -1) {
+ GPU_shader_uniform_vector(shgroup->shader, shgroup->model, 16, 1, (float *)state->model);
}
- else {
- st->cache_id = DST.state_cache_id;
+ if (shgroup->modelinverse != -1) {
+ GPU_shader_uniform_vector(
+ shgroup->shader, shgroup->modelinverse, 16, 1, (float *)state->modelinverse);
}
-
- /* No need to go further the call will not be used. */
- if ((st->flag & DRW_CALL_CULLED) != 0 && (st->flag & DRW_CALL_BYPASS_CULLING) == 0) {
- return;
+ if (shgroup->objectinfo != -1) {
+ float infos[4];
+ infos[0] = state->ob_index;
+ // infos[1]; /* UNUSED. */
+ infos[2] = state->ob_random;
+ infos[3] = (state->flag & DRW_CALL_NEGSCALE) ? -1.0f : 1.0f;
+ GPU_shader_uniform_vector(shgroup->shader, shgroup->objectinfo, 4, 1, (float *)infos);
}
-
- if (st->matflag & DRW_CALL_MODELVIEWPROJECTION) {
- mul_m4_m4m4(st->modelviewprojection, DST.view_data.matstate.mat[DRW_MAT_PERS], st->model);
+ if (shgroup->orcotexfac != -1) {
+ GPU_shader_uniform_vector(
+ shgroup->shader, shgroup->orcotexfac, 3, 2, (float *)state->orcotexfac);
+ }
+ /* Still supported for compatibility with gpu_shader_* but should be forbidden
+ * and is slow (since it does not cache the result). */
+ if (shgroup->modelviewprojection != -1) {
+ float mvp[4][4];
+ mul_m4_m4m4(mvp, DST.view_active->storage.persmat, state->model);
+ GPU_shader_uniform_vector(shgroup->shader, shgroup->modelviewprojection, 16, 1, (float *)mvp);
}
}
-static void draw_geometry_prepare(DRWShadingGroup *shgroup, DRWCall *call)
+BLI_INLINE void draw_geometry_execute(DRWShadingGroup *shgroup,
+ GPUBatch *geom,
+ uint vert_first,
+ uint vert_count,
+ uint inst_first,
+ uint inst_count)
{
- /* step 1 : bind object dependent matrices */
- if (call != NULL) {
- DRWCallState *state = call->state;
+ /* bind vertex array */
+ if (DST.batch != geom) {
+ DST.batch = geom;
- if (shgroup->model != -1) {
- GPU_shader_uniform_vector(shgroup->shader, shgroup->model, 16, 1, (float *)state->model);
- }
- if (shgroup->modelinverse != -1) {
- GPU_shader_uniform_vector(
- shgroup->shader, shgroup->modelinverse, 16, 1, (float *)state->modelinverse);
- }
- if (shgroup->modelviewprojection != -1) {
- GPU_shader_uniform_vector(shgroup->shader,
- shgroup->modelviewprojection,
- 16,
- 1,
- (float *)state->modelviewprojection);
- }
- if (shgroup->objectinfo != -1) {
- float infos[4];
- infos[0] = state->ob_index;
- // infos[1]; /* UNUSED. */
- infos[2] = state->ob_random;
- infos[3] = (state->flag & DRW_CALL_NEGSCALE) ? -1.0f : 1.0f;
- GPU_shader_uniform_vector(shgroup->shader, shgroup->objectinfo, 4, 1, (float *)infos);
- }
- if (shgroup->orcotexfac != -1) {
- GPU_shader_uniform_vector(
- shgroup->shader, shgroup->orcotexfac, 3, 2, (float *)state->orcotexfac);
- }
- }
- else {
- /* For instancing and batching. */
- float unitmat[4][4];
- unit_m4(unitmat);
+ GPU_batch_program_set_no_use(
+ geom, GPU_shader_get_program(shgroup->shader), GPU_shader_get_interface(shgroup->shader));
- if (shgroup->model != -1) {
- GPU_shader_uniform_vector(shgroup->shader, shgroup->model, 16, 1, (float *)unitmat);
- }
- if (shgroup->modelinverse != -1) {
- GPU_shader_uniform_vector(shgroup->shader, shgroup->modelinverse, 16, 1, (float *)unitmat);
- }
- if (shgroup->modelviewprojection != -1) {
- GPU_shader_uniform_vector(shgroup->shader,
- shgroup->modelviewprojection,
- 16,
- 1,
- (float *)DST.view_data.matstate.mat[DRW_MAT_PERS]);
- }
- if (shgroup->objectinfo != -1) {
- GPU_shader_uniform_vector(shgroup->shader, shgroup->objectinfo, 4, 1, (float *)unitmat);
- }
- if (shgroup->orcotexfac != -1) {
- float orcofacs[2][3] = {{0.0f, 0.0f, 0.0f}, {1.0f, 1.0f, 1.0f}};
- GPU_shader_uniform_vector(shgroup->shader, shgroup->orcotexfac, 3, 2, (float *)orcofacs);
- }
+ GPU_batch_bind(geom);
}
-}
-static void draw_geometry_execute(
- DRWShadingGroup *shgroup, GPUBatch *geom, uint start, uint count, bool draw_instance)
-{
- /* step 2 : bind vertex array & draw */
- GPU_batch_program_set_no_use(
- geom, GPU_shader_get_program(shgroup->shader), GPU_shader_get_interface(shgroup->shader));
/* XXX hacking gawain. we don't want to call glUseProgram! (huge performance loss) */
geom->program_in_use = true;
- GPU_batch_draw_range_ex(geom, start, count, draw_instance);
+ GPU_batch_draw_advanced(geom, vert_first, vert_count, inst_first, inst_count);
geom->program_in_use = false; /* XXX hacking gawain */
}
@@ -863,7 +593,7 @@ enum {
static void set_bound_flags(uint64_t *slots, uint64_t *persist_slots, int slot_idx, char bind_type)
{
- uint64_t slot = 1lu << (unsigned long)slot_idx;
+ uint64_t slot = 1llu << (unsigned long)slot_idx;
*slots |= slot;
if (bind_type == BIND_PERSIST) {
*persist_slots |= slot;
@@ -1023,6 +753,67 @@ static void release_ubo_slots(bool with_persist)
}
}
+static void draw_update_uniforms(DRWShadingGroup *shgroup)
+{
+ for (DRWUniform *uni = shgroup->uniforms; uni; uni = uni->next) {
+ 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:
+ case DRW_UNIFORM_INT:
+ GPU_shader_uniform_vector_int(
+ shgroup->shader, uni->location, uni->length, uni->arraysize, data);
+ break;
+ case DRW_UNIFORM_FLOAT_COPY:
+ case DRW_UNIFORM_FLOAT:
+ GPU_shader_uniform_vector(
+ shgroup->shader, uni->location, uni->length, uni->arraysize, data);
+ 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);
+ 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);
+ break;
+ case DRW_UNIFORM_BLOCK:
+ ubo = (GPUUniformBuffer *)uni->pvalue;
+ bind_ubo(ubo, BIND_TEMP);
+ GPU_shader_uniform_buffer(shgroup->shader, uni->location, ubo);
+ break;
+ case DRW_UNIFORM_BLOCK_PERSIST:
+ ubo = (GPUUniformBuffer *)uni->pvalue;
+ bind_ubo(ubo, BIND_PERSIST);
+ GPU_shader_uniform_buffer(shgroup->shader, uni->location, ubo);
+ break;
+ }
+ }
+
+ BLI_assert(ubo_bindings_validate(shgroup));
+}
+
BLI_INLINE bool draw_select_do_call(DRWShadingGroup *shgroup, DRWCall *call)
{
#ifdef USE_GPU_SELECT
@@ -1052,7 +843,12 @@ BLI_INLINE bool draw_select_do_call(DRWShadingGroup *shgroup, DRWCall *call)
while (start < tot) {
GPU_select_load_id(select_id[start]);
- draw_geometry_execute(shgroup, call->batch, start, count, is_instancing);
+ if (is_instancing) {
+ draw_geometry_execute(shgroup, call->batch, 0, 0, start, count);
+ }
+ else {
+ draw_geometry_execute(shgroup, call->batch, start, count, 0, 0);
+ }
start += count;
}
return true;
@@ -1070,8 +866,6 @@ static void draw_shgroup(DRWShadingGroup *shgroup, DRWState pass_state)
{
BLI_assert(shgroup->shader);
- GPUTexture *tex;
- GPUUniformBuffer *ubo;
const bool shader_changed = (DST.shader != shgroup->shader);
bool use_tfeedback = false;
@@ -1081,6 +875,7 @@ static void draw_shgroup(DRWShadingGroup *shgroup, DRWState pass_state)
}
GPU_shader_bind(shgroup->shader);
DST.shader = shgroup->shader;
+ DST.batch = NULL;
}
if (shgroup->tfeedback_target != NULL) {
@@ -1094,62 +889,7 @@ static void draw_shgroup(DRWShadingGroup *shgroup, DRWState pass_state)
drw_state_set((pass_state & shgroup->state_extra_disable) | shgroup->state_extra);
drw_stencil_set(shgroup->stencil_mask);
- /* Binding Uniform */
- for (DRWUniform *uni = shgroup->uniforms; uni; uni = uni->next) {
- 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:
- case DRW_UNIFORM_INT:
- GPU_shader_uniform_vector_int(
- shgroup->shader, uni->location, uni->length, uni->arraysize, data);
- break;
- case DRW_UNIFORM_FLOAT_COPY:
- case DRW_UNIFORM_FLOAT:
- GPU_shader_uniform_vector(
- shgroup->shader, uni->location, uni->length, uni->arraysize, data);
- 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);
- 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);
- break;
- case DRW_UNIFORM_BLOCK:
- ubo = (GPUUniformBuffer *)uni->pvalue;
- bind_ubo(ubo, BIND_TEMP);
- GPU_shader_uniform_buffer(shgroup->shader, uni->location, ubo);
- break;
- case DRW_UNIFORM_BLOCK_PERSIST:
- ubo = (GPUUniformBuffer *)uni->pvalue;
- bind_ubo(ubo, BIND_PERSIST);
- GPU_shader_uniform_buffer(shgroup->shader, uni->location, ubo);
- break;
- }
- }
-
- BLI_assert(ubo_bindings_validate(shgroup));
+ draw_update_uniforms(shgroup);
/* Rendering Calls */
{
@@ -1157,12 +897,7 @@ static void draw_shgroup(DRWShadingGroup *shgroup, DRWState pass_state)
int callid = 0;
for (DRWCall *call = shgroup->calls.first; call; call = call->next) {
- /* OPTI/IDEA(clem): Do this preparation in another thread. */
- draw_visibility_eval(call->state);
- draw_matrices_model_prepare(call->state);
-
- if ((call->state->flag & DRW_CALL_CULLED) != 0 &&
- (call->state->flag & DRW_CALL_BYPASS_CULLING) == 0) {
+ if (draw_call_is_culled(call, DST.view_active)) {
continue;
}
@@ -1175,7 +910,7 @@ static void draw_shgroup(DRWShadingGroup *shgroup, DRWState pass_state)
/* Negative scale objects */
bool neg_scale = call->state->flag & DRW_CALL_NEGSCALE;
if (neg_scale != prev_neg_scale) {
- glFrontFace((neg_scale) ? DST.backface : DST.frontface);
+ glFrontFace((neg_scale) ? GL_CW : GL_CCW);
prev_neg_scale = neg_scale;
}
@@ -1185,16 +920,11 @@ static void draw_shgroup(DRWShadingGroup *shgroup, DRWState pass_state)
continue;
}
- /* TODO revisit when DRW_SHG_INSTANCE and the like is gone. */
- if (call->inst_count == 0) {
- draw_geometry_execute(shgroup, call->batch, call->vert_first, call->vert_count, false);
- }
- else {
- draw_geometry_execute(shgroup, call->batch, 0, call->inst_count, true);
- }
+ draw_geometry_execute(
+ shgroup, call->batch, call->vert_first, call->vert_count, 0, call->inst_count);
}
/* Reset state */
- glFrontFace(DST.frontface);
+ glFrontFace(GL_CCW);
}
if (use_tfeedback) {
@@ -1204,29 +934,13 @@ static void draw_shgroup(DRWShadingGroup *shgroup, DRWState pass_state)
static void drw_update_view(void)
{
- if (DST.dirty_mat) {
- DST.state_cache_id++;
- DST.dirty_mat = false;
-
- DRW_uniformbuffer_update(G_draw.view_ubo, &DST.view_data);
-
- /* Catch integer wrap around. */
- if (UNLIKELY(DST.state_cache_id == 0)) {
- DST.state_cache_id = 1;
- /* We must reset all CallStates to ensure that not
- * a single one stayed with cache_id equal to 1. */
- BLI_memblock_iter iter;
- DRWCallState *state;
- BLI_memblock_iternew(DST.vmempool->states, &iter);
- while ((state = BLI_memblock_iterstep(&iter))) {
- state->cache_id = 0;
- }
- }
+ /* TODO(fclem) update a big UBO and only bind ranges here. */
+ DRW_uniformbuffer_update(G_draw.view_ubo, &DST.view_active->storage);
- /* TODO dispatch threads to compute matrices/culling */
- }
+ /* TODO get rid of this. */
+ DST.view_storage_cpy = DST.view_active->storage;
- draw_clipping_setup_from_view();
+ draw_compute_culling(DST.view_active);
}
static void drw_draw_pass_ex(DRWPass *pass,
@@ -1242,7 +956,11 @@ static void drw_draw_pass_ex(DRWPass *pass,
BLI_assert(DST.buffer_finish_called &&
"DRW_render_instance_buffer_finish had not been called before drawing");
- drw_update_view();
+ if (DST.view_previous != DST.view_active || DST.view_active->is_dirty) {
+ drw_update_view();
+ DST.view_active->is_dirty = false;
+ DST.view_previous = DST.view_active;
+ }
/* GPU_framebuffer_clear calls can change the state outside the DRW module.
* Force reset the affected states to avoid problems later. */
diff --git a/source/blender/draw/modes/edit_curve_mode.c b/source/blender/draw/modes/edit_curve_mode.c
index 98b35cc60a4..d1ea8af86f2 100644
--- a/source/blender/draw/modes/edit_curve_mode.c
+++ b/source/blender/draw/modes/edit_curve_mode.c
@@ -112,10 +112,6 @@ static void EDIT_CURVE_engine_init(void *UNUSED(vedata))
const DRWContextState *draw_ctx = DRW_context_state_get();
EDIT_CURVE_Shaders *sh_data = &e_data.sh_data[draw_ctx->sh_cfg];
- if (draw_ctx->sh_cfg == GPU_SHADER_CFG_CLIPPED) {
- DRW_state_clip_planes_set_from_rv3d(draw_ctx->rv3d);
- }
-
const GPUShaderConfigData *sh_cfg_data = &GPU_shader_cfg_data[draw_ctx->sh_cfg];
if (!sh_data->wire_sh) {
@@ -172,7 +168,7 @@ static void EDIT_CURVE_wire_shgrp_create(EDIT_CURVE_Shaders *sh_data,
DRWShadingGroup *grp = DRW_shgroup_create(sh_data->wire_sh, pass);
DRW_shgroup_uniform_vec4(grp, "color", G_draw.block.colorWireEdit, 1);
if (rv3d->rflag & RV3D_CLIPPING) {
- DRW_shgroup_world_clip_planes_from_rv3d(grp, rv3d);
+ DRW_shgroup_state_enable(grp, DRW_STATE_CLIP_PLANES);
}
*wire_shgrp = grp;
@@ -180,7 +176,7 @@ static void EDIT_CURVE_wire_shgrp_create(EDIT_CURVE_Shaders *sh_data,
DRW_shgroup_uniform_vec4(grp, "color", G_draw.block.colorWireEdit, 1);
DRW_shgroup_uniform_float_copy(grp, "normalSize", v3d->overlay.normals_length);
if (rv3d->rflag & RV3D_CLIPPING) {
- DRW_shgroup_world_clip_planes_from_rv3d(grp, rv3d);
+ DRW_shgroup_state_enable(grp, DRW_STATE_CLIP_PLANES);
}
*wire_normals_shgrp = grp;
}
@@ -233,7 +229,7 @@ static void EDIT_CURVE_cache_init(void *vedata)
DRW_shgroup_uniform_vec2(grp, "viewportSize", DRW_viewport_size_get(), 1);
DRW_shgroup_uniform_bool(grp, "showCurveHandles", &stl->g_data->show_handles, 1);
if (rv3d->rflag & RV3D_CLIPPING) {
- DRW_shgroup_world_clip_planes_from_rv3d(grp, rv3d);
+ DRW_shgroup_state_enable(grp, DRW_STATE_CLIP_PLANES);
}
stl->g_data->overlay_edge_shgrp = grp;
@@ -242,7 +238,7 @@ static void EDIT_CURVE_cache_init(void *vedata)
grp = DRW_shgroup_create(sh_data->overlay_vert_sh, psl->overlay_vert_pass);
DRW_shgroup_uniform_block(grp, "globalsBlock", G_draw.block_ubo);
if (rv3d->rflag & RV3D_CLIPPING) {
- DRW_shgroup_world_clip_planes_from_rv3d(grp, rv3d);
+ DRW_shgroup_state_enable(grp, DRW_STATE_CLIP_PLANES);
}
stl->g_data->overlay_vert_shgrp = grp;
}
@@ -334,8 +330,6 @@ static void EDIT_CURVE_draw_scene(void *vedata)
/* Thoses passes don't write to depth and are AA'ed using other tricks. */
DRW_draw_pass(psl->overlay_edge_pass);
DRW_draw_pass(psl->overlay_vert_pass);
-
- DRW_state_clip_planes_reset();
}
/* Cleanup when destroying the engine.
diff --git a/source/blender/draw/modes/edit_lattice_mode.c b/source/blender/draw/modes/edit_lattice_mode.c
index 5604f7f27c1..3058c5c829c 100644
--- a/source/blender/draw/modes/edit_lattice_mode.c
+++ b/source/blender/draw/modes/edit_lattice_mode.c
@@ -139,9 +139,7 @@ static void EDIT_LATTICE_engine_init(void *vedata)
const DRWContextState *draw_ctx = DRW_context_state_get();
EDIT_LATTICE_Shaders *sh_data = &e_data.sh_data[draw_ctx->sh_cfg];
- if (draw_ctx->sh_cfg == GPU_SHADER_CFG_CLIPPED) {
- DRW_state_clip_planes_set_from_rv3d(draw_ctx->rv3d);
- }
+
const GPUShaderConfigData *sh_cfg_data = &GPU_shader_cfg_data[draw_ctx->sh_cfg];
if (!sh_data->wire) {
@@ -186,7 +184,7 @@ static void EDIT_LATTICE_cache_init(void *vedata)
DRW_STATE_DEPTH_LESS_EQUAL);
stl->g_data->wire_shgrp = DRW_shgroup_create(sh_data->wire, psl->wire_pass);
if (rv3d->rflag & RV3D_CLIPPING) {
- DRW_shgroup_world_clip_planes_from_rv3d(stl->g_data->wire_shgrp, rv3d);
+ DRW_shgroup_state_enable(stl->g_data->wire_shgrp, DRW_STATE_CLIP_PLANES);
}
psl->vert_pass = DRW_pass_create("Lattice Verts",
@@ -194,7 +192,7 @@ static void EDIT_LATTICE_cache_init(void *vedata)
stl->g_data->vert_shgrp = DRW_shgroup_create(sh_data->overlay_vert, psl->vert_pass);
DRW_shgroup_uniform_block(stl->g_data->vert_shgrp, "globalsBlock", G_draw.block_ubo);
if (rv3d->rflag & RV3D_CLIPPING) {
- DRW_shgroup_world_clip_planes_from_rv3d(stl->g_data->vert_shgrp, rv3d);
+ DRW_shgroup_state_enable(stl->g_data->vert_shgrp, DRW_STATE_CLIP_PLANES);
}
}
}
diff --git a/source/blender/draw/modes/edit_mesh_mode.c b/source/blender/draw/modes/edit_mesh_mode.c
index 1bd94cbeecf..865e443b186 100644
--- a/source/blender/draw/modes/edit_mesh_mode.c
+++ b/source/blender/draw/modes/edit_mesh_mode.c
@@ -38,8 +38,6 @@
#include "BKE_editmesh.h"
#include "BKE_object.h"
-#include "BIF_glutil.h"
-
#include "BLI_dynstr.h"
#include "BLI_string_utils.h"
@@ -68,16 +66,25 @@ extern char datatoc_gpu_shader_flat_color_frag_glsl[];
extern char datatoc_gpu_shader_point_varying_color_frag_glsl[];
/* *********** LISTS *********** */
+
+typedef struct EDIT_MESH_ComponentPassList {
+ struct DRWPass *faces;
+ struct DRWPass *faces_cage;
+ struct DRWPass *edges;
+ struct DRWPass *verts;
+} EDIT_MESH_ComponentPassList;
+
typedef struct EDIT_MESH_PassList {
struct DRWPass *weight_faces;
struct DRWPass *depth_hidden_wire;
struct DRWPass *depth_hidden_wire_in_front;
- struct DRWPass *edit_face_overlay;
- struct DRWPass *edit_face_overlay_in_front;
- struct DRWPass *edit_face_in_front;
- struct DRWPass *edit_face_occluded;
+
+ EDIT_MESH_ComponentPassList edit_passes;
+ EDIT_MESH_ComponentPassList edit_passes_in_front;
+
struct DRWPass *mix_occlude;
struct DRWPass *facefill_occlude;
+ struct DRWPass *facefill_occlude_cage;
struct DRWPass *mesh_analysis_pass;
struct DRWPass *normals;
} EDIT_MESH_PassList;
@@ -134,6 +141,14 @@ static struct {
struct GPUTexture *occlude_wire_color_tx;
} e_data = {{{NULL}}}; /* Engine data */
+typedef struct EDIT_MESH_ComponentShadingGroupList {
+ DRWShadingGroup *verts;
+ DRWShadingGroup *edges;
+ DRWShadingGroup *faces;
+ DRWShadingGroup *faces_cage;
+ DRWShadingGroup *facedots;
+} EDIT_MESH_ComponentShadingGroupList;
+
typedef struct EDIT_MESH_PrivateData {
/* weight */
DRWShadingGroup *fweights_shgrp;
@@ -144,11 +159,8 @@ typedef struct EDIT_MESH_PrivateData {
DRWShadingGroup *vnormals_shgrp;
DRWShadingGroup *lnormals_shgrp;
- DRWShadingGroup *vert_shgrp;
- DRWShadingGroup *edge_shgrp;
- DRWShadingGroup *face_shgrp;
- DRWShadingGroup *face_cage_shgrp;
- DRWShadingGroup *facedot_shgrp;
+ EDIT_MESH_ComponentShadingGroupList edit_shgrps;
+ EDIT_MESH_ComponentShadingGroupList edit_in_front_shgrps;
DRWShadingGroup *vert_shgrp_in_front;
DRWShadingGroup *edge_shgrp_in_front;
@@ -157,8 +169,14 @@ typedef struct EDIT_MESH_PrivateData {
DRWShadingGroup *facedot_shgrp_in_front;
DRWShadingGroup *facefill_occluded_shgrp;
+ DRWShadingGroup *facefill_occluded_cage_shgrp;
DRWShadingGroup *mesh_analysis_shgrp;
+ DRWView *view_faces;
+ DRWView *view_faces_cage;
+ DRWView *view_edges;
+ DRWView *view_wires;
+
int data_mask[4];
int ghost_ob;
int edit_ob;
@@ -172,6 +190,7 @@ typedef struct EDIT_MESH_PrivateData {
static void EDIT_MESH_engine_init(void *vedata)
{
EDIT_MESH_FramebufferList *fbl = ((EDIT_MESH_Data *)vedata)->fbl;
+ EDIT_MESH_StorageList *stl = ((EDIT_MESH_Data *)vedata)->stl;
const DRWContextState *draw_ctx = DRW_context_state_get();
EDIT_MESH_Shaders *sh_data = &e_data.sh_data[draw_ctx->sh_cfg];
@@ -188,10 +207,6 @@ static void EDIT_MESH_engine_init(void *vedata)
{GPU_ATTACHMENT_TEXTURE(e_data.occlude_wire_depth_tx),
GPU_ATTACHMENT_TEXTURE(e_data.occlude_wire_color_tx)});
- if (draw_ctx->sh_cfg == GPU_SHADER_CFG_CLIPPED) {
- DRW_state_clip_planes_set_from_rv3d(draw_ctx->rv3d);
- }
-
const GPUShaderConfigData *sh_cfg_data = &GPU_shader_cfg_data[draw_ctx->sh_cfg];
if (!sh_data->weight_face) {
@@ -307,17 +322,27 @@ static void EDIT_MESH_engine_init(void *vedata)
sh_data->depth = DRW_shader_create_3d_depth_only(draw_ctx->sh_cfg);
}
+
+ if (!stl->g_data) {
+ /* Alloc transient pointers */
+ stl->g_data = MEM_mallocN(sizeof(*stl->g_data), __func__);
+ }
+
+ {
+ /* Create view with depth offset */
+ stl->g_data->view_faces = (DRWView *)DRW_view_default_get();
+ stl->g_data->view_faces_cage = DRW_view_create_with_zoffset(draw_ctx->rv3d, 0.5f);
+ stl->g_data->view_edges = DRW_view_create_with_zoffset(draw_ctx->rv3d, 1.0f);
+ stl->g_data->view_wires = DRW_view_create_with_zoffset(draw_ctx->rv3d, 1.5f);
+ }
}
-static DRWPass *edit_mesh_create_overlay_pass(float *face_alpha,
- int *data_mask,
- bool do_edges,
- DRWState statemod,
- DRWShadingGroup **r_face_shgrp,
- DRWShadingGroup **r_face_cage_shgrp,
- DRWShadingGroup **r_facedot_shgrp,
- DRWShadingGroup **r_edge_shgrp,
- DRWShadingGroup **r_vert_shgrp)
+static void edit_mesh_create_overlay_passes(float face_alpha,
+ int *data_mask,
+ bool do_edges,
+ DRWState statemod,
+ EDIT_MESH_ComponentPassList *passes,
+ EDIT_MESH_ComponentShadingGroupList *shgrps)
{
const DRWContextState *draw_ctx = DRW_context_state_get();
RegionView3D *rv3d = draw_ctx->rv3d;
@@ -328,17 +353,6 @@ static DRWPass *edit_mesh_create_overlay_pass(float *face_alpha,
const bool select_face = (tsettings->selectmode & SCE_SELECT_FACE) != 0;
const bool select_edge = (tsettings->selectmode & SCE_SELECT_EDGE) != 0;
- float winmat[4][4];
- float viewdist = rv3d->dist;
- DRW_viewport_matrix_get(winmat, DRW_MAT_WIN);
- /* special exception for ortho camera (viewdist isnt used for perspective cameras) */
- if (rv3d->persp == RV3D_CAMOB && rv3d->is_persp == false) {
- viewdist = 1.0f / max_ff(fabsf(rv3d->winmat[0][0]), fabsf(rv3d->winmat[1][1]));
- }
- const float depth_ofs = bglPolygonOffsetCalc((float *)winmat, viewdist, 1.0f);
-
- DRWPass *pass = DRW_pass_create("Edit Mesh Face Overlay Pass", DRW_STATE_WRITE_COLOR | statemod);
-
DRWShadingGroup *grp;
GPUShader *vert_sh = sh_data->overlay_vert;
@@ -347,70 +361,67 @@ static DRWPass *edit_mesh_create_overlay_pass(float *face_alpha,
GPUShader *facedot_sh = sh_data->overlay_facedot;
/* Faces */
- if (select_face) {
- grp = *r_facedot_shgrp = DRW_shgroup_create(facedot_sh, pass);
- DRW_shgroup_uniform_block(grp, "globalsBlock", G_draw.block_ubo);
- DRW_shgroup_state_enable(grp, DRW_STATE_WRITE_DEPTH);
- if (rv3d->rflag & RV3D_CLIPPING) {
- DRW_shgroup_world_clip_planes_from_rv3d(grp, rv3d);
- }
- }
-
- grp = *r_face_shgrp = DRW_shgroup_create(face_sh, pass);
+ passes->faces = DRW_pass_create("Edit Mesh Faces", DRW_STATE_WRITE_COLOR | statemod);
+ grp = shgrps->faces = DRW_shgroup_create(face_sh, passes->faces);
DRW_shgroup_uniform_block(grp, "globalsBlock", G_draw.block_ubo);
- DRW_shgroup_uniform_float(grp, "faceAlphaMod", face_alpha, 1);
+ DRW_shgroup_uniform_float_copy(grp, "faceAlphaMod", face_alpha);
DRW_shgroup_uniform_ivec4(grp, "dataMask", data_mask, 1);
- DRW_shgroup_uniform_float_copy(grp, "ofs", 0.0f);
DRW_shgroup_uniform_bool_copy(grp, "selectFaces", select_face);
if (rv3d->rflag & RV3D_CLIPPING) {
- DRW_shgroup_world_clip_planes_from_rv3d(grp, rv3d);
+ DRW_shgroup_state_enable(grp, DRW_STATE_CLIP_PLANES);
}
/* Cage geom needs to be offseted to avoid Z-fighting. */
- grp = *r_face_cage_shgrp = DRW_shgroup_create_sub(*r_face_shgrp);
- DRW_shgroup_state_enable(grp, DRW_STATE_OFFSET_NEGATIVE);
+ passes->faces_cage = DRW_pass_create("Edit Mesh Faces Cage", DRW_STATE_WRITE_COLOR | statemod);
+ grp = shgrps->faces_cage = DRW_shgroup_create(face_sh, passes->faces_cage);
+ DRW_shgroup_uniform_block(grp, "globalsBlock", G_draw.block_ubo);
+ DRW_shgroup_uniform_float_copy(grp, "faceAlphaMod", face_alpha);
+ DRW_shgroup_uniform_ivec4(grp, "dataMask", data_mask, 1);
+ DRW_shgroup_uniform_bool_copy(grp, "selectFaces", select_face);
+ if (rv3d->rflag & RV3D_CLIPPING) {
+ DRW_shgroup_state_enable(grp, DRW_STATE_CLIP_PLANES);
+ }
/* Edges */
- grp = *r_edge_shgrp = DRW_shgroup_create(edge_sh, pass);
+ /* Change first vertex convention to match blender loop structure. */
+ passes->edges = DRW_pass_create(
+ "Edit Mesh Edges", DRW_STATE_WRITE_COLOR | DRW_STATE_FIRST_VERTEX_CONVENTION | statemod);
+ grp = shgrps->edges = DRW_shgroup_create(edge_sh, passes->edges);
DRW_shgroup_uniform_block(grp, "globalsBlock", G_draw.block_ubo);
DRW_shgroup_uniform_vec2(grp, "viewportSize", DRW_viewport_size_get(), 1);
DRW_shgroup_uniform_vec2(grp, "viewportSizeInv", DRW_viewport_invert_size_get(), 1);
DRW_shgroup_uniform_ivec4(grp, "dataMask", data_mask, 1);
- DRW_shgroup_uniform_bool_copy(grp, "doEdges", do_edges);
- DRW_shgroup_uniform_float_copy(grp, "ofs", depth_ofs);
- DRW_shgroup_uniform_bool_copy(grp, "selectEdges", select_edge);
-
- DRW_shgroup_state_enable(grp, DRW_STATE_OFFSET_NEGATIVE);
- /* To match blender loop structure. */
- DRW_shgroup_state_enable(grp, DRW_STATE_FIRST_VERTEX_CONVENTION);
+ DRW_shgroup_uniform_bool_copy(grp, "selectEdges", do_edges || select_edge);
if (rv3d->rflag & RV3D_CLIPPING) {
- DRW_shgroup_world_clip_planes_from_rv3d(grp, rv3d);
+ DRW_shgroup_state_enable(grp, DRW_STATE_CLIP_PLANES);
}
/* Verts */
+ passes->verts = DRW_pass_create("Edit Mesh Verts",
+ (DRW_STATE_WRITE_COLOR | statemod) & ~DRW_STATE_BLEND);
if (select_vert) {
- grp = *r_vert_shgrp = DRW_shgroup_create(vert_sh, pass);
+ grp = shgrps->verts = DRW_shgroup_create(vert_sh, passes->verts);
DRW_shgroup_uniform_block(grp, "globalsBlock", G_draw.block_ubo);
DRW_shgroup_uniform_vec2(grp, "viewportSize", DRW_viewport_size_get(), 1);
- DRW_shgroup_uniform_float_copy(grp, "ofs", depth_ofs * 1.5f);
- DRW_shgroup_state_enable(grp, DRW_STATE_OFFSET_NEGATIVE | DRW_STATE_WRITE_DEPTH);
- DRW_shgroup_state_disable(grp, DRW_STATE_BLEND);
if (rv3d->rflag & RV3D_CLIPPING) {
- DRW_shgroup_world_clip_planes_from_rv3d(grp, rv3d);
+ DRW_shgroup_state_enable(grp, DRW_STATE_CLIP_PLANES);
+ }
+ }
+ if (select_face) {
+ grp = shgrps->facedots = DRW_shgroup_create(facedot_sh, passes->verts);
+ DRW_shgroup_uniform_block(grp, "globalsBlock", G_draw.block_ubo);
+ DRW_shgroup_state_enable(grp, DRW_STATE_WRITE_DEPTH);
+ if (rv3d->rflag & RV3D_CLIPPING) {
+ DRW_shgroup_state_enable(grp, DRW_STATE_CLIP_PLANES);
}
}
-
- return pass;
}
-static float backwire_opacity;
-static float face_mod;
-static float size_normal;
-
static void EDIT_MESH_cache_init(void *vedata)
{
EDIT_MESH_PassList *psl = ((EDIT_MESH_Data *)vedata)->psl;
EDIT_MESH_StorageList *stl = ((EDIT_MESH_Data *)vedata)->stl;
+ EDIT_MESH_PrivateData *g_data = stl->g_data;
DefaultTextureList *dtxl = DRW_viewport_texture_list_get();
const DRWContextState *draw_ctx = DRW_context_state_get();
@@ -419,70 +430,70 @@ static void EDIT_MESH_cache_init(void *vedata)
Scene *scene = draw_ctx->scene;
ToolSettings *tsettings = scene->toolsettings;
EDIT_MESH_Shaders *sh_data = &e_data.sh_data[draw_ctx->sh_cfg];
- static float zero = 0.0f;
- if (!stl->g_data) {
- /* Alloc transient pointers */
- stl->g_data = MEM_mallocN(sizeof(*stl->g_data), __func__);
- }
- stl->g_data->ghost_ob = 0;
- stl->g_data->edit_ob = 0;
- stl->g_data->do_faces = true;
- stl->g_data->do_edges = true;
+ bool do_occlude_wire = (v3d->overlay.edit_flag & V3D_OVERLAY_EDIT_OCCLUDE_WIRE) != 0;
+
+ g_data->ghost_ob = 0;
+ g_data->edit_ob = 0;
+ g_data->do_faces = true;
+ g_data->do_edges = true;
- stl->g_data->do_zbufclip = XRAY_FLAG_ENABLED(v3d);
+ g_data->do_zbufclip = XRAY_FLAG_ENABLED(v3d);
- stl->g_data->data_mask[0] = 0xFF; /* Face Flag */
- stl->g_data->data_mask[1] = 0xFF; /* Edge Flag */
- stl->g_data->data_mask[2] = 0xFF; /* Crease */
- stl->g_data->data_mask[3] = 0xFF; /* BWeight */
+ g_data->data_mask[0] = 0xFF; /* Face Flag */
+ g_data->data_mask[1] = 0xFF; /* Edge Flag */
+ g_data->data_mask[2] = 0xFF; /* Crease */
+ g_data->data_mask[3] = 0xFF; /* BWeight */
if (draw_ctx->object_edit->type == OB_MESH) {
if (BKE_object_is_in_editmode(draw_ctx->object_edit)) {
if ((v3d->overlay.edit_flag & V3D_OVERLAY_EDIT_FREESTYLE_FACE) == 0) {
- stl->g_data->data_mask[0] &= ~VFLAG_FACE_FREESTYLE;
+ g_data->data_mask[0] &= ~VFLAG_FACE_FREESTYLE;
}
if ((v3d->overlay.edit_flag & V3D_OVERLAY_EDIT_FACES) == 0) {
- stl->g_data->data_mask[0] &= ~(VFLAG_FACE_SELECTED & VFLAG_FACE_FREESTYLE);
- stl->g_data->do_faces = false;
- stl->g_data->do_zbufclip = false;
+ g_data->data_mask[0] &= ~(VFLAG_FACE_SELECTED & VFLAG_FACE_FREESTYLE);
+ g_data->do_faces = false;
+ g_data->do_zbufclip = false;
}
if ((v3d->overlay.edit_flag & V3D_OVERLAY_EDIT_SEAMS) == 0) {
- stl->g_data->data_mask[1] &= ~VFLAG_EDGE_SEAM;
+ g_data->data_mask[1] &= ~VFLAG_EDGE_SEAM;
}
if ((v3d->overlay.edit_flag & V3D_OVERLAY_EDIT_SHARP) == 0) {
- stl->g_data->data_mask[1] &= ~VFLAG_EDGE_SHARP;
+ g_data->data_mask[1] &= ~VFLAG_EDGE_SHARP;
}
if ((v3d->overlay.edit_flag & V3D_OVERLAY_EDIT_FREESTYLE_EDGE) == 0) {
- stl->g_data->data_mask[1] &= ~VFLAG_EDGE_FREESTYLE;
+ g_data->data_mask[1] &= ~VFLAG_EDGE_FREESTYLE;
}
if ((v3d->overlay.edit_flag & V3D_OVERLAY_EDIT_EDGES) == 0) {
if ((tsettings->selectmode & SCE_SELECT_EDGE) == 0) {
- stl->g_data->data_mask[1] &= ~(VFLAG_EDGE_ACTIVE & VFLAG_EDGE_SELECTED);
- stl->g_data->do_edges = false;
+ g_data->do_edges = false;
}
}
if ((v3d->overlay.edit_flag & V3D_OVERLAY_EDIT_CREASES) == 0) {
- stl->g_data->data_mask[2] = 0x0;
+ g_data->data_mask[2] = 0x0;
}
if ((v3d->overlay.edit_flag & V3D_OVERLAY_EDIT_BWEIGHTS) == 0) {
- stl->g_data->data_mask[3] = 0x0;
+ g_data->data_mask[3] = 0x0;
}
}
}
+ float backwire_opacity = v3d->overlay.backwire_opacity;
+ float size_normal = v3d->overlay.normals_length;
+ float face_mod = (do_occlude_wire || !g_data->do_faces) ? 0.0f : 1.0f;
+
{
psl->weight_faces = DRW_pass_create(
"Weight Pass", DRW_STATE_WRITE_COLOR | DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_LESS_EQUAL);
- stl->g_data->fweights_shgrp = DRW_shgroup_create(sh_data->weight_face, psl->weight_faces);
+ g_data->fweights_shgrp = DRW_shgroup_create(sh_data->weight_face, psl->weight_faces);
static float alpha = 1.0f;
- DRW_shgroup_uniform_float(stl->g_data->fweights_shgrp, "opacity", &alpha, 1);
- DRW_shgroup_uniform_texture(stl->g_data->fweights_shgrp, "colorramp", G_draw.weight_ramp);
- DRW_shgroup_uniform_block(stl->g_data->fweights_shgrp, "globalsBlock", G_draw.block_ubo);
+ DRW_shgroup_uniform_float(g_data->fweights_shgrp, "opacity", &alpha, 1);
+ DRW_shgroup_uniform_texture(g_data->fweights_shgrp, "colorramp", G_draw.weight_ramp);
+ DRW_shgroup_uniform_block(g_data->fweights_shgrp, "globalsBlock", G_draw.block_ubo);
if (rv3d->rflag & RV3D_CLIPPING) {
- DRW_shgroup_world_clip_planes_from_rv3d(stl->g_data->fweights_shgrp, rv3d);
+ DRW_shgroup_state_enable(g_data->fweights_shgrp, DRW_STATE_CLIP_PLANES);
}
}
@@ -491,19 +502,18 @@ static void EDIT_MESH_cache_init(void *vedata)
psl->depth_hidden_wire = DRW_pass_create("Depth Pass Hidden Wire",
DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_LESS_EQUAL |
DRW_STATE_CULL_BACK);
- stl->g_data->depth_shgrp_hidden_wire = DRW_shgroup_create(sh_data->depth,
- psl->depth_hidden_wire);
+ g_data->depth_shgrp_hidden_wire = DRW_shgroup_create(sh_data->depth, psl->depth_hidden_wire);
if (rv3d->rflag & RV3D_CLIPPING) {
- DRW_shgroup_world_clip_planes_from_rv3d(stl->g_data->depth_shgrp_hidden_wire, rv3d);
+ DRW_shgroup_state_enable(g_data->depth_shgrp_hidden_wire, DRW_STATE_CLIP_PLANES);
}
psl->depth_hidden_wire_in_front = DRW_pass_create(
"Depth Pass Hidden Wire In Front",
DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_LESS_EQUAL | DRW_STATE_CULL_BACK);
- stl->g_data->depth_shgrp_hidden_wire_in_front = DRW_shgroup_create(
- sh_data->depth, psl->depth_hidden_wire_in_front);
+ g_data->depth_shgrp_hidden_wire_in_front = DRW_shgroup_create(sh_data->depth,
+ psl->depth_hidden_wire_in_front);
if (rv3d->rflag & RV3D_CLIPPING) {
- DRW_shgroup_world_clip_planes_from_rv3d(stl->g_data->depth_shgrp_hidden_wire_in_front, rv3d);
+ DRW_shgroup_state_enable(g_data->depth_shgrp_hidden_wire_in_front, DRW_STATE_CLIP_PLANES);
}
}
@@ -513,25 +523,25 @@ static void EDIT_MESH_cache_init(void *vedata)
DRW_STATE_WRITE_DEPTH | DRW_STATE_WRITE_COLOR |
DRW_STATE_DEPTH_LESS_EQUAL);
- stl->g_data->fnormals_shgrp = DRW_shgroup_create(sh_data->normals_face, psl->normals);
- DRW_shgroup_uniform_float(stl->g_data->fnormals_shgrp, "normalSize", &size_normal, 1);
- DRW_shgroup_uniform_vec4(stl->g_data->fnormals_shgrp, "color", G_draw.block.colorNormal, 1);
+ g_data->fnormals_shgrp = DRW_shgroup_create(sh_data->normals_face, psl->normals);
+ DRW_shgroup_uniform_float(g_data->fnormals_shgrp, "normalSize", &size_normal, 1);
+ DRW_shgroup_uniform_vec4(g_data->fnormals_shgrp, "color", G_draw.block.colorNormal, 1);
if (rv3d->rflag & RV3D_CLIPPING) {
- DRW_shgroup_world_clip_planes_from_rv3d(stl->g_data->fnormals_shgrp, rv3d);
+ DRW_shgroup_state_enable(g_data->fnormals_shgrp, DRW_STATE_CLIP_PLANES);
}
- stl->g_data->vnormals_shgrp = DRW_shgroup_create(sh_data->normals, psl->normals);
- DRW_shgroup_uniform_float(stl->g_data->vnormals_shgrp, "normalSize", &size_normal, 1);
- DRW_shgroup_uniform_vec4(stl->g_data->vnormals_shgrp, "color", G_draw.block.colorVNormal, 1);
+ g_data->vnormals_shgrp = DRW_shgroup_create(sh_data->normals, psl->normals);
+ DRW_shgroup_uniform_float(g_data->vnormals_shgrp, "normalSize", &size_normal, 1);
+ DRW_shgroup_uniform_vec4(g_data->vnormals_shgrp, "color", G_draw.block.colorVNormal, 1);
if (rv3d->rflag & RV3D_CLIPPING) {
- DRW_shgroup_world_clip_planes_from_rv3d(stl->g_data->vnormals_shgrp, rv3d);
+ DRW_shgroup_state_enable(g_data->vnormals_shgrp, DRW_STATE_CLIP_PLANES);
}
- stl->g_data->lnormals_shgrp = DRW_shgroup_create(sh_data->normals_loop, psl->normals);
- DRW_shgroup_uniform_float(stl->g_data->lnormals_shgrp, "normalSize", &size_normal, 1);
- DRW_shgroup_uniform_vec4(stl->g_data->lnormals_shgrp, "color", G_draw.block.colorLNormal, 1);
+ g_data->lnormals_shgrp = DRW_shgroup_create(sh_data->normals_loop, psl->normals);
+ DRW_shgroup_uniform_float(g_data->lnormals_shgrp, "normalSize", &size_normal, 1);
+ DRW_shgroup_uniform_vec4(g_data->lnormals_shgrp, "color", G_draw.block.colorLNormal, 1);
if (rv3d->rflag & RV3D_CLIPPING) {
- DRW_shgroup_world_clip_planes_from_rv3d(stl->g_data->lnormals_shgrp, rv3d);
+ DRW_shgroup_state_enable(g_data->lnormals_shgrp, DRW_STATE_CLIP_PLANES);
}
}
@@ -540,63 +550,66 @@ static void EDIT_MESH_cache_init(void *vedata)
DRWState state = DRW_STATE_WRITE_COLOR | DRW_STATE_DEPTH_LESS_EQUAL | DRW_STATE_BLEND;
psl->mesh_analysis_pass = DRW_pass_create("Mesh Analysis", state);
const bool is_vertex_color = scene->toolsettings->statvis.type == SCE_STATVIS_SHARP;
- stl->g_data->mesh_analysis_shgrp = DRW_shgroup_create(
+ g_data->mesh_analysis_shgrp = DRW_shgroup_create(
is_vertex_color ? sh_data->mesh_analysis_vertex : sh_data->mesh_analysis_face,
psl->mesh_analysis_pass);
if (rv3d->rflag & RV3D_CLIPPING) {
- DRW_shgroup_world_clip_planes_from_rv3d(stl->g_data->mesh_analysis_shgrp, rv3d);
+ DRW_shgroup_state_enable(g_data->mesh_analysis_shgrp, DRW_STATE_CLIP_PLANES);
}
}
/* For in front option */
- psl->edit_face_overlay_in_front = edit_mesh_create_overlay_pass(
- &face_mod,
- stl->g_data->data_mask,
- stl->g_data->do_edges,
- DRW_STATE_DEPTH_LESS_EQUAL | DRW_STATE_BLEND,
- &stl->g_data->face_shgrp_in_front,
- &stl->g_data->face_cage_shgrp_in_front,
- &stl->g_data->facedot_shgrp_in_front,
- &stl->g_data->edge_shgrp_in_front,
- &stl->g_data->vert_shgrp_in_front);
-
- if (!stl->g_data->do_zbufclip) {
- psl->edit_face_overlay = edit_mesh_create_overlay_pass(&face_mod,
- stl->g_data->data_mask,
- stl->g_data->do_edges,
- DRW_STATE_DEPTH_LESS_EQUAL |
- DRW_STATE_BLEND,
- &stl->g_data->face_shgrp,
- &stl->g_data->face_cage_shgrp,
- &stl->g_data->facedot_shgrp,
- &stl->g_data->edge_shgrp,
- &stl->g_data->vert_shgrp);
+ edit_mesh_create_overlay_passes(face_mod,
+ g_data->data_mask,
+ g_data->do_edges,
+ DRW_STATE_DEPTH_LESS_EQUAL | DRW_STATE_BLEND,
+ &psl->edit_passes_in_front,
+ &g_data->edit_in_front_shgrps);
+
+ if (!g_data->do_zbufclip) {
+ edit_mesh_create_overlay_passes(face_mod,
+ g_data->data_mask,
+ g_data->do_edges,
+ DRW_STATE_DEPTH_LESS_EQUAL | DRW_STATE_BLEND,
+ &psl->edit_passes,
+ &g_data->edit_shgrps);
}
else {
/* We render all wires with depth and opaque to a new fbo and blend the result based on depth
* values */
- psl->edit_face_occluded = edit_mesh_create_overlay_pass(&zero,
- stl->g_data->data_mask,
- stl->g_data->do_edges,
- DRW_STATE_DEPTH_LESS_EQUAL |
- DRW_STATE_WRITE_DEPTH,
- &stl->g_data->face_shgrp,
- &stl->g_data->face_cage_shgrp,
- &stl->g_data->facedot_shgrp,
- &stl->g_data->edge_shgrp,
- &stl->g_data->vert_shgrp);
-
- /* however we loose the front faces value (because we need the depth of occluded wires and
- * faces are alpha blended ) so we recover them in a new pass. */
- psl->facefill_occlude = DRW_pass_create(
- "Front Face Color", DRW_STATE_WRITE_COLOR | DRW_STATE_DEPTH_LESS_EQUAL | DRW_STATE_BLEND);
- stl->g_data->facefill_occluded_shgrp = DRW_shgroup_create(sh_data->overlay_facefill,
- psl->facefill_occlude);
- DRW_shgroup_uniform_block(
- stl->g_data->facefill_occluded_shgrp, "globalsBlock", G_draw.block_ubo);
- DRW_shgroup_uniform_ivec4(
- stl->g_data->facefill_occluded_shgrp, "dataMask", stl->g_data->data_mask, 1);
- if (rv3d->rflag & RV3D_CLIPPING) {
- DRW_shgroup_world_clip_planes_from_rv3d(stl->g_data->facefill_occluded_shgrp, rv3d);
+ edit_mesh_create_overlay_passes(0.0f,
+ g_data->data_mask,
+ g_data->do_edges,
+ DRW_STATE_DEPTH_LESS_EQUAL | DRW_STATE_WRITE_DEPTH,
+ &psl->edit_passes,
+ &g_data->edit_shgrps);
+
+ DRWState state = DRW_STATE_WRITE_COLOR | DRW_STATE_DEPTH_LESS_EQUAL | DRW_STATE_BLEND;
+ psl->facefill_occlude = DRW_pass_create("Front Face Color", state);
+ psl->facefill_occlude_cage = DRW_pass_create("Front Face Cage Color", state);
+
+ if (g_data->do_faces) {
+ DRWShadingGroup *shgrp;
+
+ /* however we loose the front faces value (because we need the depth of occluded wires and
+ * faces are alpha blended ) so we recover them in a new pass. */
+ shgrp = g_data->facefill_occluded_shgrp = DRW_shgroup_create(sh_data->overlay_facefill,
+ psl->facefill_occlude);
+ DRW_shgroup_uniform_block(shgrp, "globalsBlock", G_draw.block_ubo);
+ DRW_shgroup_uniform_ivec4(shgrp, "dataMask", g_data->data_mask, 1);
+ if (rv3d->rflag & RV3D_CLIPPING) {
+ DRW_shgroup_state_enable(shgrp, DRW_STATE_CLIP_PLANES);
+ }
+
+ shgrp = g_data->facefill_occluded_cage_shgrp = DRW_shgroup_create(
+ sh_data->overlay_facefill, psl->facefill_occlude_cage);
+ DRW_shgroup_uniform_block(shgrp, "globalsBlock", G_draw.block_ubo);
+ DRW_shgroup_uniform_ivec4(shgrp, "dataMask", g_data->data_mask, 1);
+ if (rv3d->rflag & RV3D_CLIPPING) {
+ DRW_shgroup_state_enable(shgrp, DRW_STATE_CLIP_PLANES);
+ }
+ }
+ else {
+ g_data->facefill_occluded_shgrp = NULL;
}
/* we need a full screen pass to combine the result */
@@ -606,11 +619,26 @@ static void EDIT_MESH_cache_init(void *vedata)
DRW_STATE_WRITE_COLOR | DRW_STATE_BLEND);
DRWShadingGroup *mix_shgrp = DRW_shgroup_create(sh_data->overlay_mix, psl->mix_occlude);
DRW_shgroup_call(mix_shgrp, quad, NULL);
- DRW_shgroup_uniform_float(mix_shgrp, "alpha", &backwire_opacity, 1);
+ DRW_shgroup_uniform_float_copy(mix_shgrp, "alpha", backwire_opacity);
DRW_shgroup_uniform_texture_ref(mix_shgrp, "wireColor", &e_data.occlude_wire_color_tx);
DRW_shgroup_uniform_texture_ref(mix_shgrp, "wireDepth", &e_data.occlude_wire_depth_tx);
DRW_shgroup_uniform_texture_ref(mix_shgrp, "sceneDepth", &dtxl->depth);
}
+
+ bool show_face_dots = (v3d->overlay.edit_flag & V3D_OVERLAY_EDIT_FACE_DOT) != 0;
+
+ if (g_data->do_faces == false && g_data->do_edges == false &&
+ (tsettings->selectmode & SCE_SELECT_FACE)) {
+ /* Force display of face centers in this case because that's
+ * the only way to see if a face is selected. */
+ show_face_dots = true;
+ }
+
+ /* HACK: set pointers to NULL even if generated. */
+ if (!show_face_dots) {
+ g_data->edit_shgrps.facedots = NULL;
+ g_data->edit_in_front_shgrps.facedots = NULL;
+ }
}
static void edit_mesh_add_ob_to_pass(Scene *scene,
@@ -619,8 +647,7 @@ static void edit_mesh_add_ob_to_pass(Scene *scene,
DRWShadingGroup *edge_shgrp,
DRWShadingGroup *face_shgrp,
DRWShadingGroup *face_cage_shgrp,
- DRWShadingGroup *facedot_shgrp,
- DRWShadingGroup *facefill_shgrp)
+ DRWShadingGroup *facedot_shgrp)
{
struct GPUBatch *geom_tris, *geom_verts, *geom_edges, *geom_fcenter;
ToolSettings *tsettings = scene->toolsettings;
@@ -634,7 +661,6 @@ static void edit_mesh_add_ob_to_pass(Scene *scene,
}
face_shgrp = (has_edit_mesh_cage) ? face_cage_shgrp : face_shgrp;
- face_shgrp = (facefill_shgrp != NULL) ? facefill_shgrp : face_shgrp;
geom_tris = DRW_mesh_batch_cache_get_edit_triangles(ob->data);
geom_edges = DRW_mesh_batch_cache_get_edit_edges(ob->data);
@@ -659,7 +685,6 @@ static void EDIT_MESH_cache_populate(void *vedata, Object *ob)
const DRWContextState *draw_ctx = DRW_context_state_get();
View3D *v3d = draw_ctx->v3d;
Scene *scene = draw_ctx->scene;
- ToolSettings *tsettings = scene->toolsettings;
struct GPUBatch *geom;
if (ob->type == OB_MESH) {
@@ -672,25 +697,6 @@ static void EDIT_MESH_cache_populate(void *vedata, Object *ob)
bool vnormals_do = (v3d->overlay.edit_flag & V3D_OVERLAY_EDIT_VERT_NORMALS) != 0;
bool lnormals_do = (v3d->overlay.edit_flag & V3D_OVERLAY_EDIT_LOOP_NORMALS) != 0;
- bool show_face_dots = (v3d->overlay.edit_flag & V3D_OVERLAY_EDIT_FACE_DOT) != 0;
-
- if (g_data->do_faces == false && g_data->do_edges == false &&
- (tsettings->selectmode & SCE_SELECT_FACE)) {
- /* Force display of face centers in this case because that's
- * the only way to see if a face is selected. */
- show_face_dots = true;
- }
-
- /* Updating uniform */
- backwire_opacity = v3d->overlay.backwire_opacity;
- size_normal = v3d->overlay.normals_length;
-
- face_mod = (do_occlude_wire) ? 0.0f : 1.0f;
-
- if (!g_data->do_faces) {
- face_mod = 0.0f;
- }
-
if (do_show_weight) {
geom = DRW_cache_mesh_surface_weights_get(ob);
DRW_shgroup_call(g_data->fweights_shgrp, geom, ob->obmat);
@@ -733,32 +739,29 @@ static void EDIT_MESH_cache_populate(void *vedata, Object *ob)
if (g_data->do_zbufclip) {
edit_mesh_add_ob_to_pass(scene,
ob,
- g_data->vert_shgrp,
- g_data->edge_shgrp,
- g_data->face_shgrp,
- g_data->face_cage_shgrp,
- g_data->facedot_shgrp,
- (g_data->do_faces) ? g_data->facefill_occluded_shgrp : NULL);
+ g_data->edit_shgrps.verts,
+ g_data->edit_shgrps.edges,
+ g_data->facefill_occluded_shgrp,
+ g_data->facefill_occluded_cage_shgrp,
+ g_data->edit_shgrps.facedots);
}
else if (do_in_front) {
edit_mesh_add_ob_to_pass(scene,
ob,
- g_data->vert_shgrp_in_front,
- g_data->edge_shgrp_in_front,
- g_data->face_shgrp_in_front,
- g_data->face_cage_shgrp_in_front,
- (show_face_dots) ? g_data->facedot_shgrp_in_front : NULL,
- NULL);
+ g_data->edit_in_front_shgrps.verts,
+ g_data->edit_in_front_shgrps.edges,
+ g_data->edit_in_front_shgrps.faces,
+ g_data->edit_in_front_shgrps.faces_cage,
+ g_data->edit_in_front_shgrps.facedots);
}
else {
edit_mesh_add_ob_to_pass(scene,
ob,
- g_data->vert_shgrp,
- g_data->edge_shgrp,
- g_data->face_shgrp,
- g_data->face_cage_shgrp,
- (show_face_dots) ? g_data->facedot_shgrp : NULL,
- NULL);
+ g_data->edit_shgrps.verts,
+ g_data->edit_shgrps.edges,
+ g_data->edit_shgrps.faces,
+ g_data->edit_shgrps.faces_cage,
+ g_data->edit_shgrps.facedots);
}
g_data->ghost_ob += (ob->dtx & OB_DRAWXRAY) ? 1 : 0;
@@ -776,6 +779,24 @@ static void EDIT_MESH_cache_populate(void *vedata, Object *ob)
}
}
+static void edit_mesh_draw_components(EDIT_MESH_ComponentPassList *passes,
+ EDIT_MESH_PrivateData *g_data)
+{
+ DRW_view_set_active(g_data->view_faces);
+ DRW_draw_pass(passes->faces);
+
+ DRW_view_set_active(g_data->view_faces_cage);
+ DRW_draw_pass(passes->faces_cage);
+
+ DRW_view_set_active(g_data->view_edges);
+ DRW_draw_pass(passes->edges);
+
+ DRW_view_set_active(g_data->view_wires);
+ DRW_draw_pass(passes->verts);
+
+ DRW_view_set_active(NULL);
+}
+
static void EDIT_MESH_draw_scene(void *vedata)
{
EDIT_MESH_PassList *psl = ((EDIT_MESH_Data *)vedata)->psl;
@@ -794,13 +815,20 @@ static void EDIT_MESH_draw_scene(void *vedata)
DRW_draw_pass(psl->depth_hidden_wire_in_front);
/* render facefill */
+ DRW_view_set_active(stl->g_data->view_faces);
DRW_draw_pass(psl->facefill_occlude);
+ DRW_view_set_active(stl->g_data->view_faces_cage);
+ DRW_draw_pass(psl->facefill_occlude_cage);
+
+ DRW_view_set_active(NULL);
+
/* Render wires on a separate framebuffer */
GPU_framebuffer_bind(fbl->occlude_wire_fb);
GPU_framebuffer_clear_color_depth(fbl->occlude_wire_fb, clearcol, 1.0f);
DRW_draw_pass(psl->normals);
- DRW_draw_pass(psl->edit_face_occluded);
+
+ edit_mesh_draw_components(&psl->edit_passes, stl->g_data);
/* Combine with scene buffer */
GPU_framebuffer_bind(dfbl->color_only_fb);
@@ -811,7 +839,7 @@ static void EDIT_MESH_draw_scene(void *vedata)
View3D *v3d = draw_ctx->v3d;
DRW_draw_pass(psl->normals);
- DRW_draw_pass(psl->edit_face_overlay);
+ edit_mesh_draw_components(&psl->edit_passes, stl->g_data);
if (v3d->shading.type == OB_SOLID && !XRAY_FLAG_ENABLED(v3d) && stl->g_data->ghost_ob == 1 &&
stl->g_data->edit_ob == 1) {
@@ -822,10 +850,8 @@ static void EDIT_MESH_draw_scene(void *vedata)
}
DRW_draw_pass(psl->depth_hidden_wire_in_front);
- DRW_draw_pass(psl->edit_face_overlay_in_front);
+ edit_mesh_draw_components(&psl->edit_passes_in_front, stl->g_data);
}
-
- DRW_state_clip_planes_reset();
}
static void EDIT_MESH_engine_free(void)
diff --git a/source/blender/draw/modes/edit_metaball_mode.c b/source/blender/draw/modes/edit_metaball_mode.c
index 1dc6bd84fa1..82b1ddbd66d 100644
--- a/source/blender/draw/modes/edit_metaball_mode.c
+++ b/source/blender/draw/modes/edit_metaball_mode.c
@@ -93,14 +93,6 @@ typedef struct EDIT_METABALL_PrivateData {
/* *********** FUNCTIONS *********** */
-static void EDIT_METABALL_engine_init(void *UNUSED(vedata))
-{
- const DRWContextState *draw_ctx = DRW_context_state_get();
- if (draw_ctx->sh_cfg == GPU_SHADER_CFG_CLIPPED) {
- DRW_state_clip_planes_set_from_rv3d(draw_ctx->rv3d);
- }
-}
-
/* Here init all passes and shading groups
* Assume that all Passes are NULL */
static void EDIT_METABALL_cache_init(void *vedata)
@@ -209,11 +201,6 @@ static void EDIT_METABALL_draw_scene(void *vedata)
EDIT_METABALL_PassList *psl = ((EDIT_METABALL_Data *)vedata)->psl;
/* render passes on default framebuffer. */
DRW_draw_pass(psl->pass);
-
- /* If you changed framebuffer, double check you rebind
- * the default one with its textures attached before finishing */
-
- DRW_state_clip_planes_reset();
}
/* Cleanup when destroying the engine.
@@ -232,7 +219,7 @@ DrawEngineType draw_engine_edit_metaball_type = {
NULL,
N_("EditMetaballMode"),
&EDIT_METABALL_data_size,
- &EDIT_METABALL_engine_init,
+ NULL,
&EDIT_METABALL_engine_free,
&EDIT_METABALL_cache_init,
&EDIT_METABALL_cache_populate,
diff --git a/source/blender/draw/modes/object_mode.c b/source/blender/draw/modes/object_mode.c
index 3407aeee302..58bfa2f23cc 100644
--- a/source/blender/draw/modes/object_mode.c
+++ b/source/blender/draw/modes/object_mode.c
@@ -531,7 +531,7 @@ static void OBJECT_engine_init(void *vedata)
{
/* Grid precompute */
- float invviewmat[4][4], invwinmat[4][4];
+ float viewinv[4][4], wininv[4][4];
float viewmat[4][4], winmat[4][4];
View3D *v3d = draw_ctx->v3d;
Scene *scene = draw_ctx->scene;
@@ -546,10 +546,10 @@ static void OBJECT_engine_init(void *vedata)
const bool show_ortho_grid = (v3d->gridflag & V3D_SHOW_ORTHO_GRID) != 0;
e_data.draw_grid = show_axis_x || show_axis_y || show_axis_z || show_floor;
- DRW_viewport_matrix_get(winmat, DRW_MAT_WIN);
- DRW_viewport_matrix_get(viewmat, DRW_MAT_VIEW);
- DRW_viewport_matrix_get(invwinmat, DRW_MAT_WININV);
- DRW_viewport_matrix_get(invviewmat, DRW_MAT_VIEWINV);
+ DRW_view_winmat_get(NULL, winmat, false);
+ DRW_view_winmat_get(NULL, wininv, true);
+ DRW_view_viewmat_get(NULL, viewmat, false);
+ DRW_view_viewmat_get(NULL, viewinv, true);
/* if perps */
if (winmat[3][3] == 0.0f) {
@@ -561,7 +561,7 @@ static void OBJECT_engine_init(void *vedata)
/* convert the view vectors to view space */
for (int i = 0; i < 2; i++) {
- mul_m4_v4(invwinmat, viewvecs[i]);
+ mul_m4_v4(wininv, viewvecs[i]);
mul_v3_fl(viewvecs[i], 1.0f / viewvecs[i][2]); /* perspective divide */
}
@@ -623,8 +623,8 @@ static void OBJECT_engine_init(void *vedata)
e_data.zpos_flag = SHOW_AXIS_Z;
float zvec[3], campos[3];
- negate_v3_v3(zvec, invviewmat[2]);
- copy_v3_v3(campos, invviewmat[3]);
+ negate_v3_v3(zvec, viewinv[2]);
+ copy_v3_v3(campos, viewinv[3]);
/* z axis : chose the most facing plane */
if (fabsf(zvec[0]) < fabsf(zvec[1])) {
@@ -708,7 +708,7 @@ static DRWShadingGroup *shgroup_outline(DRWPass *pass,
DRW_shgroup_uniform_int(grp, "baseId", ofs, 1);
if (sh_cfg == GPU_SHADER_CFG_CLIPPED) {
- DRW_shgroup_world_clip_planes_from_rv3d(grp, DRW_context_state_get()->rv3d);
+ DRW_shgroup_state_enable(grp, DRW_STATE_CLIP_PLANES);
}
return grp;
}
@@ -723,7 +723,7 @@ static DRWShadingGroup *shgroup_wire(DRWPass *pass,
DRW_shgroup_uniform_vec4(grp, "color", col, 1);
if (sh_cfg == GPU_SHADER_CFG_CLIPPED) {
- DRW_shgroup_world_clip_planes_from_rv3d(grp, DRW_context_state_get()->rv3d);
+ DRW_shgroup_state_enable(grp, DRW_STATE_CLIP_PLANES);
}
return grp;
}
@@ -739,7 +739,7 @@ static DRWShadingGroup *shgroup_points(DRWPass *pass,
DRW_shgroup_uniform_vec4(grp, "innerColor", G_draw.block.colorEditMeshMiddle, 1);
if (sh_cfg == GPU_SHADER_CFG_CLIPPED) {
- DRW_shgroup_world_clip_planes_from_rv3d(grp, DRW_context_state_get()->rv3d);
+ DRW_shgroup_state_enable(grp, DRW_STATE_CLIP_PLANES);
}
return grp;
}
@@ -1016,7 +1016,7 @@ static void DRW_shgroup_empty_image(OBJECT_Shaders *sh_data,
DRW_shgroup_uniform_vec2(grp, "offset", ob->ima_ofs, 1);
DRW_shgroup_uniform_vec3(grp, "color", color, 1);
if (sh_cfg == GPU_SHADER_CFG_CLIPPED) {
- DRW_shgroup_world_clip_planes_from_rv3d(grp, DRW_context_state_get()->rv3d);
+ DRW_shgroup_state_enable(grp, DRW_STATE_CLIP_PLANES);
}
DRW_shgroup_call(grp, DRW_cache_image_plane_wire_get(), ob->obmat);
}
@@ -1036,7 +1036,7 @@ static void DRW_shgroup_empty_image(OBJECT_Shaders *sh_data,
DRW_shgroup_uniform_vec4(grp, "objectColor", ob->color, 1);
DRW_shgroup_uniform_bool_copy(grp, "useAlphaTest", !use_alpha_blend);
if (sh_cfg == GPU_SHADER_CFG_CLIPPED) {
- DRW_shgroup_world_clip_planes_from_rv3d(grp, DRW_context_state_get()->rv3d);
+ DRW_shgroup_state_enable(grp, DRW_STATE_CLIP_PLANES);
}
DRW_shgroup_call(grp, DRW_cache_image_plane_get(), ob->obmat);
}
@@ -1404,7 +1404,7 @@ static void OBJECT_cache_init(void *vedata)
DRW_shgroup_uniform_vec4(grp, "color", gb->colorLightNoAlpha, 1);
DRW_shgroup_uniform_float(grp, "size", &gb->sizeLightCenter, 1);
if (draw_ctx->sh_cfg == GPU_SHADER_CFG_CLIPPED) {
- DRW_shgroup_world_clip_planes_from_rv3d(grp, DRW_context_state_get()->rv3d);
+ DRW_shgroup_state_enable(grp, DRW_STATE_CLIP_PLANES);
}
sgl->light_center = buffer_dynpoints_uniform_color(grp);
@@ -1492,7 +1492,7 @@ static void OBJECT_cache_init(void *vedata)
DRWShadingGroup *grp_transp = DRW_shgroup_create(sh, sgl->transp_shapes);
if (draw_ctx->sh_cfg == GPU_SHADER_CFG_CLIPPED) {
- DRW_shgroup_world_clip_planes_from_rv3d(grp_transp, DRW_context_state_get()->rv3d);
+ DRW_shgroup_state_enable(grp_transp, DRW_STATE_CLIP_PLANES);
}
DRWShadingGroup *grp_cull_back = DRW_shgroup_create_sub(grp_transp);
@@ -1544,7 +1544,7 @@ static void OBJECT_cache_init(void *vedata)
DRW_shgroup_uniform_vec4(grp, "color", gb->colorActive, 1);
DRW_shgroup_uniform_vec4(grp, "outlineColor", gb->colorOutline, 1);
if (draw_ctx->sh_cfg == GPU_SHADER_CFG_CLIPPED) {
- DRW_shgroup_world_clip_planes_from_rv3d(grp, draw_ctx->rv3d);
+ DRW_shgroup_state_enable(grp, DRW_STATE_CLIP_PLANES);
}
/* TODO find better name. */
stl->g_data->center_active = buffer_dynpoints_uniform_color(grp);
@@ -2134,29 +2134,31 @@ static void DRW_shgroup_camera(OBJECT_ShadingGroupList *sgl, Object *ob, ViewLay
cam->runtime.drw_tria[1][1] = shift[1] + ((1.1f * drawsize * (asp[1] + 0.7f)) * scale[1]);
if (look_through) {
- /* Only draw the frame. */
- float mat[4][4];
- if (is_multiview) {
- const bool is_left = v3d->multiview_eye == STEREO_LEFT_ID;
- const char *view_name = is_left ? STEREO_LEFT_NAME : STEREO_RIGHT_NAME;
- BKE_camera_multiview_model_matrix(&scene->r, ob, view_name, mat);
- const float shiftx = BKE_camera_multiview_shift_x(&scene->r, ob, view_name);
- const float delta_shiftx = shiftx - cam->shiftx;
- const float width = cam->runtime.drw_corners[0][2][0] - cam->runtime.drw_corners[0][0][0];
- for (int i = 0; i < 4; i++) {
- cam->runtime.drw_corners[0][i][0] -= delta_shiftx * width;
+ if (!DRW_state_is_image_render()) {
+ /* Only draw the frame. */
+ float mat[4][4];
+ if (is_multiview) {
+ const bool is_left = v3d->multiview_eye == STEREO_LEFT_ID;
+ const char *view_name = is_left ? STEREO_LEFT_NAME : STEREO_RIGHT_NAME;
+ BKE_camera_multiview_model_matrix(&scene->r, ob, view_name, mat);
+ const float shiftx = BKE_camera_multiview_shift_x(&scene->r, ob, view_name);
+ const float delta_shiftx = shiftx - cam->shiftx;
+ const float width = cam->runtime.drw_corners[0][2][0] - cam->runtime.drw_corners[0][0][0];
+ for (int i = 0; i < 4; i++) {
+ cam->runtime.drw_corners[0][i][0] -= delta_shiftx * width;
+ }
+ }
+ else {
+ copy_m4_m4(mat, ob->obmat);
}
- }
- else {
- copy_m4_m4(mat, ob->obmat);
- }
- DRW_buffer_add_entry(sgl->camera_frame,
- color,
- cam->runtime.drw_corners[0],
- &cam->runtime.drw_depth[0],
- cam->runtime.drw_tria,
- mat);
+ DRW_buffer_add_entry(sgl->camera_frame,
+ color,
+ cam->runtime.drw_corners[0],
+ &cam->runtime.drw_depth[0],
+ cam->runtime.drw_tria,
+ mat);
+ }
}
else {
if (!is_stereo3d_cameras) {
@@ -2437,12 +2439,11 @@ static void DRW_shgroup_volume_extra(OBJECT_ShadingGroupList *sgl,
if (sds->slice_method == MOD_SMOKE_SLICE_AXIS_ALIGNED &&
sds->axis_slice_method == AXIS_SLICE_SINGLE) {
- float invviewmat[4][4];
- DRW_viewport_matrix_get(invviewmat, DRW_MAT_VIEWINV);
+ float viewinv[4][4];
+ DRW_view_viewmat_get(NULL, viewinv, true);
- const int axis = (sds->slice_axis == SLICE_AXIS_AUTO) ?
- axis_dominant_v3_single(invviewmat[2]) :
- sds->slice_axis - 1;
+ const int axis = (sds->slice_axis == SLICE_AXIS_AUTO) ? axis_dominant_v3_single(viewinv[2]) :
+ sds->slice_axis - 1;
slice_axis = axis;
line_count /= sds->res[axis];
}
diff --git a/source/blender/draw/modes/overlay_mode.c b/source/blender/draw/modes/overlay_mode.c
index 36493c5eff5..6e484d3bcc0 100644
--- a/source/blender/draw/modes/overlay_mode.c
+++ b/source/blender/draw/modes/overlay_mode.c
@@ -71,6 +71,7 @@ typedef struct OVERLAY_Data {
typedef struct OVERLAY_PrivateData {
DRWShadingGroup *face_orientation_shgrp;
DRWShadingGroup *face_wires_shgrp;
+ DRWView *view_wires;
BLI_mempool *wire_color_mempool;
View3DOverlay overlay;
float wire_step_param;
@@ -111,10 +112,6 @@ static void overlay_engine_init(void *vedata)
const DRWContextState *draw_ctx = DRW_context_state_get();
OVERLAY_Shaders *sh_data = &e_data.sh_data[draw_ctx->sh_cfg];
- if (draw_ctx->sh_cfg == GPU_SHADER_CFG_CLIPPED) {
- DRW_state_clip_planes_set_from_rv3d(draw_ctx->rv3d);
- }
-
if (!stl->g_data) {
/* Alloc transient pointers */
stl->g_data = MEM_callocN(sizeof(*stl->g_data), __func__);
@@ -167,6 +164,8 @@ static void overlay_engine_init(void *vedata)
});
#endif
}
+
+ stl->g_data->view_wires = DRW_view_create_with_zoffset(draw_ctx->rv3d, 1.0f);
}
static void overlay_cache_init(void *vedata)
@@ -211,19 +210,19 @@ static void overlay_cache_init(void *vedata)
g_data->face_orientation_shgrp = DRW_shgroup_create(sh_data->face_orientation,
psl->face_orientation_pass);
if (rv3d->rflag & RV3D_CLIPPING) {
- DRW_shgroup_world_clip_planes_from_rv3d(g_data->face_orientation_shgrp, rv3d);
+ DRW_shgroup_state_enable(g_data->face_orientation_shgrp, DRW_STATE_CLIP_PLANES);
}
}
{
/* Wireframe */
DRWState state = DRW_STATE_WRITE_COLOR | DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_LESS |
- DRW_STATE_FIRST_VERTEX_CONVENTION | DRW_STATE_OFFSET_NEGATIVE;
+ DRW_STATE_FIRST_VERTEX_CONVENTION;
float wire_size = U.pixelsize * 0.5f;
float winmat[4][4];
float viewdist = rv3d->dist;
- DRW_viewport_matrix_get(winmat, DRW_MAT_WIN);
+ DRW_view_winmat_get(NULL, winmat, false);
/* special exception for ortho camera (viewdist isnt used for perspective cameras) */
if (rv3d->persp == RV3D_CAMOB && rv3d->is_persp == false) {
viewdist = 1.0f / max_ff(fabsf(rv3d->winmat[0][0]), fabsf(rv3d->winmat[1][1]));
@@ -247,7 +246,7 @@ static void overlay_cache_init(void *vedata)
g_data->face_wires_shgrp, "viewportSizeInv", DRW_viewport_invert_size_get(), 1);
}
if (rv3d->rflag & RV3D_CLIPPING) {
- DRW_shgroup_world_clip_planes_from_rv3d(g_data->face_wires_shgrp, rv3d);
+ DRW_shgroup_state_enable(g_data->face_wires_shgrp, DRW_STATE_CLIP_PLANES);
}
g_data->wire_step_param = stl->g_data->overlay.wireframe_threshold - 254.0f / 255.0f;
@@ -493,8 +492,11 @@ static void overlay_draw_scene(void *vedata)
DRW_stats_query_end();
}
+ DRW_view_set_active(stl->g_data->view_wires);
DRW_draw_pass(psl->face_wireframe_pass);
+ DRW_view_set_active(NULL);
+
/* TODO(fclem): find a way to unify the multisample pass together
* (non meshes + armature + wireframe) */
MULTISAMPLE_SYNC_DISABLE(dfbl, dtxl);
diff --git a/source/blender/draw/modes/paint_texture_mode.c b/source/blender/draw/modes/paint_texture_mode.c
index 847d2d2f8aa..a27895f6ce8 100644
--- a/source/blender/draw/modes/paint_texture_mode.c
+++ b/source/blender/draw/modes/paint_texture_mode.c
@@ -128,14 +128,17 @@ typedef struct PAINT_TEXTURE_PrivateData {
/* face-mask */
DRWShadingGroup *lwire_select_shgrp;
DRWShadingGroup *face_select_shgrp;
+
+ DRWView *view_wires;
} PAINT_TEXTURE_PrivateData; /* Transient data */
/* *********** FUNCTIONS *********** */
/* Init Textures, Framebuffers, Storage and Shaders.
* It is called for every frames. */
-static void PAINT_TEXTURE_engine_init(void *UNUSED(vedata))
+static void PAINT_TEXTURE_engine_init(void *vedata)
{
+ PAINT_TEXTURE_StorageList *stl = ((PAINT_TEXTURE_Data *)vedata)->stl;
const DRWContextState *draw_ctx = DRW_context_state_get();
PAINT_TEXTURE_Shaders *sh_data = &e_data.sh_data[draw_ctx->sh_cfg];
@@ -154,6 +157,16 @@ static void PAINT_TEXTURE_engine_init(void *UNUSED(vedata))
.defs = (const char *[]){sh_cfg_data->def, NULL},
});
+ sh_data->image_mask = GPU_shader_create_from_arrays({
+ .vert = (const char *[]){sh_cfg_data->lib,
+ datatoc_common_globals_lib_glsl,
+ datatoc_common_view_lib_glsl,
+ datatoc_paint_texture_vert_glsl,
+ NULL},
+ .frag = (const char *[]){datatoc_paint_texture_frag_glsl, NULL},
+ .defs = (const char *[]){sh_cfg_data->def, "#define TEXTURE_PAINT_MASK\n", NULL},
+ });
+
sh_data->wire_select_overlay = GPU_shader_create_from_arrays({
.vert = (const char *[]){sh_cfg_data->lib,
datatoc_common_globals_lib_glsl,
@@ -175,6 +188,14 @@ static void PAINT_TEXTURE_engine_init(void *UNUSED(vedata))
.defs = (const char *[]){sh_cfg_data->def, NULL},
});
}
+
+ if (!stl->g_data) {
+ /* Alloc transient pointers */
+ stl->g_data = MEM_mallocN(sizeof(*stl->g_data), __func__);
+ stl->g_data->shgroup_image_array = NULL;
+ }
+
+ stl->g_data->view_wires = DRW_view_create_with_zoffset(draw_ctx->rv3d, 1.0f);
}
static DRWShadingGroup *create_texture_paint_shading_group(PAINT_TEXTURE_PassList *psl,
@@ -212,12 +233,6 @@ static void PAINT_TEXTURE_cache_init(void *vedata)
PAINT_TEXTURE_PassList *psl = ((PAINT_TEXTURE_Data *)vedata)->psl;
PAINT_TEXTURE_StorageList *stl = ((PAINT_TEXTURE_Data *)vedata)->stl;
- if (!stl->g_data) {
- /* Alloc transient pointers */
- stl->g_data = MEM_mallocN(sizeof(*stl->g_data), __func__);
- stl->g_data->shgroup_image_array = NULL;
- }
-
const DRWContextState *draw_ctx = DRW_context_state_get();
PAINT_TEXTURE_Shaders *sh_data = &e_data.sh_data[draw_ctx->sh_cfg];
@@ -233,7 +248,7 @@ static void PAINT_TEXTURE_cache_init(void *vedata)
DRW_shgroup_uniform_vec4(shgrp, "color", color, 1);
if (draw_ctx->sh_cfg == GPU_SHADER_CFG_CLIPPED) {
- DRW_shgroup_world_clip_planes_from_rv3d(shgrp, draw_ctx->rv3d);
+ DRW_shgroup_state_enable(shgrp, DRW_STATE_CLIP_PLANES);
}
psl->image_faces = pass;
stl->g_data->shgroup_fallback = shgrp;
@@ -286,31 +301,29 @@ static void PAINT_TEXTURE_cache_init(void *vedata)
/* Face Mask */
{
- DRWPass *pass = DRW_pass_create("Wire Mask Pass",
- (DRW_STATE_WRITE_COLOR | DRW_STATE_WRITE_DEPTH |
- DRW_STATE_DEPTH_LESS_EQUAL | DRW_STATE_OFFSET_NEGATIVE));
+ DRWState state = DRW_STATE_WRITE_COLOR | DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_LESS_EQUAL;
+ DRWPass *pass = DRW_pass_create("Wire Mask Pass", state);
DRWShadingGroup *shgrp = DRW_shgroup_create(sh_data->wire_select_overlay, pass);
DRW_shgroup_uniform_block(shgrp, "globalsBlock", G_draw.block_ubo);
if (draw_ctx->sh_cfg == GPU_SHADER_CFG_CLIPPED) {
- DRW_shgroup_world_clip_planes_from_rv3d(shgrp, draw_ctx->rv3d);
+ DRW_shgroup_state_enable(shgrp, DRW_STATE_CLIP_PLANES);
}
psl->wire_select_overlay = pass;
stl->g_data->lwire_select_shgrp = shgrp;
}
{
-
- DRWPass *pass = DRW_pass_create("Face Mask Pass",
- DRW_STATE_WRITE_COLOR | DRW_STATE_WRITE_DEPTH |
- DRW_STATE_DEPTH_LESS_EQUAL | DRW_STATE_BLEND);
+ DRWState state = DRW_STATE_WRITE_COLOR | DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_LESS_EQUAL |
+ DRW_STATE_BLEND;
+ DRWPass *pass = DRW_pass_create("Face Mask Pass", state);
DRWShadingGroup *shgrp = DRW_shgroup_create(sh_data->face_select_overlay, pass);
static float col[4] = {1.0f, 1.0f, 1.0f, 0.2f};
DRW_shgroup_uniform_vec4(shgrp, "color", col, 1);
if (draw_ctx->sh_cfg == GPU_SHADER_CFG_CLIPPED) {
- DRW_shgroup_world_clip_planes_from_rv3d(shgrp, draw_ctx->rv3d);
+ DRW_shgroup_state_enable(shgrp, DRW_STATE_CLIP_PLANES);
}
psl->face_select_overlay = pass;
stl->g_data->face_select_shgrp = shgrp;
@@ -395,6 +408,7 @@ static void PAINT_TEXTURE_draw_scene(void *vedata)
{
PAINT_TEXTURE_PassList *psl = ((PAINT_TEXTURE_Data *)vedata)->psl;
PAINT_TEXTURE_FramebufferList *fbl = ((PAINT_TEXTURE_Data *)vedata)->fbl;
+ PAINT_TEXTURE_StorageList *stl = ((PAINT_TEXTURE_Data *)vedata)->stl;
/* Default framebuffer and texture */
DefaultFramebufferList *dfbl = DRW_viewport_framebuffer_list_get();
@@ -405,7 +419,11 @@ static void PAINT_TEXTURE_draw_scene(void *vedata)
DRW_draw_pass(psl->image_faces);
DRW_draw_pass(psl->face_select_overlay);
+
+ DRW_view_set_active(stl->g_data->view_wires);
DRW_draw_pass(psl->wire_select_overlay);
+
+ DRW_view_set_active(NULL);
}
/* Cleanup when destroying the engine.
diff --git a/source/blender/draw/modes/paint_vertex_mode.c b/source/blender/draw/modes/paint_vertex_mode.c
index da76573a7e4..051f57fd9e0 100644
--- a/source/blender/draw/modes/paint_vertex_mode.c
+++ b/source/blender/draw/modes/paint_vertex_mode.c
@@ -100,18 +100,17 @@ typedef struct PAINT_VERTEX_PrivateData {
} by_mode[MODE_LEN];
DRWShadingGroup *face_select_shgrp;
DRWShadingGroup *vert_select_shgrp;
+ DRWView *view_wires;
} PAINT_VERTEX_PrivateData; /* Transient data */
/* *********** FUNCTIONS *********** */
-static void PAINT_VERTEX_engine_init(void *UNUSED(vedata))
+static void PAINT_VERTEX_engine_init(void *vedata)
{
+ PAINT_VERTEX_StorageList *stl = ((PAINT_VERTEX_Data *)vedata)->stl;
const DRWContextState *draw_ctx = DRW_context_state_get();
PAINT_VERTEX_Shaders *sh_data = &e_data.sh_data[draw_ctx->sh_cfg];
- if (draw_ctx->sh_cfg == GPU_SHADER_CFG_CLIPPED) {
- DRW_state_clip_planes_set_from_rv3d(draw_ctx->rv3d);
- }
const GPUShaderConfigData *sh_cfg_data = &GPU_shader_cfg_data[draw_ctx->sh_cfg];
if (!sh_data->face_select_overlay) {
@@ -178,6 +177,13 @@ static void PAINT_VERTEX_engine_init(void *UNUSED(vedata))
});
}
}
+
+ if (!stl->g_data) {
+ /* Alloc transient pointers */
+ stl->g_data = MEM_mallocN(sizeof(*stl->g_data), __func__);
+ }
+
+ stl->g_data->view_wires = DRW_view_create_with_zoffset(draw_ctx->rv3d, 1.0f);
}
static void PAINT_VERTEX_cache_init(void *vedata)
@@ -189,11 +195,6 @@ static void PAINT_VERTEX_cache_init(void *vedata)
const RegionView3D *rv3d = draw_ctx->rv3d;
PAINT_VERTEX_Shaders *sh_data = &e_data.sh_data[draw_ctx->sh_cfg];
- if (!stl->g_data) {
- /* Alloc transient pointers */
- stl->g_data = MEM_mallocN(sizeof(*stl->g_data), __func__);
- }
-
/* Vertex color pass */
{
DRWPass *pass = DRW_pass_create(
@@ -202,7 +203,7 @@ static void PAINT_VERTEX_cache_init(void *vedata)
DRW_shgroup_uniform_float_copy(
shgrp, "white_factor", 1.0f - v3d->overlay.vertex_paint_mode_opacity);
if (rv3d->rflag & RV3D_CLIPPING) {
- DRW_shgroup_world_clip_planes_from_rv3d(shgrp, rv3d);
+ DRW_shgroup_state_enable(shgrp, DRW_STATE_CLIP_PLANES);
}
psl->by_mode[VERTEX_MODE].color_faces = pass;
stl->g_data->by_mode[VERTEX_MODE].color_shgrp = shgrp;
@@ -219,21 +220,20 @@ static void PAINT_VERTEX_cache_init(void *vedata)
DRW_shgroup_uniform_texture(shgrp, "colorramp", G_draw.weight_ramp);
DRW_shgroup_uniform_block(shgrp, "globalsBlock", G_draw.block_ubo);
if (rv3d->rflag & RV3D_CLIPPING) {
- DRW_shgroup_world_clip_planes_from_rv3d(shgrp, rv3d);
+ DRW_shgroup_state_enable(shgrp, DRW_STATE_CLIP_PLANES);
}
psl->by_mode[WEIGHT_MODE].color_faces = pass;
stl->g_data->by_mode[WEIGHT_MODE].color_shgrp = shgrp;
}
{
- DRWPass *pass = DRW_pass_create("Wire Pass",
- DRW_STATE_WRITE_COLOR | DRW_STATE_WRITE_DEPTH |
- DRW_STATE_DEPTH_LESS_EQUAL | DRW_STATE_OFFSET_NEGATIVE);
+ DRWPass *pass = DRW_pass_create(
+ "Wire Pass", DRW_STATE_WRITE_COLOR | DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_LESS_EQUAL);
for (int i = 0; i < MODE_LEN; i++) {
DRWShadingGroup *shgrp = DRW_shgroup_create(sh_data->by_mode[i].wire_overlay, pass);
DRW_shgroup_uniform_block(shgrp, "globalsBlock", G_draw.block_ubo);
if (rv3d->rflag & RV3D_CLIPPING) {
- DRW_shgroup_world_clip_planes_from_rv3d(shgrp, rv3d);
+ DRW_shgroup_state_enable(shgrp, DRW_STATE_CLIP_PLANES);
}
stl->g_data->by_mode[i].lwire_shgrp = shgrp;
}
@@ -243,12 +243,12 @@ static void PAINT_VERTEX_cache_init(void *vedata)
{
DRWPass *pass = DRW_pass_create("Wire Mask Pass",
DRW_STATE_WRITE_COLOR | DRW_STATE_WRITE_DEPTH |
- DRW_STATE_DEPTH_LESS_EQUAL | DRW_STATE_OFFSET_NEGATIVE);
+ DRW_STATE_DEPTH_LESS_EQUAL);
for (int i = 0; i < MODE_LEN; i++) {
DRWShadingGroup *shgrp = DRW_shgroup_create(sh_data->by_mode[i].wire_select_overlay, pass);
DRW_shgroup_uniform_block(shgrp, "globalsBlock", G_draw.block_ubo);
if (rv3d->rflag & RV3D_CLIPPING) {
- DRW_shgroup_world_clip_planes_from_rv3d(shgrp, rv3d);
+ DRW_shgroup_state_enable(shgrp, DRW_STATE_CLIP_PLANES);
}
stl->g_data->by_mode[i].lwire_select_shgrp = shgrp;
}
@@ -263,7 +263,7 @@ static void PAINT_VERTEX_cache_init(void *vedata)
DRWShadingGroup *shgrp = DRW_shgroup_create(sh_data->face_select_overlay, pass);
DRW_shgroup_uniform_vec4(shgrp, "color", col, 1);
if (rv3d->rflag & RV3D_CLIPPING) {
- DRW_shgroup_world_clip_planes_from_rv3d(shgrp, rv3d);
+ DRW_shgroup_state_enable(shgrp, DRW_STATE_CLIP_PLANES);
}
psl->face_select_overlay = pass;
stl->g_data->face_select_shgrp = shgrp;
@@ -272,11 +272,11 @@ static void PAINT_VERTEX_cache_init(void *vedata)
{
DRWPass *pass = DRW_pass_create("Vert Mask Pass",
DRW_STATE_WRITE_COLOR | DRW_STATE_WRITE_DEPTH |
- DRW_STATE_DEPTH_LESS_EQUAL | DRW_STATE_OFFSET_NEGATIVE);
+ DRW_STATE_DEPTH_LESS_EQUAL);
DRWShadingGroup *shgrp = DRW_shgroup_create(sh_data->vert_select_overlay, pass);
DRW_shgroup_uniform_block(shgrp, "globalsBlock", G_draw.block_ubo);
if (rv3d->rflag & RV3D_CLIPPING) {
- DRW_shgroup_world_clip_planes_from_rv3d(shgrp, rv3d);
+ DRW_shgroup_state_enable(shgrp, DRW_STATE_CLIP_PLANES);
}
psl->vert_select_overlay = pass;
stl->g_data->vert_select_shgrp = shgrp;
@@ -337,13 +337,18 @@ static void PAINT_VERTEX_cache_populate(void *vedata, Object *ob)
static void PAINT_VERTEX_draw_scene(void *vedata)
{
PAINT_VERTEX_PassList *psl = ((PAINT_VERTEX_Data *)vedata)->psl;
+ PAINT_VERTEX_StorageList *stl = ((PAINT_VERTEX_Data *)vedata)->stl;
for (int i = 0; i < MODE_LEN; i++) {
DRW_draw_pass(psl->by_mode[i].color_faces);
}
+ DRW_draw_pass(psl->face_select_overlay);
+
+ DRW_view_set_active(stl->g_data->view_wires);
DRW_draw_pass(psl->wire_overlay);
DRW_draw_pass(psl->wire_select_overlay);
DRW_draw_pass(psl->vert_select_overlay);
- DRW_draw_pass(psl->face_select_overlay);
+
+ DRW_view_set_active(NULL);
}
static void PAINT_VERTEX_engine_free(void)
diff --git a/source/blender/draw/modes/shaders/common_view_lib.glsl b/source/blender/draw/modes/shaders/common_view_lib.glsl
index 79ac351912d..20a54947db7 100644
--- a/source/blender/draw/modes/shaders/common_view_lib.glsl
+++ b/source/blender/draw/modes/shaders/common_view_lib.glsl
@@ -1,3 +1,5 @@
+#define COMMON_VIEW_LIB
+
/* keep in sync with DRWManager.view_data */
layout(std140) uniform viewBlock
{
@@ -9,11 +11,18 @@ layout(std140) uniform viewBlock
mat4 ProjectionMatrix;
mat4 ProjectionMatrixInverse;
- vec4 CameraTexCoFactors;
+ vec4 clipPlanes[6];
- vec4 clipPlanes[2];
+ /* TODO move it elsewhere. */
+ vec4 CameraTexCoFactors;
};
+#ifdef world_clip_planes_calc_clip_distance
+# undef world_clip_planes_calc_clip_distance
+# define world_clip_planes_calc_clip_distance(p) \
+ _world_clip_planes_calc_clip_distance(p, clipPlanes)
+#endif
+
uniform mat4 ModelMatrix;
uniform mat4 ModelMatrixInverse;
@@ -48,3 +57,11 @@ uniform mat4 ModelMatrixInverse;
#define point_world_to_ndc(p) (ViewProjectionMatrix * vec4(p, 1.0))
#define point_world_to_object(p) ((ModelMatrixInverse * vec4(p, 1.0)).xyz)
#define point_world_to_view(p) ((ViewMatrix * vec4(p, 1.0)).xyz)
+
+/* Due to some shader compiler bug, we somewhat need to access gl_VertexID
+ * to make vertex shaders work. even if it's actually dead code. */
+#ifdef GPU_INTEL
+# define GPU_INTEL_VERTEX_SHADER_WORKAROUND gl_Position.x = float(gl_VertexID);
+#else
+# define GPU_INTEL_VERTEX_SHADER_WORKAROUND
+#endif
diff --git a/source/blender/draw/modes/shaders/edit_curve_overlay_handle_vert.glsl b/source/blender/draw/modes/shaders/edit_curve_overlay_handle_vert.glsl
index 2f3d37a6e73..590c2905be6 100644
--- a/source/blender/draw/modes/shaders/edit_curve_overlay_handle_vert.glsl
+++ b/source/blender/draw/modes/shaders/edit_curve_overlay_handle_vert.glsl
@@ -7,6 +7,8 @@ flat out int vertFlag;
void main()
{
+ GPU_INTEL_VERTEX_SHADER_WORKAROUND
+
vec3 world_pos = point_object_to_world(pos);
gl_Position = point_world_to_ndc(world_pos);
vertFlag = data;
diff --git a/source/blender/draw/modes/shaders/edit_curve_overlay_loosevert_vert.glsl b/source/blender/draw/modes/shaders/edit_curve_overlay_loosevert_vert.glsl
index b1b707b59f4..6eec43d99be 100644
--- a/source/blender/draw/modes/shaders/edit_curve_overlay_loosevert_vert.glsl
+++ b/source/blender/draw/modes/shaders/edit_curve_overlay_loosevert_vert.glsl
@@ -9,6 +9,8 @@ out vec4 finalColor;
void main()
{
+ GPU_INTEL_VERTEX_SHADER_WORKAROUND
+
if ((data & VERT_SELECTED) != 0) {
if ((data & VERT_ACTIVE) != 0) {
finalColor = colorEditMeshActive;
diff --git a/source/blender/draw/modes/shaders/edit_curve_overlay_normals_vert.glsl b/source/blender/draw/modes/shaders/edit_curve_overlay_normals_vert.glsl
index ef60ddbc395..e1d5319ffb9 100644
--- a/source/blender/draw/modes/shaders/edit_curve_overlay_normals_vert.glsl
+++ b/source/blender/draw/modes/shaders/edit_curve_overlay_normals_vert.glsl
@@ -9,6 +9,8 @@ in float rad;
void main()
{
+ GPU_INTEL_VERTEX_SHADER_WORKAROUND
+
vec3 final_pos = pos;
float flip = (gl_InstanceID != 0) ? -1.0 : 1.0;
diff --git a/source/blender/draw/modes/shaders/edit_lattice_overlay_loosevert_vert.glsl b/source/blender/draw/modes/shaders/edit_lattice_overlay_loosevert_vert.glsl
index f7df6bb4b68..ac6b353412d 100644
--- a/source/blender/draw/modes/shaders/edit_lattice_overlay_loosevert_vert.glsl
+++ b/source/blender/draw/modes/shaders/edit_lattice_overlay_loosevert_vert.glsl
@@ -22,6 +22,8 @@ vec2 proj(vec4 pos)
void main()
{
+ GPU_INTEL_VERTEX_SHADER_WORKAROUND
+
clipCase = 0;
vec3 world_pos = point_object_to_world(pos);
diff --git a/source/blender/draw/modes/shaders/edit_mesh_overlay_common_lib.glsl b/source/blender/draw/modes/shaders/edit_mesh_overlay_common_lib.glsl
index 7d4cba66933..6aa20a9d21b 100644
--- a/source/blender/draw/modes/shaders/edit_mesh_overlay_common_lib.glsl
+++ b/source/blender/draw/modes/shaders/edit_mesh_overlay_common_lib.glsl
@@ -1,5 +1,4 @@
-uniform bool doEdges = true;
uniform bool selectFaces = true;
uniform bool selectEdges = true;
@@ -17,21 +16,23 @@ vec4 EDIT_MESH_edge_color_outer(int edge_flag, int face_flag, float crease, floa
vec4 EDIT_MESH_edge_color_inner(int edge_flag)
{
vec4 color = colorWireEdit;
- vec4 color_select = (selectEdges) ? colorEdgeSelect : colorFaceSelect;
- color = (doEdges && ((edge_flag & EDGE_SELECTED) != 0)) ? color_select : color;
- color = (doEdges && ((edge_flag & EDGE_ACTIVE) != 0)) ? colorEditMeshActive : color;
+ vec4 color_select = (selectEdges) ? colorEdgeSelect : mix(colorEdgeSelect, colorWireEdit, .45);
+ color = ((edge_flag & EDGE_SELECTED) != 0) ? color_select : color;
+ color = ((edge_flag & EDGE_ACTIVE) != 0) ? colorEditMeshActive : color;
- float non_edge_select_alpha = (selectFaces && (edge_flag & EDGE_SELECTED) != 0) ? 0.75 : 0.4;
- color.a = (selectEdges) ? 1.0 : non_edge_select_alpha;
+ color.a = (selectEdges || (edge_flag & (EDGE_SELECTED | EDGE_ACTIVE)) != 0) ? 1.0 : 0.4;
return color;
}
vec4 EDIT_MESH_edge_vertex_color(int vertex_flag)
{
vec4 color = colorWireEdit;
- vec4 color_select = (selectEdges) ? colorEdgeSelect : colorFaceSelect;
- color = (doEdges && (vertex_flag & (VERT_ACTIVE | VERT_SELECTED)) != 0) ? color_select : color;
- color.a = (selectEdges) ? 1.0 : 0.4;
+ vec4 color_select = (selectEdges) ? colorEdgeSelect : mix(colorEdgeSelect, colorWireEdit, .45);
+
+ bool edge_selected = (vertex_flag & (VERT_ACTIVE | VERT_SELECTED)) != 0;
+ color = (edge_selected) ? color_select : color;
+
+ color.a = (selectEdges || edge_selected) ? 1.0 : 0.4;
return color;
}
diff --git a/source/blender/draw/modes/shaders/edit_mesh_overlay_facefill_vert.glsl b/source/blender/draw/modes/shaders/edit_mesh_overlay_facefill_vert.glsl
index a20c1124fe1..df37c6fb0bc 100644
--- a/source/blender/draw/modes/shaders/edit_mesh_overlay_facefill_vert.glsl
+++ b/source/blender/draw/modes/shaders/edit_mesh_overlay_facefill_vert.glsl
@@ -8,6 +8,8 @@ flat out vec4 faceColor;
void main()
{
+ GPU_INTEL_VERTEX_SHADER_WORKAROUND
+
vec3 world_pos = point_object_to_world(pos);
gl_Position = point_world_to_ndc(world_pos);
diff --git a/source/blender/draw/modes/shaders/edit_mesh_overlay_mesh_analysis_vert.glsl b/source/blender/draw/modes/shaders/edit_mesh_overlay_mesh_analysis_vert.glsl
index 968a63c7780..7065ce3df7c 100644
--- a/source/blender/draw/modes/shaders/edit_mesh_overlay_mesh_analysis_vert.glsl
+++ b/source/blender/draw/modes/shaders/edit_mesh_overlay_mesh_analysis_vert.glsl
@@ -12,6 +12,8 @@ out vec4 weightColor;
void main()
{
+ GPU_INTEL_VERTEX_SHADER_WORKAROUND
+
vec3 world_pos = point_object_to_world(pos);
gl_Position = point_world_to_ndc(world_pos);
weightColor = vec4(weight_color.rgb, 1.0);
diff --git a/source/blender/draw/modes/shaders/edit_mesh_overlay_vert.glsl b/source/blender/draw/modes/shaders/edit_mesh_overlay_vert.glsl
index 9aa656818cb..fabc317cf4f 100644
--- a/source/blender/draw/modes/shaders/edit_mesh_overlay_vert.glsl
+++ b/source/blender/draw/modes/shaders/edit_mesh_overlay_vert.glsl
@@ -20,6 +20,8 @@ out int selectOveride;
void main()
{
+ GPU_INTEL_VERTEX_SHADER_WORKAROUND
+
vec3 world_pos = point_object_to_world(pos);
#if !defined(FACE)
diff --git a/source/blender/draw/modes/shaders/edit_normals_vert.glsl b/source/blender/draw/modes/shaders/edit_normals_vert.glsl
index 9bf0fb7315c..384d13923f6 100644
--- a/source/blender/draw/modes/shaders/edit_normals_vert.glsl
+++ b/source/blender/draw/modes/shaders/edit_normals_vert.glsl
@@ -21,6 +21,8 @@ flat out vec4 v2;
void main()
{
+ GPU_INTEL_VERTEX_SHADER_WORKAROUND
+
vec3 n = normalize(normal_object_to_world(nor));
vec3 world_pos = point_object_to_world(pos);
diff --git a/source/blender/editors/animation/anim_markers.c b/source/blender/editors/animation/anim_markers.c
index 876bc9ae3e4..90632da8a7c 100644
--- a/source/blender/editors/animation/anim_markers.c
+++ b/source/blender/editors/animation/anim_markers.c
@@ -482,7 +482,7 @@ static void draw_markers_background(rctf *rect)
immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
unsigned char shade[4];
- UI_GetThemeColor4ubv(TH_SCRUBBING_BACKGROUND, shade);
+ UI_GetThemeColor4ubv(TH_TIME_SCRUB_BACKGROUND, shade);
immUniformColor4ubv(shade);
diff --git a/source/blender/editors/animation/time_scrub_ui.c b/source/blender/editors/animation/time_scrub_ui.c
index 37e7eab74d4..70a9b7ba1fa 100644
--- a/source/blender/editors/animation/time_scrub_ui.c
+++ b/source/blender/editors/animation/time_scrub_ui.c
@@ -46,12 +46,12 @@
#include "RNA_access.h"
-static void get_scrubbing_region_rect(const ARegion *ar, rcti *rect)
+static void get_time_scrub_region_rect(const ARegion *ar, rcti *rect)
{
rect->xmin = 0;
rect->xmax = ar->winx;
rect->ymax = ar->winy;
- rect->ymin = rect->ymax - UI_SCRUBBING_MARGIN_Y;
+ rect->ymin = rect->ymax - UI_TIME_SCRUB_MARGIN_Y;
}
static int get_centered_text_y(const rcti *rect)
@@ -64,7 +64,7 @@ static void draw_background(const rcti *rect)
uint pos = GPU_vertformat_attr_add(immVertexFormat(), "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
- immUniformThemeColor(TH_SCRUBBING_BACKGROUND);
+ immUniformThemeColor(TH_TIME_SCRUB_BACKGROUND);
GPU_blend(true);
GPU_blend_set_func_separate(
@@ -91,7 +91,7 @@ static void get_current_time_str(
static void draw_current_frame(const Scene *scene,
bool display_seconds,
const View2D *v2d,
- const rcti *scrubbing_region_rect,
+ const rcti *scrub_region_rect,
int current_frame)
{
const uiFontStyle *fstyle = UI_FSTYLE_WIDGET;
@@ -111,9 +111,9 @@ static void draw_current_frame(const Scene *scene,
UI_draw_roundbox_3fvAlpha(true,
frame_x - box_width / 2 + U.pixelsize / 2,
- scrubbing_region_rect->ymin + box_padding,
+ scrub_region_rect->ymin + box_padding,
frame_x + box_width / 2 + U.pixelsize / 2,
- scrubbing_region_rect->ymax - box_padding,
+ scrub_region_rect->ymax - box_padding,
4 * UI_DPI_FAC,
bg_color,
1.0f);
@@ -121,36 +121,36 @@ static void draw_current_frame(const Scene *scene,
UI_GetThemeColorShade4fv(TH_CFRAME, 5, bg_color);
UI_draw_roundbox_aa(false,
frame_x - box_width / 2 + U.pixelsize / 2,
- scrubbing_region_rect->ymin + box_padding,
+ scrub_region_rect->ymin + box_padding,
frame_x + box_width / 2 + U.pixelsize / 2,
- scrubbing_region_rect->ymax - box_padding,
+ scrub_region_rect->ymax - box_padding,
4 * UI_DPI_FAC,
bg_color);
UI_fontstyle_draw_simple(fstyle,
frame_x - text_width / 2 + U.pixelsize / 2,
- get_centered_text_y(scrubbing_region_rect),
+ get_centered_text_y(scrub_region_rect),
frame_str,
color);
}
-void ED_scrubbing_draw(const ARegion *ar,
- const Scene *scene,
- bool display_seconds,
- bool discrete_frames)
+void ED_time_scrub_draw(const ARegion *ar,
+ const Scene *scene,
+ bool display_seconds,
+ bool discrete_frames)
{
const View2D *v2d = &ar->v2d;
GPU_matrix_push_projection();
wmOrtho2_region_pixelspace(ar);
- rcti scrubbing_region_rect;
- get_scrubbing_region_rect(ar, &scrubbing_region_rect);
+ rcti scrub_region_rect;
+ get_time_scrub_region_rect(ar, &scrub_region_rect);
- draw_background(&scrubbing_region_rect);
+ draw_background(&scrub_region_rect);
- rcti numbers_rect = scrubbing_region_rect;
- numbers_rect.ymin = get_centered_text_y(&scrubbing_region_rect) - 4 * UI_DPI_FAC;
+ rcti numbers_rect = scrub_region_rect;
+ numbers_rect.ymin = get_centered_text_y(&scrub_region_rect) - 4 * UI_DPI_FAC;
if (discrete_frames) {
UI_view2d_draw_scale_x__discrete_frames_or_seconds(
ar, v2d, &numbers_rect, scene, display_seconds, TH_TEXT);
@@ -160,19 +160,19 @@ void ED_scrubbing_draw(const ARegion *ar,
ar, v2d, &numbers_rect, scene, display_seconds, TH_TEXT);
}
- draw_current_frame(scene, display_seconds, v2d, &scrubbing_region_rect, scene->r.cfra);
+ draw_current_frame(scene, display_seconds, v2d, &scrub_region_rect, scene->r.cfra);
GPU_matrix_pop_projection();
}
-bool ED_event_in_scrubbing_region(const ARegion *ar, const wmEvent *event)
+bool ED_time_scrub_event_in_region(const ARegion *ar, const wmEvent *event)
{
rcti rect = ar->winrct;
- rect.ymin = rect.ymax - UI_SCRUBBING_MARGIN_Y;
+ rect.ymin = rect.ymax - UI_TIME_SCRUB_MARGIN_Y;
return BLI_rcti_isect_pt(&rect, event->x, event->y);
}
-void ED_channel_search_draw(const bContext *C, ARegion *ar, bDopeSheet *dopesheet)
+void ED_time_scrub_channel_search_draw(const bContext *C, ARegion *ar, bDopeSheet *dopesheet)
{
GPU_matrix_push_projection();
wmOrtho2_region_pixelspace(ar);
@@ -180,7 +180,7 @@ void ED_channel_search_draw(const bContext *C, ARegion *ar, bDopeSheet *dopeshee
rcti rect;
rect.xmin = 0;
rect.xmax = ceilf(ar->sizex * UI_DPI_FAC);
- rect.ymin = ar->sizey * UI_DPI_FAC - UI_SCRUBBING_MARGIN_Y;
+ rect.ymin = ar->sizey * UI_DPI_FAC - UI_TIME_SCRUB_MARGIN_Y;
rect.ymax = ceilf(ar->sizey * UI_DPI_FAC);
uint pos = GPU_vertformat_attr_add(immVertexFormat(), "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
diff --git a/source/blender/editors/curve/editcurve.c b/source/blender/editors/curve/editcurve.c
index 65f502d5cd2..8d131ee28ba 100644
--- a/source/blender/editors/curve/editcurve.c
+++ b/source/blender/editors/curve/editcurve.c
@@ -2584,33 +2584,42 @@ void CURVE_OT_switch_direction(wmOperatorType *ot)
static int set_goal_weight_exec(bContext *C, wmOperator *op)
{
- Object *obedit = CTX_data_edit_object(C);
- ListBase *editnurb = object_editcurve_get(obedit);
- Nurb *nu;
- BezTriple *bezt;
- BPoint *bp;
- float weight = RNA_float_get(op->ptr, "weight");
- int a;
+ ViewLayer *view_layer = CTX_data_view_layer(C);
+ uint objects_len;
+ Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data(
+ view_layer, CTX_wm_view3d(C), &objects_len);
- for (nu = editnurb->first; nu; nu = nu->next) {
- if (nu->bezt) {
- for (bezt = nu->bezt, a = 0; a < nu->pntsu; a++, bezt++) {
- if (bezt->f2 & SELECT) {
- bezt->weight = weight;
+ for (uint ob_index = 0; ob_index < objects_len; ob_index++) {
+ Object *obedit = objects[ob_index];
+ ListBase *editnurb = object_editcurve_get(obedit);
+ Nurb *nu;
+ BezTriple *bezt;
+ BPoint *bp;
+ float weight = RNA_float_get(op->ptr, "weight");
+ int a;
+
+ for (nu = editnurb->first; nu; nu = nu->next) {
+ if (nu->bezt) {
+ for (bezt = nu->bezt, a = 0; a < nu->pntsu; a++, bezt++) {
+ if (bezt->f2 & SELECT) {
+ bezt->weight = weight;
+ }
}
}
- }
- else if (nu->bp) {
- for (bp = nu->bp, a = 0; a < nu->pntsu * nu->pntsv; a++, bp++) {
- if (bp->f1 & SELECT) {
- bp->weight = weight;
+ else if (nu->bp) {
+ for (bp = nu->bp, a = 0; a < nu->pntsu * nu->pntsv; a++, bp++) {
+ if (bp->f1 & SELECT) {
+ bp->weight = weight;
+ }
}
}
}
+
+ DEG_id_tag_update(obedit->data, 0);
+ WM_event_add_notifier(C, NC_GEOM | ND_DATA, obedit->data);
}
- DEG_id_tag_update(obedit->data, 0);
- WM_event_add_notifier(C, NC_GEOM | ND_DATA, obedit->data);
+ MEM_freeN(objects);
return OPERATOR_FINISHED;
}
@@ -2638,33 +2647,42 @@ void CURVE_OT_spline_weight_set(wmOperatorType *ot)
static int set_radius_exec(bContext *C, wmOperator *op)
{
- Object *obedit = CTX_data_edit_object(C);
- ListBase *editnurb = object_editcurve_get(obedit);
- Nurb *nu;
- BezTriple *bezt;
- BPoint *bp;
- float radius = RNA_float_get(op->ptr, "radius");
- int a;
+ ViewLayer *view_layer = CTX_data_view_layer(C);
+ uint objects_len;
+ Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data(
+ view_layer, CTX_wm_view3d(C), &objects_len);
- for (nu = editnurb->first; nu; nu = nu->next) {
- if (nu->bezt) {
- for (bezt = nu->bezt, a = 0; a < nu->pntsu; a++, bezt++) {
- if (bezt->f2 & SELECT) {
- bezt->radius = radius;
+ for (uint ob_index = 0; ob_index < objects_len; ob_index++) {
+ Object *obedit = objects[ob_index];
+ ListBase *editnurb = object_editcurve_get(obedit);
+ Nurb *nu;
+ BezTriple *bezt;
+ BPoint *bp;
+ float radius = RNA_float_get(op->ptr, "radius");
+ int a;
+
+ for (nu = editnurb->first; nu; nu = nu->next) {
+ if (nu->bezt) {
+ for (bezt = nu->bezt, a = 0; a < nu->pntsu; a++, bezt++) {
+ if (bezt->f2 & SELECT) {
+ bezt->radius = radius;
+ }
}
}
- }
- else if (nu->bp) {
- for (bp = nu->bp, a = 0; a < nu->pntsu * nu->pntsv; a++, bp++) {
- if (bp->f1 & SELECT) {
- bp->radius = radius;
+ else if (nu->bp) {
+ for (bp = nu->bp, a = 0; a < nu->pntsu * nu->pntsv; a++, bp++) {
+ if (bp->f1 & SELECT) {
+ bp->radius = radius;
+ }
}
}
}
+
+ WM_event_add_notifier(C, NC_GEOM | ND_DATA, obedit->data);
+ DEG_id_tag_update(obedit->data, 0);
}
- WM_event_add_notifier(C, NC_GEOM | ND_DATA, obedit->data);
- DEG_id_tag_update(obedit->data, 0);
+ MEM_freeN(objects);
return OPERATOR_FINISHED;
}
@@ -2743,81 +2761,90 @@ static void smooth_single_bp(BPoint *bp,
static int smooth_exec(bContext *C, wmOperator *UNUSED(op))
{
const float factor = 1.0f / 6.0f;
- Object *obedit = CTX_data_edit_object(C);
- ListBase *editnurb = object_editcurve_get(obedit);
- Nurb *nu;
+ ViewLayer *view_layer = CTX_data_view_layer(C);
+ uint objects_len;
+ Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data(
+ view_layer, CTX_wm_view3d(C), &objects_len);
- int a, a_end;
- bool changed = false;
+ for (uint ob_index = 0; ob_index < objects_len; ob_index++) {
+ Object *obedit = objects[ob_index];
+ ListBase *editnurb = object_editcurve_get(obedit);
+ Nurb *nu;
- for (nu = editnurb->first; nu; nu = nu->next) {
- if (nu->bezt) {
- /* duplicate the curve to use in weight calculation */
- const BezTriple *bezt_orig = MEM_dupallocN(nu->bezt);
- BezTriple *bezt;
- changed = false;
+ int a, a_end;
+ bool changed = false;
- /* check whether its cyclic or not, and set initial & final conditions */
- if (nu->flagu & CU_NURB_CYCLIC) {
- a = 0;
- a_end = nu->pntsu;
- }
- else {
- a = 1;
- a_end = nu->pntsu - 1;
- }
+ for (nu = editnurb->first; nu; nu = nu->next) {
+ if (nu->bezt) {
+ /* duplicate the curve to use in weight calculation */
+ const BezTriple *bezt_orig = MEM_dupallocN(nu->bezt);
+ BezTriple *bezt;
+ changed = false;
+
+ /* check whether its cyclic or not, and set initial & final conditions */
+ if (nu->flagu & CU_NURB_CYCLIC) {
+ a = 0;
+ a_end = nu->pntsu;
+ }
+ else {
+ a = 1;
+ a_end = nu->pntsu - 1;
+ }
- /* for all the curve points */
- for (; a < a_end; a++) {
- /* respect selection */
- bezt = &nu->bezt[a];
- if (bezt->f2 & SELECT) {
- const BezTriple *bezt_orig_prev, *bezt_orig_next;
+ /* for all the curve points */
+ for (; a < a_end; a++) {
+ /* respect selection */
+ bezt = &nu->bezt[a];
+ if (bezt->f2 & SELECT) {
+ const BezTriple *bezt_orig_prev, *bezt_orig_next;
- bezt_orig_prev = &bezt_orig[mod_i(a - 1, nu->pntsu)];
- bezt_orig_next = &bezt_orig[mod_i(a + 1, nu->pntsu)];
+ bezt_orig_prev = &bezt_orig[mod_i(a - 1, nu->pntsu)];
+ bezt_orig_next = &bezt_orig[mod_i(a + 1, nu->pntsu)];
- smooth_single_bezt(bezt, bezt_orig_prev, bezt_orig_next, factor);
+ smooth_single_bezt(bezt, bezt_orig_prev, bezt_orig_next, factor);
- changed = true;
+ changed = true;
+ }
+ }
+ MEM_freeN((void *)bezt_orig);
+ if (changed) {
+ BKE_nurb_handles_calc(nu);
}
}
- MEM_freeN((void *)bezt_orig);
- if (changed) {
- BKE_nurb_handles_calc(nu);
- }
- }
- else if (nu->bp) {
- /* Same as above, keep these the same! */
- const BPoint *bp_orig = MEM_dupallocN(nu->bp);
- BPoint *bp;
+ else if (nu->bp) {
+ /* Same as above, keep these the same! */
+ const BPoint *bp_orig = MEM_dupallocN(nu->bp);
+ BPoint *bp;
- if (nu->flagu & CU_NURB_CYCLIC) {
- a = 0;
- a_end = nu->pntsu;
- }
- else {
- a = 1;
- a_end = nu->pntsu - 1;
- }
+ if (nu->flagu & CU_NURB_CYCLIC) {
+ a = 0;
+ a_end = nu->pntsu;
+ }
+ else {
+ a = 1;
+ a_end = nu->pntsu - 1;
+ }
- for (; a < a_end; a++) {
- bp = &nu->bp[a];
- if (bp->f1 & SELECT) {
- const BPoint *bp_orig_prev, *bp_orig_next;
+ for (; a < a_end; a++) {
+ bp = &nu->bp[a];
+ if (bp->f1 & SELECT) {
+ const BPoint *bp_orig_prev, *bp_orig_next;
- bp_orig_prev = &bp_orig[mod_i(a - 1, nu->pntsu)];
- bp_orig_next = &bp_orig[mod_i(a + 1, nu->pntsu)];
+ bp_orig_prev = &bp_orig[mod_i(a - 1, nu->pntsu)];
+ bp_orig_next = &bp_orig[mod_i(a + 1, nu->pntsu)];
- smooth_single_bp(bp, bp_orig_prev, bp_orig_next, factor);
+ smooth_single_bp(bp, bp_orig_prev, bp_orig_next, factor);
+ }
}
+ MEM_freeN((void *)bp_orig);
}
- MEM_freeN((void *)bp_orig);
}
+
+ WM_event_add_notifier(C, NC_GEOM | ND_DATA, obedit->data);
+ DEG_id_tag_update(obedit->data, 0);
}
- WM_event_add_notifier(C, NC_GEOM | ND_DATA, obedit->data);
- DEG_id_tag_update(obedit->data, 0);
+ MEM_freeN(objects);
return OPERATOR_FINISHED;
}
@@ -3023,13 +3050,22 @@ static void curve_smooth_value(ListBase *editnurb, const int bezt_offsetof, cons
static int curve_smooth_weight_exec(bContext *C, wmOperator *UNUSED(op))
{
- Object *obedit = CTX_data_edit_object(C);
- ListBase *editnurb = object_editcurve_get(obedit);
+ ViewLayer *view_layer = CTX_data_view_layer(C);
+ uint objects_len;
+ Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data(
+ view_layer, CTX_wm_view3d(C), &objects_len);
+
+ for (uint ob_index = 0; ob_index < objects_len; ob_index++) {
+ Object *obedit = objects[ob_index];
+ ListBase *editnurb = object_editcurve_get(obedit);
+
+ curve_smooth_value(editnurb, offsetof(BezTriple, weight), offsetof(BPoint, weight));
- curve_smooth_value(editnurb, offsetof(BezTriple, weight), offsetof(BPoint, weight));
+ WM_event_add_notifier(C, NC_GEOM | ND_DATA, obedit->data);
+ DEG_id_tag_update(obedit->data, 0);
+ }
- WM_event_add_notifier(C, NC_GEOM | ND_DATA, obedit->data);
- DEG_id_tag_update(obedit->data, 0);
+ MEM_freeN(objects);
return OPERATOR_FINISHED;
}
@@ -3051,13 +3087,22 @@ void CURVE_OT_smooth_weight(wmOperatorType *ot)
static int curve_smooth_radius_exec(bContext *C, wmOperator *UNUSED(op))
{
- Object *obedit = CTX_data_edit_object(C);
- ListBase *editnurb = object_editcurve_get(obedit);
+ ViewLayer *view_layer = CTX_data_view_layer(C);
+ uint objects_len;
+ Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data(
+ view_layer, CTX_wm_view3d(C), &objects_len);
- curve_smooth_value(editnurb, offsetof(BezTriple, radius), offsetof(BPoint, radius));
+ for (uint ob_index = 0; ob_index < objects_len; ob_index++) {
+ Object *obedit = objects[ob_index];
+ ListBase *editnurb = object_editcurve_get(obedit);
- WM_event_add_notifier(C, NC_GEOM | ND_DATA, obedit->data);
- DEG_id_tag_update(obedit->data, 0);
+ curve_smooth_value(editnurb, offsetof(BezTriple, radius), offsetof(BPoint, radius));
+
+ WM_event_add_notifier(C, NC_GEOM | ND_DATA, obedit->data);
+ DEG_id_tag_update(obedit->data, 0);
+ }
+
+ MEM_freeN(objects);
return OPERATOR_FINISHED;
}
@@ -3079,13 +3124,22 @@ void CURVE_OT_smooth_radius(wmOperatorType *ot)
static int curve_smooth_tilt_exec(bContext *C, wmOperator *UNUSED(op))
{
- Object *obedit = CTX_data_edit_object(C);
- ListBase *editnurb = object_editcurve_get(obedit);
+ ViewLayer *view_layer = CTX_data_view_layer(C);
+ uint objects_len;
+ Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data(
+ view_layer, CTX_wm_view3d(C), &objects_len);
+
+ for (uint ob_index = 0; ob_index < objects_len; ob_index++) {
+ Object *obedit = objects[ob_index];
+ ListBase *editnurb = object_editcurve_get(obedit);
- curve_smooth_value(editnurb, offsetof(BezTriple, tilt), offsetof(BPoint, tilt));
+ curve_smooth_value(editnurb, offsetof(BezTriple, tilt), offsetof(BPoint, tilt));
+
+ WM_event_add_notifier(C, NC_GEOM | ND_DATA, obedit->data);
+ DEG_id_tag_update(obedit->data, 0);
+ }
- WM_event_add_notifier(C, NC_GEOM | ND_DATA, obedit->data);
- DEG_id_tag_update(obedit->data, 0);
+ MEM_freeN(objects);
return OPERATOR_FINISHED;
}
@@ -3253,7 +3307,8 @@ static int reveal_exec(bContext *C, wmOperator *op)
}
if (changed) {
- DEG_id_tag_update(obedit->data, ID_RECALC_COPY_ON_WRITE | ID_RECALC_SELECT);
+ DEG_id_tag_update(obedit->data,
+ ID_RECALC_COPY_ON_WRITE | ID_RECALC_SELECT | ID_RECALC_GEOMETRY);
WM_event_add_notifier(C, NC_GEOM | ND_SELECT, obedit->data);
changed_multi = true;
}
@@ -3909,54 +3964,63 @@ static void findselectedNurbvert(
static int set_spline_type_exec(bContext *C, wmOperator *op)
{
- Main *bmain = CTX_data_main(C);
- Object *obedit = CTX_data_edit_object(C);
- View3D *v3d = CTX_wm_view3d(C);
- ListBase *editnurb = object_editcurve_get(obedit);
- Nurb *nu;
- bool changed = false;
- bool changed_size = false;
- const bool use_handles = RNA_boolean_get(op->ptr, "use_handles");
- const int type = RNA_enum_get(op->ptr, "type");
+ ViewLayer *view_layer = CTX_data_view_layer(C);
+ uint objects_len;
+ Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data(
+ view_layer, CTX_wm_view3d(C), &objects_len);
+ int ret_value = OPERATOR_CANCELLED;
- if (type == CU_CARDINAL || type == CU_BSPLINE) {
- BKE_report(op->reports, RPT_ERROR, "Not yet implemented");
- return OPERATOR_CANCELLED;
- }
+ for (uint ob_index = 0; ob_index < objects_len; ob_index++) {
+ Object *obedit = objects[ob_index];
+ Main *bmain = CTX_data_main(C);
+ View3D *v3d = CTX_wm_view3d(C);
+ ListBase *editnurb = object_editcurve_get(obedit);
+ Nurb *nu;
+ bool changed = false;
+ bool changed_size = false;
+ const bool use_handles = RNA_boolean_get(op->ptr, "use_handles");
+ const int type = RNA_enum_get(op->ptr, "type");
- for (nu = editnurb->first; nu; nu = nu->next) {
- if (ED_curve_nurb_select_check(v3d, nu)) {
- const int pntsu_prev = nu->pntsu;
- if (BKE_nurb_type_convert(nu, type, use_handles)) {
- changed = true;
- if (pntsu_prev != nu->pntsu) {
- changed_size = true;
+ if (type == CU_CARDINAL || type == CU_BSPLINE) {
+ BKE_report(op->reports, RPT_ERROR, "Not yet implemented");
+ continue;
+ }
+
+ for (nu = editnurb->first; nu; nu = nu->next) {
+ if (ED_curve_nurb_select_check(v3d, nu)) {
+ const int pntsu_prev = nu->pntsu;
+ if (BKE_nurb_type_convert(nu, type, use_handles)) {
+ changed = true;
+ if (pntsu_prev != nu->pntsu) {
+ changed_size = true;
+ }
+ }
+ else {
+ BKE_report(op->reports, RPT_ERROR, "No conversion possible");
}
- }
- else {
- BKE_report(op->reports, RPT_ERROR, "No conversion possible");
}
}
- }
- if (changed) {
- if (ED_curve_updateAnimPaths(bmain, obedit->data)) {
- WM_event_add_notifier(C, NC_OBJECT | ND_KEYS, obedit);
- }
+ if (changed) {
+ if (ED_curve_updateAnimPaths(bmain, obedit->data)) {
+ WM_event_add_notifier(C, NC_OBJECT | ND_KEYS, obedit);
+ }
- DEG_id_tag_update(obedit->data, 0);
- WM_event_add_notifier(C, NC_GEOM | ND_DATA, obedit->data);
+ DEG_id_tag_update(obedit->data, 0);
+ WM_event_add_notifier(C, NC_GEOM | ND_DATA, obedit->data);
- if (changed_size) {
- Curve *cu = obedit->data;
- cu->actvert = CU_ACT_NONE;
- }
+ if (changed_size) {
+ Curve *cu = obedit->data;
+ cu->actvert = CU_ACT_NONE;
+ }
- return OPERATOR_FINISHED;
- }
- else {
- return OPERATOR_CANCELLED;
+ ret_value = OPERATOR_FINISHED;
+ }
}
+
+ MEM_freeN(objects);
+
+ return ret_value;
}
void CURVE_OT_spline_type_set(wmOperatorType *ot)
@@ -6747,31 +6811,41 @@ void CURVE_OT_decimate(wmOperatorType *ot)
static int shade_smooth_exec(bContext *C, wmOperator *op)
{
- Object *obedit = CTX_data_edit_object(C);
View3D *v3d = CTX_wm_view3d(C);
- ListBase *editnurb = object_editcurve_get(obedit);
- Nurb *nu;
+ ViewLayer *view_layer = CTX_data_view_layer(C);
int clear = (STREQ(op->idname, "CURVE_OT_shade_flat"));
+ uint objects_len;
+ Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data(
+ view_layer, CTX_wm_view3d(C), &objects_len);
+ int ret_value = OPERATOR_CANCELLED;
- if (obedit->type != OB_CURVE) {
- return OPERATOR_CANCELLED;
- }
+ for (uint ob_index = 0; ob_index < objects_len; ob_index++) {
+ Object *obedit = objects[ob_index];
+ ListBase *editnurb = object_editcurve_get(obedit);
- for (nu = editnurb->first; nu; nu = nu->next) {
- if (ED_curve_nurb_select_check(v3d, nu)) {
- if (!clear) {
- nu->flag |= CU_SMOOTH;
- }
- else {
- nu->flag &= ~CU_SMOOTH;
+ if (obedit->type != OB_CURVE) {
+ continue;
+ }
+
+ for (Nurb *nu = editnurb->first; nu; nu = nu->next) {
+ if (ED_curve_nurb_select_check(v3d, nu)) {
+ if (!clear) {
+ nu->flag |= CU_SMOOTH;
+ }
+ else {
+ nu->flag &= ~CU_SMOOTH;
+ }
}
}
+
+ WM_event_add_notifier(C, NC_GEOM | ND_DATA, obedit->data);
+ DEG_id_tag_update(obedit->data, 0);
+ ret_value = OPERATOR_FINISHED;
}
- WM_event_add_notifier(C, NC_GEOM | ND_DATA, obedit->data);
- DEG_id_tag_update(obedit->data, 0);
+ MEM_freeN(objects);
- return OPERATOR_FINISHED;
+ return ret_value;
}
void CURVE_OT_shade_smooth(wmOperatorType *ot)
@@ -7026,7 +7100,7 @@ static int match_texture_space_exec(bContext *C, wmOperator *UNUSED(op))
int a;
if (object->runtime.curve_cache == NULL) {
- BKE_displist_make_curveTypes(depsgraph, scene, object, false, false, NULL);
+ BKE_displist_make_curveTypes(depsgraph, scene, object, false, false);
}
INIT_MINMAX(min, max);
diff --git a/source/blender/editors/curve/editfont.c b/source/blender/editors/curve/editfont.c
index 0759b64d14a..ffbfb692ca9 100644
--- a/source/blender/editors/curve/editfont.c
+++ b/source/blender/editors/curve/editfont.c
@@ -2007,7 +2007,7 @@ static int font_open_exec(bContext *C, wmOperator *op)
id_us_min(&font->id);
RNA_id_pointer_create(&font->id, &idptr);
- RNA_property_pointer_set(NULL, &pprop->ptr, pprop->prop, idptr);
+ RNA_property_pointer_set(&pprop->ptr, pprop->prop, idptr, NULL);
RNA_property_update(C, &pprop->ptr, pprop->prop);
}
@@ -2090,7 +2090,7 @@ static int font_unlink_exec(bContext *C, wmOperator *op)
builtin_font = BKE_vfont_builtin_get();
RNA_id_pointer_create(&builtin_font->id, &idptr);
- RNA_property_pointer_set(NULL, &pprop.ptr, pprop.prop, idptr);
+ RNA_property_pointer_set(&pprop.ptr, pprop.prop, idptr, NULL);
RNA_property_update(C, &pprop.ptr, pprop.prop);
return OPERATOR_FINISHED;
diff --git a/source/blender/editors/datafiles/CMakeLists.txt b/source/blender/editors/datafiles/CMakeLists.txt
index 316ad3f91d6..d2d0095bdb2 100644
--- a/source/blender/editors/datafiles/CMakeLists.txt
+++ b/source/blender/editors/datafiles/CMakeLists.txt
@@ -569,9 +569,9 @@ set(ICON_NAMES
loop_forwards
back
forward
+ file_cache
file_volume
- alembic
- volume
+ file_3d
file_hidden
file_backup
disk_drive
diff --git a/source/blender/editors/gpencil/gpencil_fill.c b/source/blender/editors/gpencil/gpencil_fill.c
index 96f405fab2f..bf15b846bb6 100644
--- a/source/blender/editors/gpencil/gpencil_fill.c
+++ b/source/blender/editors/gpencil/gpencil_fill.c
@@ -401,7 +401,8 @@ static bool gp_render_offscreen(tGPDfill *tgpf)
glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
- ED_view3d_update_viewmat(tgpf->depsgraph, tgpf->scene, tgpf->v3d, tgpf->ar, NULL, winmat, NULL);
+ ED_view3d_update_viewmat(
+ tgpf->depsgraph, tgpf->scene, tgpf->v3d, tgpf->ar, NULL, winmat, NULL, true);
/* set for opengl */
GPU_matrix_projection_set(tgpf->rv3d->winmat);
GPU_matrix_set(tgpf->rv3d->viewmat);
diff --git a/source/blender/editors/include/ED_anim_api.h b/source/blender/editors/include/ED_anim_api.h
index cd68981dee3..7a29e6b5e66 100644
--- a/source/blender/editors/include/ED_anim_api.h
+++ b/source/blender/editors/include/ED_anim_api.h
@@ -404,7 +404,7 @@ typedef enum eAnimFilter_Flags {
/* channel heights */
#define ACHANNEL_FIRST_TOP(ac) \
- (UI_view2d_scale_get_y(&(ac)->ar->v2d) * -UI_SCRUBBING_MARGIN_Y - ACHANNEL_SKIP)
+ (UI_view2d_scale_get_y(&(ac)->ar->v2d) * -UI_TIME_SCRUB_MARGIN_Y - ACHANNEL_SKIP)
#define ACHANNEL_HEIGHT(ac) (0.8f * (ac)->yscale_fac * U.widget_unit)
#define ACHANNEL_SKIP (0.1f * U.widget_unit)
#define ACHANNEL_STEP(ac) (ACHANNEL_HEIGHT(ac) + ACHANNEL_SKIP)
@@ -422,7 +422,7 @@ typedef enum eAnimFilter_Flags {
/* NLA channel heights */
#define NLACHANNEL_FIRST_TOP(ac) \
- (UI_view2d_scale_get_y(&(ac)->ar->v2d) * -UI_SCRUBBING_MARGIN_Y - NLACHANNEL_SKIP)
+ (UI_view2d_scale_get_y(&(ac)->ar->v2d) * -UI_TIME_SCRUB_MARGIN_Y - NLACHANNEL_SKIP)
#define NLACHANNEL_HEIGHT(snla) \
((snla && (snla->flag & SNLA_NOSTRIPCURVES)) ? (0.8f * U.widget_unit) : (1.2f * U.widget_unit))
#define NLACHANNEL_SKIP (0.1f * U.widget_unit)
diff --git a/source/blender/editors/include/ED_mask.h b/source/blender/editors/include/ED_mask.h
index c3883de0722..3322cf0a863 100644
--- a/source/blender/editors/include/ED_mask.h
+++ b/source/blender/editors/include/ED_mask.h
@@ -24,6 +24,7 @@
#ifndef __ED_MASK_H__
#define __ED_MASK_H__
+struct Depsgraph;
struct KeyframeEditData;
struct MaskLayer;
struct MaskLayerShape;
@@ -55,7 +56,8 @@ void ED_operatormacros_mask(void);
/* mask_draw.c */
void ED_mask_draw(const struct bContext *C, const char draw_flag, const char draw_type);
-void ED_mask_draw_region(struct Mask *mask,
+void ED_mask_draw_region(struct Depsgraph *depsgraph,
+ struct Mask *mask,
struct ARegion *ar,
const char draw_flag,
const char draw_type,
diff --git a/source/blender/editors/include/ED_mesh.h b/source/blender/editors/include/ED_mesh.h
index 4e6bf7d4df5..0a8304f3f8a 100644
--- a/source/blender/editors/include/ED_mesh.h
+++ b/source/blender/editors/include/ED_mesh.h
@@ -152,24 +152,16 @@ struct BMElem *EDBM_select_id_bm_elem_get(struct EDBMSelectID_Context *sel_id_ct
const uint sel_id,
uint *r_base_index);
+uint EDBM_select_id_context_offset_for_object_elem(const struct EDBMSelectID_Context *sel_id_ctx,
+ int base_index,
+ char htype);
+
+uint EDBM_select_id_context_elem_len(const struct EDBMSelectID_Context *sel_id_ctx);
+
void EDBM_select_mirrored(
struct BMEditMesh *em, const int axis, const bool extend, int *r_totmirr, int *r_totfail);
void EDBM_automerge(struct Scene *scene, struct Object *ob, bool update, const char hflag);
-bool EDBM_backbuf_border_init(
- struct ViewContext *vc, short xmin, short ymin, short xmax, short ymax);
-bool EDBM_backbuf_check(unsigned int index);
-void EDBM_backbuf_free(void);
-
-bool EDBM_backbuf_border_mask_init(struct ViewContext *vc,
- const int mcords[][2],
- short tot,
- short xmin,
- short ymin,
- short xmax,
- short ymax);
-bool EDBM_backbuf_circle_init(struct ViewContext *vc, short xs, short ys, short rads);
-
struct BMVert *EDBM_vert_find_nearest_ex(struct ViewContext *vc,
float *r_dist,
const bool use_select_bias,
@@ -249,9 +241,6 @@ void em_setup_viewcontext(struct bContext *C, struct ViewContext *vc); /* rename
bool EDBM_mesh_deselect_all_multi_ex(struct Base **bases, const uint bases_len);
bool EDBM_mesh_deselect_all_multi(struct bContext *C);
-/* Only use for modes that don't support multi-edit-modes (painting). */
-extern unsigned int bm_vertoffs, bm_solidoffs, bm_wireoffs;
-
/* editmesh_preselect_edgering.c */
struct EditMesh_PreSelEdgeRing;
struct EditMesh_PreSelEdgeRing *EDBM_preselect_edgering_create(void);
@@ -291,7 +280,6 @@ bool paintface_mouse_select(struct bContext *C,
bool extend,
bool deselect,
bool toggle);
-bool do_paintface_box_select(struct ViewContext *vc, const struct rcti *rect, int sel_op);
bool paintface_deselect_all_visible(struct bContext *C,
struct Object *ob,
int action,
diff --git a/source/blender/editors/include/ED_select_buffer_utils.h b/source/blender/editors/include/ED_select_buffer_utils.h
new file mode 100644
index 00000000000..af745cee676
--- /dev/null
+++ b/source/blender/editors/include/ED_select_buffer_utils.h
@@ -0,0 +1,43 @@
+/*
+ * 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 editors
+ */
+
+#ifndef __ED_SELECT_BUFFER_UTILS_H__
+#define __ED_SELECT_BUFFER_UTILS_H__
+
+struct rcti;
+
+/* Boolean array from selection ID's. */
+uint *ED_select_buffer_bitmap_from_rect(const uint bitmap_len, const struct rcti *rect);
+uint *ED_select_buffer_bitmap_from_circle(const uint bitmap_len,
+ const int center[2],
+ const int radius);
+uint *ED_select_buffer_bitmap_from_poly(const uint bitmap_len,
+ const int poly[][2],
+ const int poly_len,
+ const rcti *rect);
+
+/* Single result from selection ID's. */
+uint ED_select_buffer_sample_point(const int center[2]);
+uint ED_select_buffer_find_nearest_to_point(const int center[2],
+ const uint id_min,
+ const uint id_max,
+ uint *dist);
+
+#endif /* __ED_SELECT_BUFFER_UTILS_H__ */
diff --git a/source/blender/editors/include/ED_time_scrub_ui.h b/source/blender/editors/include/ED_time_scrub_ui.h
index a2e3098e949..b43e674224c 100644
--- a/source/blender/editors/include/ED_time_scrub_ui.h
+++ b/source/blender/editors/include/ED_time_scrub_ui.h
@@ -21,23 +21,23 @@
* \ingroup editors
*/
-#ifndef __ED_SCRUBBING_H__
-#define __ED_SCRUBBING_H__
+#ifndef __ED_TIME_SCRUB_UI_H__
+#define __ED_TIME_SCRUB_UI_H__
struct View2DGrid;
struct bContext;
struct bDopeSheet;
struct wmEvent;
-void ED_scrubbing_draw(const struct ARegion *ar,
- const struct Scene *scene,
- bool display_seconds,
- bool discrete_frames);
+void ED_time_scrub_draw(const struct ARegion *ar,
+ const struct Scene *scene,
+ bool display_seconds,
+ bool discrete_frames);
-bool ED_event_in_scrubbing_region(const struct ARegion *ar, const struct wmEvent *event);
+bool ED_time_scrub_event_in_region(const struct ARegion *ar, const struct wmEvent *event);
-void ED_channel_search_draw(const struct bContext *C,
- struct ARegion *ar,
- struct bDopeSheet *dopesheet);
+void ED_time_scrub_channel_search_draw(const struct bContext *C,
+ struct ARegion *ar,
+ struct bDopeSheet *dopesheet);
-#endif /* __ED_SCRUBBING_H__ */
+#endif /* __ED_TIME_SCRUB_UI_H__ */
diff --git a/source/blender/editors/include/ED_view3d.h b/source/blender/editors/include/ED_view3d.h
index cd4cefe8891..5ce9133a531 100644
--- a/source/blender/editors/include/ED_view3d.h
+++ b/source/blender/editors/include/ED_view3d.h
@@ -42,6 +42,7 @@ struct GPUFX;
struct GPUFXSettings;
struct GPUOffScreen;
struct GPUViewport;
+struct ID;
struct ImBuf;
struct MVert;
struct Main;
@@ -449,16 +450,9 @@ void ED_view3d_backbuf_depth_validate(struct ViewContext *vc);
int ED_view3d_backbuf_sample_size_clamp(struct ARegion *ar, const float dist);
void ED_view3d_select_id_validate(struct ViewContext *vc);
-void ED_view3d_select_id_validate_with_select_mode(struct ViewContext *vc, short select_mode);
-uint ED_view3d_select_id_sample(struct ViewContext *vc, int x, int y);
-uint *ED_view3d_select_id_read(
- struct ViewContext *vc, int xmin, int ymin, int xmax, int ymax, uint *r_buf_len);
-uint *ED_view3d_select_id_read_rect(struct ViewContext *vc,
- const struct rcti *rect,
- uint *r_buf_len);
-uint ED_view3d_select_id_read_nearest(
- struct ViewContext *vc, const int mval[2], const uint min, const uint max, uint *r_dist);
+uint *ED_view3d_select_id_read(int xmin, int ymin, int xmax, int ymax, uint *r_buf_len);
+uint *ED_view3d_select_id_read_rect(const struct rcti *rect, uint *r_buf_len);
bool ED_view3d_autodist(struct Depsgraph *depsgraph,
struct ARegion *ar,
@@ -590,7 +584,6 @@ struct ImBuf *ED_view3d_draw_offscreen_imbuf(struct Depsgraph *depsgraph,
int sizex,
int sizey,
unsigned int flag,
- unsigned int draw_flags,
int alpha_mode,
int samples,
const char *viewname,
@@ -621,7 +614,8 @@ void ED_view3d_update_viewmat(struct Depsgraph *depsgraph,
struct ARegion *ar,
float viewmat[4][4],
float winmat[4][4],
- const struct rcti *rect);
+ const struct rcti *rect,
+ bool offscreen);
bool ED_view3d_quat_from_axis_view(const char view, float quat[4]);
char ED_view3d_quat_to_axis_view(const float quat[4], const float epsilon);
char ED_view3d_lock_view_from_index(int index);
diff --git a/source/blender/editors/include/UI_icons.h b/source/blender/editors/include/UI_icons.h
index f54e4d1c61b..048f30bdf26 100644
--- a/source/blender/editors/include/UI_icons.h
+++ b/source/blender/editors/include/UI_icons.h
@@ -96,8 +96,8 @@ DEF_ICON(PINNED)
DEF_ICON(SCREEN_BACK)
DEF_ICON(RIGHTARROW)
DEF_ICON(DOWNARROW_HLT)
-DEF_ICON_BLANK(103)
-DEF_ICON_BLANK(104)
+DEF_ICON(FCURVE_SNAPSHOT)
+DEF_ICON(OBJECT_HIDDEN)
DEF_ICON_BLANK(105)
DEF_ICON_BLANK(106)
DEF_ICON(PLUGIN)
@@ -699,8 +699,8 @@ DEF_ICON(VIS_SEL_10)
DEF_ICON(VIS_SEL_01)
DEF_ICON(VIS_SEL_00)
DEF_ICON_BLANK(231)
-DEF_ICON(AUTOMERGE_ON)
DEF_ICON(AUTOMERGE_OFF)
+DEF_ICON(AUTOMERGE_ON)
DEF_ICON_BLANK(234)
DEF_ICON(UV_VERTEXSEL)
DEF_ICON(UV_EDGESEL)
@@ -821,9 +821,9 @@ DEF_ICON(FORWARD)
DEF_ICON_BLANK(825)
DEF_ICON_BLANK(826)
DEF_ICON_BLANK(827)
+DEF_ICON(FILE_CACHE)
DEF_ICON(FILE_VOLUME)
-DEF_ICON(ALEMBIC)
-DEF_ICON(VOLUME)
+DEF_ICON(FILE_3D)
DEF_ICON(FILE_HIDDEN)
DEF_ICON(FILE_BACKUP)
DEF_ICON(DISK_DRIVE)
diff --git a/source/blender/editors/include/UI_interface.h b/source/blender/editors/include/UI_interface.h
index 14d681ee817..bf728ec7772 100644
--- a/source/blender/editors/include/UI_interface.h
+++ b/source/blender/editors/include/UI_interface.h
@@ -281,6 +281,9 @@ enum {
/** Value is animated, but the current value differs from the animated one. */
UI_BUT_ANIMATED_CHANGED = 1 << 25,
+
+ /* Draw the checkbox buttons inverted. */
+ UI_BUT_CHECKBOX_INVERT = 1 << 26,
};
/* scale fixed button widths by this to account for DPI */
@@ -1627,7 +1630,7 @@ struct Panel *UI_panel_begin(struct ScrArea *sa,
struct PanelType *pt,
struct Panel *pa,
bool *r_open);
-void UI_panel_end(uiBlock *block, int width, int height);
+void UI_panel_end(uiBlock *block, int width, int height, bool open);
void UI_panels_scale(struct ARegion *ar, float new_width);
void UI_panel_label_offset(struct uiBlock *block, int *r_x, int *r_y);
int UI_panel_size_y(const struct Panel *pa);
@@ -1638,6 +1641,7 @@ struct PanelCategoryDyn *UI_panel_category_find(struct ARegion *ar, const char *
struct PanelCategoryStack *UI_panel_category_active_find(struct ARegion *ar, const char *idname);
const char *UI_panel_category_active_get(struct ARegion *ar, bool set_fallback);
void UI_panel_category_active_set(struct ARegion *ar, const char *idname);
+void UI_panel_category_active_set_default(struct ARegion *ar, const char *idname);
struct PanelCategoryDyn *UI_panel_category_find_mouse_over_ex(struct ARegion *ar,
const int x,
const int y);
@@ -1711,14 +1715,28 @@ enum {
UI_ITEM_O_RETURN_PROPS = 1 << 0,
UI_ITEM_R_EXPAND = 1 << 1,
UI_ITEM_R_SLIDER = 1 << 2,
+ /**
+ * Use for booleans, causes the button to draw with an outline (emboss),
+ * instead of text with a checkbox.
+ * This is implied when toggle buttons have an icon
+ * unless #UI_ITEM_R_ICON_NEVER flag is set.
+ */
UI_ITEM_R_TOGGLE = 1 << 3,
- UI_ITEM_R_ICON_ONLY = 1 << 4,
- UI_ITEM_R_EVENT = 1 << 5,
- UI_ITEM_R_FULL_EVENT = 1 << 6,
- UI_ITEM_R_NO_BG = 1 << 7,
- UI_ITEM_R_IMMEDIATE = 1 << 8,
- UI_ITEM_O_DEPRESS = 1 << 9,
- UI_ITEM_R_COMPACT = 1 << 10,
+ /**
+ * Don't attempt to use an icon when the icon is set to #ICON_NONE.
+ *
+ * Use for boolean's, causes the buttons to always show as a checkbox
+ * even when there is an icon (which would normally show the button as a toggle).
+ */
+ UI_ITEM_R_ICON_NEVER = 1 << 4,
+ UI_ITEM_R_ICON_ONLY = 1 << 5,
+ UI_ITEM_R_EVENT = 1 << 6,
+ UI_ITEM_R_FULL_EVENT = 1 << 7,
+ UI_ITEM_R_NO_BG = 1 << 8,
+ UI_ITEM_R_IMMEDIATE = 1 << 9,
+ UI_ITEM_O_DEPRESS = 1 << 10,
+ UI_ITEM_R_COMPACT = 1 << 11,
+ UI_ITEM_R_CHECKBOX_INVERT = 1 << 12,
};
#define UI_HEADER_OFFSET ((void)0, 0.4f * UI_UNIT_X)
@@ -2233,6 +2251,7 @@ void uiItemL(uiLayout *layout, const char *name, int icon); /* label */
/* label icon for dragging */
void uiItemLDrag(uiLayout *layout, struct PointerRNA *ptr, const char *name, int icon);
/* menu */
+void uiItemM_ptr(uiLayout *layout, struct MenuType *mt, const char *name, int icon);
void uiItemM(uiLayout *layout, const char *menuname, const char *name, int icon);
/* menu contents */
void uiItemMContents(uiLayout *layout, const char *menuname);
diff --git a/source/blender/editors/include/UI_resources.h b/source/blender/editors/include/UI_resources.h
index 6dc632921ad..db6bb35560d 100644
--- a/source/blender/editors/include/UI_resources.h
+++ b/source/blender/editors/include/UI_resources.h
@@ -105,7 +105,7 @@ typedef enum ThemeColorID {
TH_FACE_DOT,
TH_FACEDOT_SIZE,
TH_CFRAME,
- TH_SCRUBBING_BACKGROUND,
+ TH_TIME_SCRUB_BACKGROUND,
TH_TIME_KEYFRAME,
TH_TIME_GP_KEYFRAME,
TH_NURB_ULINE,
diff --git a/source/blender/editors/include/UI_view2d.h b/source/blender/editors/include/UI_view2d.h
index d03d4b1b4f5..42ac3bb30d8 100644
--- a/source/blender/editors/include/UI_view2d.h
+++ b/source/blender/editors/include/UI_view2d.h
@@ -260,6 +260,6 @@ void UI_view2d_smooth_view(struct bContext *C,
const int smooth_viewtx);
#define UI_MARKER_MARGIN_Y (42 * UI_DPI_FAC)
-#define UI_SCRUBBING_MARGIN_Y (23 * UI_DPI_FAC)
+#define UI_TIME_SCRUB_MARGIN_Y (23 * UI_DPI_FAC)
#endif /* __UI_VIEW2D_H__ */
diff --git a/source/blender/editors/interface/interface.c b/source/blender/editors/interface/interface.c
index f1724d92402..931a4faa1c0 100644
--- a/source/blender/editors/interface/interface.c
+++ b/source/blender/editors/interface/interface.c
@@ -1845,6 +1845,9 @@ int ui_but_is_pushed_ex(uiBut *but, double *value)
}
}
+ if ((but->drawflag & UI_BUT_CHECKBOX_INVERT) && (is_push != -1)) {
+ is_push = !((bool)is_push);
+ }
return is_push;
}
int ui_but_is_pushed(uiBut *but)
@@ -2772,7 +2775,7 @@ bool ui_but_string_set(bContext *C, uiBut *but, const char *str)
}
else if (type == PROP_POINTER) {
if (str[0] == '\0') {
- RNA_property_pointer_set(NULL, &but->rnapoin, but->rnaprop, PointerRNA_NULL);
+ RNA_property_pointer_set(&but->rnapoin, but->rnaprop, PointerRNA_NULL, NULL);
return true;
}
else {
@@ -2788,14 +2791,14 @@ bool ui_but_string_set(bContext *C, uiBut *but, const char *str)
* Fact remains, using editstr as main 'reference' over whole search button thingy
* is utterly weak and should be redesigned imho, but that's not a simple task. */
if (prop && RNA_property_collection_lookup_string(&ptr, prop, str, &rptr)) {
- RNA_property_pointer_set(NULL, &but->rnapoin, but->rnaprop, rptr);
+ RNA_property_pointer_set(&but->rnapoin, but->rnaprop, rptr, NULL);
}
else if (but->func_arg2 != NULL) {
RNA_pointer_create(NULL,
RNA_property_pointer_type(&but->rnapoin, but->rnaprop),
but->func_arg2,
&rptr);
- RNA_property_pointer_set(NULL, &but->rnapoin, but->rnaprop, rptr);
+ RNA_property_pointer_set(&but->rnapoin, but->rnaprop, rptr, NULL);
}
return true;
@@ -3735,6 +3738,16 @@ void ui_def_but_icon(uiBut *but, const int icon, const int flag)
}
}
+/**
+ * Avoid using this where possible since it's better not to ask for an icon in the first place.
+ */
+void ui_def_but_icon_clear(uiBut *but)
+{
+ but->icon = ICON_NONE;
+ but->flag &= ~UI_HAS_ICON;
+ but->drawflag &= ~UI_BUT_ICON_LEFT;
+}
+
static void ui_def_but_rna__disable(uiBut *but, const char *info)
{
but->flag |= UI_BUT_DISABLED;
diff --git a/source/blender/editors/interface/interface_context_menu.c b/source/blender/editors/interface/interface_context_menu.c
index 9ef98db49f5..ca35689112f 100644
--- a/source/blender/editors/interface/interface_context_menu.c
+++ b/source/blender/editors/interface/interface_context_menu.c
@@ -47,6 +47,8 @@
#include "RNA_access.h"
+#include "BPY_extern.h"
+
#include "WM_api.h"
#include "WM_types.h"
@@ -92,7 +94,7 @@ static const char *shortcut_get_operator_property(bContext *C, uiBut *but, IDPro
{
if (but->optype) {
/* Operator */
- *prop = (but->opptr) ? IDP_CopyProperty(but->opptr->data) : NULL;
+ *prop = (but->opptr && but->opptr->data) ? IDP_CopyProperty(but->opptr->data) : NULL;
return but->optype->idname;
}
else if (but->rnaprop) {
@@ -358,7 +360,31 @@ static void ui_but_user_menu_add(bContext *C, uiBut *but, bUserMenu *um)
if (drawstr[0] == '\0') {
/* Hard code overrides for generic operators. */
if (UI_but_is_tool(but)) {
- RNA_string_get(but->opptr, "name", drawstr);
+ char idname[64];
+ RNA_string_get(but->opptr, "name", idname);
+#ifdef WITH_PYTHON
+ {
+ const char *expr_imports[] = {"bpy", "bl_ui", NULL};
+ char expr[256];
+ SNPRINTF(expr,
+ "bl_ui.space_toolsystem_common.item_from_id("
+ "bpy.context, "
+ "bpy.context.space_data.type, "
+ "'%s').label",
+ idname);
+ char *expr_result = NULL;
+ if (BPY_execute_string_as_string(C, expr_imports, expr, true, &expr_result)) {
+ STRNCPY(drawstr, expr_result);
+ MEM_freeN(expr_result);
+ }
+ else {
+ BLI_assert(0);
+ STRNCPY(drawstr, idname);
+ }
+ }
+#else
+ STRNCPY(drawstr, idname);
+#endif
}
}
ED_screen_user_menu_item_add_operator(
diff --git a/source/blender/editors/interface/interface_eyedropper_datablock.c b/source/blender/editors/interface/interface_eyedropper_datablock.c
index 4a2d59c05de..658aa4f67f9 100644
--- a/source/blender/editors/interface/interface_eyedropper_datablock.c
+++ b/source/blender/editors/interface/interface_eyedropper_datablock.c
@@ -207,7 +207,7 @@ static bool datadropper_id_set(bContext *C, DataDropper *ddr, ID *id)
RNA_id_pointer_create(id, &ptr_value);
- RNA_property_pointer_set(NULL, &ddr->ptr, ddr->prop, ptr_value);
+ RNA_property_pointer_set(&ddr->ptr, ddr->prop, ptr_value, NULL);
RNA_property_update(C, &ddr->ptr, ddr->prop);
diff --git a/source/blender/editors/interface/interface_handlers.c b/source/blender/editors/interface/interface_handlers.c
index a3b438ece42..b8e97f58c2f 100644
--- a/source/blender/editors/interface/interface_handlers.c
+++ b/source/blender/editors/interface/interface_handlers.c
@@ -556,18 +556,9 @@ static void ui_but_update_preferences_dirty(uiBut *but)
/* Not very elegant, but ensures preference changes force re-save. */
bool tag = false;
if (but->rnaprop) {
- if (but->rnapoin.data == &U) {
- /* Exclude navigation from setting dirty. */
- extern PropertyRNA rna_Preferences_active_section;
- if (!ELEM(but->rnaprop, &rna_Preferences_active_section)) {
- tag = true;
- }
- }
- else {
- StructRNA *base = RNA_struct_base(but->rnapoin.type);
- if (ELEM(base, &RNA_AddonPreferences, &RNA_KeyConfigPreferences)) {
- tag = true;
- }
+ StructRNA *base = RNA_struct_base(but->rnapoin.type);
+ if (ELEM(base, &RNA_AddonPreferences, &RNA_KeyConfigPreferences, &RNA_KeyMapItem)) {
+ tag = true;
}
}
@@ -1744,7 +1735,7 @@ static void ui_selectcontext_apply(bContext *C,
}
else if (rna_type == PROP_POINTER) {
const PointerRNA other_value = delta.p;
- RNA_property_pointer_set(NULL, &lptr, lprop, other_value);
+ RNA_property_pointer_set(&lptr, lprop, other_value, NULL);
}
RNA_property_update(C, &lptr, prop);
@@ -5572,9 +5563,7 @@ static int ui_do_but_COLOR(bContext *C, uiBut *but, uiHandleButtonData *data, co
if ((int)(but->a1) == UI_PALETTE_COLOR) {
if (!event->ctrl) {
float color[3];
- Scene *scene = CTX_data_scene(C);
- ViewLayer *view_layer = CTX_data_view_layer(C);
- Paint *paint = BKE_paint_get_active(scene, view_layer);
+ Paint *paint = BKE_paint_get_active_from_context(C);
Brush *brush = BKE_paint_brush(paint);
if (brush->flag & BRUSH_USE_GRADIENT) {
@@ -5589,6 +5578,8 @@ static int ui_do_but_COLOR(bContext *C, uiBut *but, uiHandleButtonData *data, co
}
}
else {
+ Scene *scene = CTX_data_scene(C);
+
if (but->rnaprop && RNA_property_subtype(but->rnaprop) == PROP_COLOR_GAMMA) {
RNA_property_float_get_array(&but->rnapoin, but->rnaprop, color);
BKE_brush_color_set(scene, brush, color);
@@ -6530,7 +6521,7 @@ static int ui_do_but_CURVE(
CurveMap *cuma = cumap->cm + cumap->cur;
CurveMapPoint *cmp;
const float m_xy[2] = {mx, my};
- float dist_min_sq = SQUARE(14.0f); /* 14 pixels radius */
+ float dist_min_sq = SQUARE(U.dpi_fac * 14.0f); /* 14 pixels radius */
int sel = -1;
if (event->ctrl) {
@@ -6565,7 +6556,7 @@ static int ui_do_but_CURVE(
BLI_rctf_transform_pt_v(&but->rect, &cumap->curr, f_xy, &cmp[0].x);
/* with 160px height 8px should translate to the old 0.05 coefficient at no zoom */
- dist_min_sq = SQUARE(8.0f);
+ dist_min_sq = SQUARE(U.dpi_fac * 8.0f);
/* loop through the curve segment table and find what's near the mouse. */
for (i = 1; i <= CM_TABLE; i++) {
diff --git a/source/blender/editors/interface/interface_icons.c b/source/blender/editors/interface/interface_icons.c
index e53e9694617..fa3605269ff 100644
--- a/source/blender/editors/interface/interface_icons.c
+++ b/source/blender/editors/interface/interface_icons.c
@@ -1086,6 +1086,12 @@ static void free_iconfile_list(struct ListBase *list)
}
}
+#else
+
+void UI_icons_reload_internal_textures(void)
+{
+}
+
#endif /* WITH_HEADLESS */
int UI_iconfile_get_index(const char *filename)
diff --git a/source/blender/editors/interface/interface_intern.h b/source/blender/editors/interface/interface_intern.h
index 33288df15ba..8a2b28ee2d4 100644
--- a/source/blender/editors/interface/interface_intern.h
+++ b/source/blender/editors/interface/interface_intern.h
@@ -500,6 +500,7 @@ extern int ui_but_string_get_max_length(uiBut *but);
extern uiBut *ui_but_drag_multi_edit_get(uiBut *but);
void ui_def_but_icon(uiBut *but, const int icon, const int flag);
+void ui_def_but_icon_clear(uiBut *but);
extern uiButExtraIconType ui_but_icon_extra_get(uiBut *but);
extern void ui_but_default_set(struct bContext *C, const bool all, const bool use_afterfunc);
diff --git a/source/blender/editors/interface/interface_layout.c b/source/blender/editors/interface/interface_layout.c
index dc57be4f07f..b89767171ab 100644
--- a/source/blender/editors/interface/interface_layout.c
+++ b/source/blender/editors/interface/interface_layout.c
@@ -484,7 +484,7 @@ static void ui_item_array(uiLayout *layout,
int UNUSED(h),
bool expand,
bool slider,
- bool toggle,
+ int toggle,
bool icon_only,
bool compact,
bool show_text)
@@ -691,7 +691,7 @@ static void ui_item_array(uiLayout *layout,
if (slider && but->type == UI_BTYPE_NUM) {
but->type = UI_BTYPE_NUM_SLIDER;
}
- if (toggle && but->type == UI_BTYPE_CHECKBOX) {
+ if ((toggle == 1) && but->type == UI_BTYPE_CHECKBOX) {
but->type = UI_BTYPE_TOGGLE;
}
if ((a == 0) && (subtype == PROP_AXISANGLE)) {
@@ -1858,12 +1858,7 @@ void uiItemFullR(uiLayout *layout,
int icon)
{
uiBlock *block = layout->root->block;
- uiBut *but = NULL;
- PropertyType type;
char namestr[UI_MAX_NAME_STR];
- int len, w, h;
- bool slider, toggle, expand, icon_only, no_bg, compact;
- bool is_array;
const bool use_prop_sep = ((layout->item.flag & UI_ITEM_PROP_SEP) != 0);
/* By default 'use_prop_sep' uses a separate column for labels.
@@ -1888,11 +1883,15 @@ void uiItemFullR(uiLayout *layout,
UI_block_layout_set_current(block, layout);
/* retrieve info */
- type = RNA_property_type(prop);
- is_array = RNA_property_array_check(prop);
- len = (is_array) ? RNA_property_array_length(ptr, prop) : 0;
+ const PropertyType type = RNA_property_type(prop);
+ const bool is_array = RNA_property_array_check(prop);
+ const int len = (is_array) ? RNA_property_array_length(ptr, prop) : 0;
+
+ const bool icon_only = (flag & UI_ITEM_R_ICON_ONLY) != 0;
- icon_only = (flag & UI_ITEM_R_ICON_ONLY) != 0;
+ /* Boolean with -1 to signify that the value depends on the presence of an icon. */
+ const int toggle = ((flag & UI_ITEM_R_TOGGLE) ? 1 : ((flag & UI_ITEM_R_ICON_NEVER) ? 0 : -1));
+ const bool no_icon = (toggle == 0);
/* set name and icon */
if (!name) {
@@ -1904,8 +1903,8 @@ void uiItemFullR(uiLayout *layout,
}
}
- if (icon == ICON_NONE) {
- icon = RNA_property_ui_icon(prop);
+ if (type != PROP_BOOLEAN) {
+ flag &= ~UI_ITEM_R_CHECKBOX_INVERT;
}
if (flag & UI_ITEM_R_ICON_ONLY) {
@@ -1932,56 +1931,66 @@ void uiItemFullR(uiLayout *layout,
}
}
-#ifdef UI_PROP_SEP_ICON_WIDTH_EXCEPTION
- if (use_prop_sep) {
- if (type == PROP_BOOLEAN && (icon == ICON_NONE) && !icon_only) {
- use_prop_sep_split_label = false;
+ if (no_icon == false) {
+ if (icon == ICON_NONE) {
+ icon = RNA_property_ui_icon(prop);
}
- }
-#endif
- /* menus and pie-menus don't show checkbox without this */
- if ((layout->root->type == UI_LAYOUT_MENU) ||
- /* use checkboxes only as a fallback in pie-menu's, when no icon is defined */
- ((layout->root->type == UI_LAYOUT_PIEMENU) && (icon == ICON_NONE))) {
- int prop_flag = RNA_property_flag(prop);
- if (type == PROP_BOOLEAN && ((is_array == false) || (index != RNA_NO_INDEX))) {
- if (prop_flag & PROP_ICONS_CONSECUTIVE) {
- icon = ICON_CHECKBOX_DEHLT; /* but->iconadd will set to correct icon */
- }
- else if (is_array) {
- icon = (RNA_property_boolean_get_index(ptr, prop, index)) ? ICON_CHECKBOX_HLT :
- ICON_CHECKBOX_DEHLT;
+ /* Menus and pie-menus don't show checkbox without this. */
+ if ((layout->root->type == UI_LAYOUT_MENU) ||
+ /* Use checkboxes only as a fallback in pie-menu's, when no icon is defined. */
+ ((layout->root->type == UI_LAYOUT_PIEMENU) && (icon == ICON_NONE))) {
+ int prop_flag = RNA_property_flag(prop);
+ if (type == PROP_BOOLEAN) {
+ if ((is_array == false) || (index != RNA_NO_INDEX)) {
+ if (prop_flag & PROP_ICONS_CONSECUTIVE) {
+ icon = ICON_CHECKBOX_DEHLT; /* but->iconadd will set to correct icon */
+ }
+ else if (is_array) {
+ icon = (RNA_property_boolean_get_index(ptr, prop, index)) ? ICON_CHECKBOX_HLT :
+ ICON_CHECKBOX_DEHLT;
+ }
+ else {
+ icon = (RNA_property_boolean_get(ptr, prop)) ? ICON_CHECKBOX_HLT : ICON_CHECKBOX_DEHLT;
+ }
+ }
}
- else {
- icon = (RNA_property_boolean_get(ptr, prop)) ? ICON_CHECKBOX_HLT : ICON_CHECKBOX_DEHLT;
+ else if (type == PROP_ENUM) {
+ if (index == RNA_ENUM_VALUE) {
+ int enum_value = RNA_property_enum_get(ptr, prop);
+ if (prop_flag & PROP_ICONS_CONSECUTIVE) {
+ icon = ICON_CHECKBOX_DEHLT; /* but->iconadd will set to correct icon */
+ }
+ else if (prop_flag & PROP_ENUM_FLAG) {
+ icon = (enum_value & value) ? ICON_CHECKBOX_HLT : ICON_CHECKBOX_DEHLT;
+ }
+ else {
+ icon = (enum_value == value) ? ICON_CHECKBOX_HLT : ICON_CHECKBOX_DEHLT;
+ }
+ }
}
}
- else if (type == PROP_ENUM && index == RNA_ENUM_VALUE) {
- int enum_value = RNA_property_enum_get(ptr, prop);
- if (prop_flag & PROP_ICONS_CONSECUTIVE) {
- icon = ICON_CHECKBOX_DEHLT; /* but->iconadd will set to correct icon */
- }
- else if (prop_flag & PROP_ENUM_FLAG) {
- icon = (enum_value & value) ? ICON_CHECKBOX_HLT : ICON_CHECKBOX_DEHLT;
- }
- else {
- icon = (enum_value == value) ? ICON_CHECKBOX_HLT : ICON_CHECKBOX_DEHLT;
- }
+ }
+
+#ifdef UI_PROP_SEP_ICON_WIDTH_EXCEPTION
+ if (use_prop_sep) {
+ if (type == PROP_BOOLEAN && (icon == ICON_NONE) && !icon_only) {
+ use_prop_sep_split_label = false;
}
}
+#endif
if ((type == PROP_ENUM) && (RNA_property_flag(prop) & PROP_ENUM_FLAG)) {
flag |= UI_ITEM_R_EXPAND;
}
- slider = (flag & UI_ITEM_R_SLIDER) != 0;
- toggle = (flag & UI_ITEM_R_TOGGLE) != 0;
- expand = (flag & UI_ITEM_R_EXPAND) != 0;
- no_bg = (flag & UI_ITEM_R_NO_BG) != 0;
- compact = (flag & UI_ITEM_R_COMPACT) != 0;
+ const bool slider = (flag & UI_ITEM_R_SLIDER) != 0;
+ const bool expand = (flag & UI_ITEM_R_EXPAND) != 0;
+ const bool no_bg = (flag & UI_ITEM_R_NO_BG) != 0;
+ const bool compact = (flag & UI_ITEM_R_COMPACT) != 0;
/* get size */
+ int w, h;
ui_item_rna_size(layout, name, icon, ptr, prop, index, icon_only, compact, &w, &h);
int prev_emboss = layout->emboss;
@@ -1989,6 +1998,8 @@ void uiItemFullR(uiLayout *layout,
layout->emboss = UI_EMBOSS_NONE;
}
+ uiBut *but = NULL;
+
/* Split the label / property. */
uiLayout *layout_parent = layout;
if (use_prop_sep) {
@@ -2156,7 +2167,13 @@ void uiItemFullR(uiLayout *layout,
but->type = UI_BTYPE_NUM_SLIDER;
}
- if (toggle && but->type == UI_BTYPE_CHECKBOX) {
+ if (flag & UI_ITEM_R_CHECKBOX_INVERT) {
+ if (ELEM(but->type, UI_BTYPE_CHECKBOX, UI_BTYPE_CHECKBOX_N)) {
+ but->drawflag |= UI_BUT_CHECKBOX_INVERT;
+ }
+ }
+
+ if ((toggle == 1) && but->type == UI_BTYPE_CHECKBOX) {
but->type = UI_BTYPE_TOGGLE;
}
@@ -2175,6 +2192,18 @@ void uiItemFullR(uiLayout *layout,
}
}
+ /* The resulting button may have the icon set since boolean button drawing
+ * is being 'helpful' and adding an icon for us.
+ * In this case we want the ability not to have an icon.
+ *
+ * We could pass an argument not to set the icon to begin with however this is the one case
+ * the functionality is needed. */
+ if (but && no_icon) {
+ if ((icon == ICON_NONE) && (but->icon != ICON_NONE)) {
+ ui_def_but_icon_clear(but);
+ }
+ }
+
/* Mark non-embossed textfields inside a listbox. */
if (but && (block->flag & UI_BLOCK_LIST_ITEM) && (but->type == UI_BTYPE_TEXT) &&
(but->dt & UI_EMBOSS_NONE)) {
@@ -2744,14 +2773,8 @@ static uiBut *ui_item_menu(uiLayout *layout,
return but;
}
-void uiItemM(uiLayout *layout, const char *menuname, const char *name, int icon)
+void uiItemM_ptr(uiLayout *layout, MenuType *mt, const char *name, int icon)
{
- MenuType *mt = WM_menutype_find(menuname, false);
- if (mt == NULL) {
- RNA_warning("not found %s", menuname);
- return;
- }
-
if (!name) {
name = CTX_IFACE_(mt->translation_context, mt->label);
}
@@ -2770,6 +2793,16 @@ void uiItemM(uiLayout *layout, const char *menuname, const char *name, int icon)
false);
}
+void uiItemM(uiLayout *layout, const char *menuname, const char *name, int icon)
+{
+ MenuType *mt = WM_menutype_find(menuname, false);
+ if (mt == NULL) {
+ RNA_warning("not found %s", menuname);
+ return;
+ }
+ uiItemM_ptr(layout, mt, name, icon);
+}
+
void uiItemMContents(uiLayout *layout, const char *menuname)
{
MenuType *mt = WM_menutype_find(menuname, false);
diff --git a/source/blender/editors/interface/interface_panel.c b/source/blender/editors/interface/interface_panel.c
index aa7ff015bad..9c5ce0c9d2c 100644
--- a/source/blender/editors/interface/interface_panel.c
+++ b/source/blender/editors/interface/interface_panel.c
@@ -367,7 +367,7 @@ Panel *UI_panel_begin(
return pa;
}
-void UI_panel_end(uiBlock *block, int width, int height)
+void UI_panel_end(uiBlock *block, int width, int height, bool open)
{
Panel *pa = block->panel;
@@ -390,21 +390,21 @@ void UI_panel_end(uiBlock *block, int width, int height)
pa->sizey = height;
}
else {
- /* check if we need to do an animation */
- if (!ELEM(width, 0, pa->sizex) || !ELEM(height, 0, pa->sizey)) {
- pa->runtime_flag |= PNL_ANIM_ALIGN;
- if (height != 0) {
- pa->ofsy += pa->sizey - height;
- }
- }
+ int old_sizex = pa->sizex, old_sizey = pa->sizey;
/* update width/height if non-zero */
if (width != 0) {
pa->sizex = width;
}
- if (height != 0) {
+ if (height != 0 || open) {
pa->sizey = height;
}
+
+ /* check if we need to do an animation */
+ if (pa->sizex != old_sizex || pa->sizey != old_sizey) {
+ pa->runtime_flag |= PNL_ANIM_ALIGN;
+ pa->ofsy += old_sizey - pa->sizey;
+ }
}
}
@@ -1676,28 +1676,7 @@ PanelCategoryStack *UI_panel_category_active_find(ARegion *ar, const char *idnam
return BLI_findstring(&ar->panels_category_active, idname, offsetof(PanelCategoryStack, idname));
}
-const char *UI_panel_category_active_get(ARegion *ar, bool set_fallback)
-{
- PanelCategoryStack *pc_act;
-
- for (pc_act = ar->panels_category_active.first; pc_act; pc_act = pc_act->next) {
- if (UI_panel_category_find(ar, pc_act->idname)) {
- return pc_act->idname;
- }
- }
-
- if (set_fallback) {
- PanelCategoryDyn *pc_dyn = ar->panels_category.first;
- if (pc_dyn) {
- UI_panel_category_active_set(ar, pc_dyn->idname);
- return pc_dyn->idname;
- }
- }
-
- return NULL;
-}
-
-void UI_panel_category_active_set(ARegion *ar, const char *idname)
+static void ui_panel_category_active_set(ARegion *ar, const char *idname, bool fallback)
{
ListBase *lb = &ar->panels_category_active;
PanelCategoryStack *pc_act = UI_panel_category_active_find(ar, idname);
@@ -1710,7 +1689,13 @@ void UI_panel_category_active_set(ARegion *ar, const char *idname)
BLI_strncpy(pc_act->idname, idname, sizeof(pc_act->idname));
}
- BLI_addhead(lb, pc_act);
+ if (fallback) {
+ /* For fallbacks, add at the end so explicitly chosen categories have priority. */
+ BLI_addtail(lb, pc_act);
+ }
+ else {
+ BLI_addhead(lb, pc_act);
+ }
/* validate all active panels, we could do this on load,
* they are harmless - but we should remove somewhere.
@@ -1729,6 +1714,39 @@ void UI_panel_category_active_set(ARegion *ar, const char *idname)
}
}
+void UI_panel_category_active_set(ARegion *ar, const char *idname)
+{
+ ui_panel_category_active_set(ar, idname, false);
+}
+
+void UI_panel_category_active_set_default(ARegion *ar, const char *idname)
+{
+ if (!UI_panel_category_active_find(ar, idname)) {
+ ui_panel_category_active_set(ar, idname, true);
+ }
+}
+
+const char *UI_panel_category_active_get(ARegion *ar, bool set_fallback)
+{
+ PanelCategoryStack *pc_act;
+
+ for (pc_act = ar->panels_category_active.first; pc_act; pc_act = pc_act->next) {
+ if (UI_panel_category_find(ar, pc_act->idname)) {
+ return pc_act->idname;
+ }
+ }
+
+ if (set_fallback) {
+ PanelCategoryDyn *pc_dyn = ar->panels_category.first;
+ if (pc_dyn) {
+ ui_panel_category_active_set(ar, pc_dyn->idname, true);
+ return pc_dyn->idname;
+ }
+ }
+
+ return NULL;
+}
+
PanelCategoryDyn *UI_panel_category_find_mouse_over_ex(ARegion *ar, const int x, const int y)
{
PanelCategoryDyn *ptd;
diff --git a/source/blender/editors/interface/interface_region_tooltip.c b/source/blender/editors/interface/interface_region_tooltip.c
index 5b205de21b8..6c780482777 100644
--- a/source/blender/editors/interface/interface_region_tooltip.c
+++ b/source/blender/editors/interface/interface_region_tooltip.c
@@ -883,8 +883,7 @@ static uiTooltipData *ui_tooltip_data_from_gizmo(bContext *C, wmGizmo *gz)
/* Operator Actions */
{
- bool use_drag = gz->drag_part != -1 && gz->highlight_part != gz->drag_part;
-
+ const bool use_drag = gz->drag_part != -1 && gz->highlight_part != gz->drag_part;
const struct {
int part;
const char *prefix;
diff --git a/source/blender/editors/interface/interface_templates.c b/source/blender/editors/interface/interface_templates.c
index 3dbfd3d2f6a..33602818fd4 100644
--- a/source/blender/editors/interface/interface_templates.c
+++ b/source/blender/editors/interface/interface_templates.c
@@ -298,7 +298,7 @@ static void template_ID_set_property_cb(bContext *C, void *arg_template, void *i
PointerRNA idptr;
RNA_id_pointer_create(item, &idptr);
- RNA_property_pointer_set(NULL, &template_ui->ptr, template_ui->prop, idptr);
+ RNA_property_pointer_set(&template_ui->ptr, template_ui->prop, idptr, NULL);
RNA_property_update(C, &template_ui->ptr, template_ui->prop);
}
}
@@ -489,7 +489,7 @@ static void template_id_cb(bContext *C, void *arg_litem, void *arg_event)
break;
case UI_ID_DELETE:
memset(&idptr, 0, sizeof(idptr));
- RNA_property_pointer_set(NULL, &template_ui->ptr, template_ui->prop, idptr);
+ RNA_property_pointer_set(&template_ui->ptr, template_ui->prop, idptr, NULL);
RNA_property_update(C, &template_ui->ptr, template_ui->prop);
if (id && CTX_wm_window(C)->eventstate->shift) {
@@ -532,7 +532,7 @@ static void template_id_cb(bContext *C, void *arg_litem, void *arg_event)
idptr = RNA_property_pointer_get(&template_ui->ptr, template_ui->prop);
}
}
- RNA_property_pointer_set(NULL, &template_ui->ptr, template_ui->prop, idptr);
+ RNA_property_pointer_set(&template_ui->ptr, template_ui->prop, idptr, NULL);
RNA_property_update(C, &template_ui->ptr, template_ui->prop);
}
break;
@@ -541,7 +541,7 @@ static void template_id_cb(bContext *C, void *arg_litem, void *arg_event)
BKE_override_static_free(&id->override_static);
/* reassign to get get proper updates/notifiers */
idptr = RNA_property_pointer_get(&template_ui->ptr, template_ui->prop);
- RNA_property_pointer_set(NULL, &template_ui->ptr, template_ui->prop, idptr);
+ RNA_property_pointer_set(&template_ui->ptr, template_ui->prop, idptr, NULL);
RNA_property_update(C, &template_ui->ptr, template_ui->prop);
}
break;
@@ -1455,7 +1455,7 @@ static void template_search_handle_cb(bContext *C, void *arg_template, void *ite
PointerRNA item_ptr;
RNA_pointer_create(NULL, type, item, &item_ptr);
- RNA_property_pointer_set(NULL, &coll_search->target_ptr, coll_search->target_prop, item_ptr);
+ RNA_property_pointer_set(&coll_search->target_ptr, coll_search->target_prop, item_ptr, NULL);
RNA_property_update(C, &coll_search->target_ptr, coll_search->target_prop);
}
diff --git a/source/blender/editors/interface/interface_widgets.c b/source/blender/editors/interface/interface_widgets.c
index 594793371ae..71629d6297c 100644
--- a/source/blender/editors/interface/interface_widgets.c
+++ b/source/blender/editors/interface/interface_widgets.c
@@ -1261,7 +1261,9 @@ void UI_widgetbase_draw_cache_flush(void)
(float *)g_widget_base_batch.params);
GPU_batch_uniform_3fv(batch, "checkerColorAndSize", checker_params);
GPU_matrix_bind(batch->interface);
- GPU_batch_draw_range_ex(batch, 0, g_widget_base_batch.count, true);
+ GPU_batch_bind(batch);
+ GPU_batch_draw_advanced(batch, 0, 0, 0, g_widget_base_batch.count);
+
GPU_batch_program_use_end(batch);
}
g_widget_base_batch.count = 0;
@@ -1946,9 +1948,9 @@ static void ui_text_clip_right_label(const uiFontStyle *fstyle, uiBut *but, cons
}
#ifdef WITH_INPUT_IME
-static void widget_draw_text_ime_underline(uiFontStyle *fstyle,
- uiWidgetColors *wcol,
- uiBut *but,
+static void widget_draw_text_ime_underline(const uiFontStyle *fstyle,
+ const uiWidgetColors *wcol,
+ const uiBut *but,
const rcti *rect,
const wmIMEData *ime_data,
const char *drawstr)
@@ -2183,7 +2185,7 @@ static void widget_draw_text(const uiFontStyle *fstyle,
ELEM(but->type, UI_BTYPE_NUM, UI_BTYPE_NUM_SLIDER) &&
/* if we're editing or multi-drag (fake editing), then use left alignment */
(but->editstr == NULL) && (drawstr == but->drawstr)) {
- drawstr_right = strchr(drawstr + but->ofs, ':');
+ drawstr_right = strrchr(drawstr + but->ofs, ':');
if (drawstr_right) {
drawstr_right++;
drawstr_left_len = (drawstr_right - drawstr);
diff --git a/source/blender/editors/interface/resources.c b/source/blender/editors/interface/resources.c
index 06acf59e07c..26beb08dd28 100644
--- a/source/blender/editors/interface/resources.c
+++ b/source/blender/editors/interface/resources.c
@@ -309,8 +309,8 @@ const uchar *UI_ThemeGetColorPtr(bTheme *btheme, int spacetype, int colorid)
case TH_GRID:
cp = ts->grid;
break;
- case TH_SCRUBBING_BACKGROUND:
- cp = ts->scrubbing_background;
+ case TH_TIME_SCRUB_BACKGROUND:
+ cp = ts->time_scrub_background;
break;
case TH_VIEW_OVERLAY:
cp = ts->view_overlay;
diff --git a/source/blender/editors/interface/view2d.c b/source/blender/editors/interface/view2d.c
index f2d4faff479..36b984e229b 100644
--- a/source/blender/editors/interface/view2d.c
+++ b/source/blender/editors/interface/view2d.c
@@ -190,7 +190,7 @@ static void view2d_masks(View2D *v2d, bool check_scrollers, const rcti *mask_scr
* also have the scrubbing area at the top.
* So the scrollbar has to move down a bit. */
if (scroll & V2D_SCROLL_VERTICAL_HANDLES) {
- v2d->vert.ymax -= UI_SCRUBBING_MARGIN_Y;
+ v2d->vert.ymax -= UI_TIME_SCRUB_MARGIN_Y;
}
/* horizontal scroller */
diff --git a/source/blender/editors/interface/view2d_draw.c b/source/blender/editors/interface/view2d_draw.c
index 2568193ee23..43b49825219 100644
--- a/source/blender/editors/interface/view2d_draw.c
+++ b/source/blender/editors/interface/view2d_draw.c
@@ -53,7 +53,7 @@
/* Compute display grid resolution
********************************************************/
-#define MIN_MAJOR_LINE_DISTANCE (UI_DPI_FAC * 50)
+#define MIN_MAJOR_LINE_DISTANCE (U.v2d_min_gridsize * UI_DPI_FAC)
static float select_major_distance(const float *possible_distances,
uint amount,
@@ -267,6 +267,10 @@ static void draw_horizontal_scale_indicators(const ARegion *ar,
void *to_string_data,
int colorid)
{
+ if (UI_view2d_scale_get_x(v2d) <= 0.0f) {
+ return;
+ }
+
GPU_matrix_push_projection();
wmOrtho2_region_pixelspace(ar);
@@ -318,6 +322,10 @@ static void draw_vertical_scale_indicators(const ARegion *ar,
void *to_string_data,
int colorid)
{
+ if (UI_view2d_scale_get_y(v2d) <= 0.0f) {
+ return;
+ }
+
GPU_matrix_push_projection();
wmOrtho2_region_pixelspace(ar);
diff --git a/source/blender/editors/io/io_cache.c b/source/blender/editors/io/io_cache.c
index e2b3b6aa8c6..9fdcec71cfd 100644
--- a/source/blender/editors/io/io_cache.c
+++ b/source/blender/editors/io/io_cache.c
@@ -108,7 +108,7 @@ static int cachefile_open_exec(bContext *C, wmOperator *op)
PointerRNA idptr;
RNA_id_pointer_create(&cache_file->id, &idptr);
- RNA_property_pointer_set(NULL, &pprop->ptr, pprop->prop, idptr);
+ RNA_property_pointer_set(&pprop->ptr, pprop->prop, idptr, NULL);
RNA_property_update(C, &pprop->ptr, pprop->prop);
}
diff --git a/source/blender/editors/io/io_collada.c b/source/blender/editors/io/io_collada.c
index 9796bf89cf3..1f844961d19 100644
--- a/source/blender/editors/io/io_collada.c
+++ b/source/blender/editors/io/io_collada.c
@@ -81,6 +81,9 @@ static int wm_collada_export_exec(bContext *C, wmOperator *op)
{
char filepath[FILE_MAX];
int apply_modifiers;
+ int global_forward;
+ int global_up;
+ int apply_global_orientation;
int export_mesh_type;
int selected;
int include_children;
@@ -103,7 +106,8 @@ static int wm_collada_export_exec(bContext *C, wmOperator *op)
int use_object_instantiation;
int use_blender_profile;
int sort_by_name;
- int export_transformation_type;
+ int export_object_transformation_type;
+ int export_animation_transformation_type;
int open_sim;
int limit_precision;
@@ -140,6 +144,10 @@ static int wm_collada_export_exec(bContext *C, wmOperator *op)
/* Options panel */
apply_modifiers = RNA_boolean_get(op->ptr, "apply_modifiers");
export_mesh_type = RNA_enum_get(op->ptr, "export_mesh_type_selection");
+ global_forward = RNA_enum_get(op->ptr, "export_global_forward_selection");
+ global_up = RNA_enum_get(op->ptr, "export_global_up_selection");
+ apply_global_orientation = RNA_boolean_get(op->ptr, "apply_global_orientation");
+
selected = RNA_boolean_get(op->ptr, "selected");
include_children = RNA_boolean_get(op->ptr, "include_children");
include_armatures = RNA_boolean_get(op->ptr, "include_armatures");
@@ -163,9 +171,13 @@ static int wm_collada_export_exec(bContext *C, wmOperator *op)
use_object_instantiation = RNA_boolean_get(op->ptr, "use_object_instantiation");
use_blender_profile = RNA_boolean_get(op->ptr, "use_blender_profile");
sort_by_name = RNA_boolean_get(op->ptr, "sort_by_name");
- export_transformation_type = RNA_enum_get(op->ptr, "export_transformation_type_selection");
- open_sim = RNA_boolean_get(op->ptr, "open_sim");
+ export_object_transformation_type = RNA_enum_get(op->ptr,
+ "export_object_transformation_type_selection");
+ export_animation_transformation_type = RNA_enum_get(
+ op->ptr, "export_animation_transformation_type_selection");
+
+ open_sim = RNA_boolean_get(op->ptr, "open_sim");
limit_precision = RNA_boolean_get(op->ptr, "limit_precision");
keep_bind_info = RNA_boolean_get(op->ptr, "keep_bind_info");
@@ -181,6 +193,10 @@ static int wm_collada_export_exec(bContext *C, wmOperator *op)
export_settings.filepath = filepath;
export_settings.apply_modifiers = apply_modifiers != 0;
+ export_settings.global_forward = global_forward;
+ export_settings.global_up = global_up;
+ export_settings.apply_global_orientation = apply_global_orientation != 0;
+
export_settings.export_mesh_type = export_mesh_type;
export_settings.selected = selected != 0;
export_settings.include_children = include_children != 0;
@@ -201,23 +217,24 @@ static int wm_collada_export_exec(bContext *C, wmOperator *op)
export_settings.use_object_instantiation = use_object_instantiation != 0;
export_settings.use_blender_profile = use_blender_profile != 0;
export_settings.sort_by_name = sort_by_name != 0;
+ export_settings.object_transformation_type = export_object_transformation_type;
+ export_settings.animation_transformation_type = export_animation_transformation_type;
+ export_settings.keep_smooth_curves = keep_smooth_curves != 0;
- if (export_animation_type == BC_ANIMATION_EXPORT_SAMPLES) {
- export_settings.export_transformation_type = export_transformation_type;
- }
- else {
+ if (export_animation_type != BC_ANIMATION_EXPORT_SAMPLES) {
// When curves are exported then we can not export as matrix
- export_settings.export_transformation_type = BC_TRANSFORMATION_TYPE_TRANSROTLOC;
+ export_settings.animation_transformation_type = BC_TRANSFORMATION_TYPE_DECOMPOSED;
}
- if (export_settings.export_transformation_type == BC_TRANSFORMATION_TYPE_TRANSROTLOC) {
- export_settings.keep_smooth_curves = keep_smooth_curves != 0;
- }
- else {
+ if (export_settings.animation_transformation_type != BC_TRANSFORMATION_TYPE_DECOMPOSED) {
// Can not export smooth curves when Matrix export is enabled.
export_settings.keep_smooth_curves = false;
}
+ if (include_animations) {
+ export_settings.object_transformation_type = export_settings.animation_transformation_type;
+ }
+
export_settings.open_sim = open_sim != 0;
export_settings.limit_precision = limit_precision != 0;
export_settings.keep_bind_info = keep_bind_info != 0;
@@ -250,14 +267,15 @@ static int wm_collada_export_exec(bContext *C, wmOperator *op)
static void uiCollada_exportSettings(uiLayout *layout, PointerRNA *imfptr)
{
- uiLayout *box, *row, *col, *split;
+ uiLayout *bbox, *box, *row, *col, *split;
bool include_animations = RNA_boolean_get(imfptr, "include_animations");
int ui_section = RNA_enum_get(imfptr, "prop_bc_export_ui_section");
BC_export_animation_type animation_type = RNA_enum_get(imfptr,
"export_animation_type_selection");
- BC_export_transformation_type transformation_type = RNA_enum_get(
- imfptr, "export_transformation_type_selection");
+
+ BC_export_transformation_type animation_transformation_type = RNA_enum_get(
+ imfptr, "export_animation_transformation_type_selection");
bool sampling = animation_type == BC_ANIMATION_EXPORT_SAMPLES;
@@ -272,6 +290,18 @@ static void uiCollada_exportSettings(uiLayout *layout, PointerRNA *imfptr)
/* Export Data options */
/* =================== */
+ bbox = uiLayoutBox(layout);
+ row = uiLayoutRow(bbox, false);
+ uiItemL(row, IFACE_("Global Orientation:"), ICON_ORIENTATION_GLOBAL);
+ row = uiLayoutRow(bbox, false);
+ uiItemR(row, imfptr, "export_global_forward_selection", 0, "", ICON_NONE);
+
+ row = uiLayoutRow(bbox, false);
+ uiItemR(row, imfptr, "export_global_up_selection", 0, "", ICON_NONE);
+
+ row = uiLayoutRow(bbox, false);
+ uiItemR(row, imfptr, "apply_global_orientation", 0, NULL, ICON_NONE);
+
row = uiLayoutRow(box, false);
uiItemR(row, imfptr, "selected", 0, NULL, ICON_NONE);
@@ -287,6 +317,8 @@ static void uiCollada_exportSettings(uiLayout *layout, PointerRNA *imfptr)
uiItemR(row, imfptr, "include_shapekeys", 0, NULL, ICON_NONE);
uiLayoutSetEnabled(row, RNA_boolean_get(imfptr, "selected"));
+ row = uiLayoutRow(box, false);
+
/* Texture options */
box = uiLayoutBox(layout);
row = uiLayoutRow(box, false);
@@ -304,13 +336,26 @@ static void uiCollada_exportSettings(uiLayout *layout, PointerRNA *imfptr)
row = uiLayoutRow(box, false);
split = uiLayoutSplit(row, 0.6f, UI_LAYOUT_ALIGN_RIGHT);
+
col = uiLayoutColumn(split, false);
uiItemR(col, imfptr, "apply_modifiers", 0, NULL, ICON_NONE);
+
col = uiLayoutColumn(split, false);
uiItemR(col, imfptr, "export_mesh_type_selection", 0, "", ICON_NONE);
uiLayoutSetEnabled(col, RNA_boolean_get(imfptr, "apply_modifiers"));
+
+ col = uiLayoutColumn(box, false);
+ uiItemR(col, imfptr, "triangulate", 1, NULL, ICON_NONE);
+
row = uiLayoutRow(box, false);
- uiItemR(row, imfptr, "triangulate", 1, NULL, ICON_NONE);
+ split = uiLayoutSplit(row, 0.6f, UI_LAYOUT_ALIGN_RIGHT);
+ uiItemL(split, IFACE_("Transformation Type"), ICON_NONE);
+ if (RNA_boolean_get(imfptr, "include_animations")) {
+ uiItemR(split, imfptr, "export_animation_transformation_type_selection", 0, "", ICON_NONE);
+ }
+ else {
+ uiItemR(split, imfptr, "export_object_transformation_type_selection", 0, "", ICON_NONE);
+ }
}
else if (ui_section == BC_UI_SECTION_ARMATURE) {
/* Armature options */
@@ -335,18 +380,24 @@ static void uiCollada_exportSettings(uiLayout *layout, PointerRNA *imfptr)
row = uiLayoutRow(box, false);
uiItemR(row, imfptr, "export_animation_type_selection", UI_ITEM_R_EXPAND, NULL, ICON_NONE);
+ uiLayoutSetEnabled(row, include_animations);
row = uiLayoutRow(box, false);
split = uiLayoutSplit(row, 0.6f, UI_LAYOUT_ALIGN_RIGHT);
uiItemL(split, IFACE_("Transformation Type"), ICON_NONE);
- uiItemR(split, imfptr, "export_transformation_type_selection", 0, "", ICON_NONE);
- uiLayoutSetEnabled(row, animation_type == BC_ANIMATION_EXPORT_SAMPLES);
+ if (RNA_boolean_get(imfptr, "include_animations")) {
+ uiItemR(split, imfptr, "export_animation_transformation_type_selection", 0, "", ICON_NONE);
+ }
+ else {
+ uiItemR(split, imfptr, "export_object_transformation_type_selection", 0, "", ICON_NONE);
+ }
+ uiLayoutSetEnabled(row, include_animations && animation_type == BC_ANIMATION_EXPORT_SAMPLES);
row = uiLayoutColumn(box, false);
uiItemR(row, imfptr, "keep_smooth_curves", 0, NULL, ICON_NONE);
uiLayoutSetEnabled(row,
include_animations &&
- (transformation_type == BC_TRANSFORMATION_TYPE_TRANSROTLOC ||
+ (animation_transformation_type == BC_TRANSFORMATION_TYPE_DECOMPOSED ||
animation_type == BC_ANIMATION_EXPORT_KEYS));
row = uiLayoutColumn(box, false);
@@ -359,6 +410,7 @@ static void uiCollada_exportSettings(uiLayout *layout, PointerRNA *imfptr)
row = uiLayoutColumn(box, false);
uiItemR(row, imfptr, "keep_flat_curves", 0, NULL, ICON_NONE);
+ uiLayoutSetEnabled(row, include_animations);
row = uiLayoutRow(box, false);
uiItemR(row, imfptr, "include_all_actions", 0, NULL, ICON_NONE);
@@ -418,17 +470,37 @@ void WM_OT_collada_export(wmOperatorType *ot)
{0, NULL, 0, NULL, NULL},
};
+ static const EnumPropertyItem prop_bc_export_global_forward[] = {
+ {BC_GLOBAL_FORWARD_X, "X", 0, "X Forward", "Global Forward is positive X Axis"},
+ {BC_GLOBAL_FORWARD_Y, "Y", 0, "Y Forward", "Global Forward is positive Y Axis"},
+ {BC_GLOBAL_FORWARD_Z, "Z", 0, "Z Forward", "Global Forward is positive Z Axis"},
+ {BC_GLOBAL_FORWARD_MINUS_X, "-X", 0, "-X Forward", "Global Forward is negative X Axis"},
+ {BC_GLOBAL_FORWARD_MINUS_Y, "-Y", 0, "-Y Forward", "Global Forward is negative Y Axis"},
+ {BC_GLOBAL_FORWARD_MINUS_Z, "-Z", 0, "-Z Forward", "Global Forward is negative Z Axis"},
+ {0, NULL, 0, NULL, NULL},
+ };
+
+ static const EnumPropertyItem prop_bc_export_global_up[] = {
+ {BC_GLOBAL_UP_X, "X", 0, "X Up", "Global UP is positive X Axis"},
+ {BC_GLOBAL_UP_Y, "Y", 0, "Y Up", "Global UP is positive Y Axis"},
+ {BC_GLOBAL_UP_Z, "Z", 0, "Z Up", "Global UP is positive Z Axis"},
+ {BC_GLOBAL_UP_MINUS_X, "-X", 0, "-X Up", "Global UP is negative X Axis"},
+ {BC_GLOBAL_UP_MINUS_Y, "-Y", 0, "-Y Up", "Global UP is negative Y Axis"},
+ {BC_GLOBAL_UP_MINUS_Z, "-Z", 0, "-Z Up", "Global UP is negative Z Axis"},
+ {0, NULL, 0, NULL, NULL},
+ };
+
static const EnumPropertyItem prop_bc_export_transformation_type[] = {
{BC_TRANSFORMATION_TYPE_MATRIX,
"matrix",
0,
"Matrix",
- "Use <matrix> to specify transformations"},
- {BC_TRANSFORMATION_TYPE_TRANSROTLOC,
- "transrotloc",
+ "Use <matrix> representation for exported transformations"},
+ {BC_TRANSFORMATION_TYPE_DECOMPOSED,
+ "decomposed",
0,
- "TransRotLoc",
- "Use <translate>, <rotate>, <scale> to specify transformations"},
+ "Decomposed",
+ "Use <rotate>, <translate> and <scale> representation for exported transformations"},
{0, NULL, 0, NULL, NULL}};
static const EnumPropertyItem prop_bc_export_animation_type[] = {
@@ -503,6 +575,27 @@ void WM_OT_collada_export(wmOperatorType *ot)
"Resolution",
"Modifier resolution for export");
+ RNA_def_enum(func,
+ "export_global_forward_selection",
+ prop_bc_export_global_forward,
+ BC_DEFAULT_FORWARD,
+ "Global Forward Axis",
+ "Global Forward axis for export");
+
+ RNA_def_enum(func,
+ "export_global_up_selection",
+ prop_bc_export_global_up,
+ BC_DEFAULT_UP,
+ "Global Up Axis",
+ "Global Up axis for export");
+
+ RNA_def_boolean(func,
+ "apply_global_orientation",
+ false,
+ "Apply Global Orientation",
+ "enabled: Rotate all root objects to match the global orientation "
+ "settings.\ndisabled: set global orientation in Collada assets");
+
RNA_def_boolean(func, "selected", false, "Selection Only", "Export only selected elements");
RNA_def_boolean(func,
@@ -611,21 +704,42 @@ void WM_OT_collada_export(wmOperatorType *ot)
func, "sort_by_name", 0, "Sort by Object name", "Sort exported data by Object name");
RNA_def_int(func,
- "export_transformation_type",
+ "export_object_transformation_type",
+ 0,
+ INT_MIN,
+ INT_MAX,
+ "Transform",
+ "Object Transformation type for translation, scale and rotation",
+ INT_MIN,
+ INT_MAX);
+
+ RNA_def_enum(func,
+ "export_object_transformation_type_selection",
+ prop_bc_export_transformation_type,
+ 0,
+ "Transform",
+ "Object Transformation type for translation, scale and rotation");
+
+ RNA_def_int(func,
+ "export_animation_transformation_type",
0,
INT_MIN,
INT_MAX,
"Transform",
- "Transformation type for translation, scale and rotation",
+ "Transformation type for translation, scale and rotation\n"
+ "Note: The Animation transformation type in the Anim Tab\n"
+ "is always equal to the Object transformation type in the Geom tab",
INT_MIN,
INT_MAX);
RNA_def_enum(func,
- "export_transformation_type_selection",
+ "export_animation_transformation_type_selection",
prop_bc_export_transformation_type,
0,
"Transform",
- "Transformation type for translation, scale and rotation");
+ "Transformation type for translation, scale and rotation\n"
+ "Note: The Animation transformation type in the Anim Tab\n"
+ "is always equal to the Object transformation type in the Geom tab");
RNA_def_boolean(func,
"open_sim",
diff --git a/source/blender/editors/mask/mask_add.c b/source/blender/editors/mask/mask_add.c
index 3c456f9e2e2..fc85eab6e66 100644
--- a/source/blender/editors/mask/mask_add.c
+++ b/source/blender/editors/mask/mask_add.c
@@ -29,6 +29,7 @@
#include "BKE_mask.h"
#include "DEG_depsgraph.h"
+#include "DEG_depsgraph_query.h"
#include "DNA_scene_types.h"
#include "DNA_screen_types.h"
@@ -47,7 +48,7 @@
#include "mask_intern.h" /* own include */
bool ED_mask_find_nearest_diff_point(const bContext *C,
- struct Mask *mask,
+ struct Mask *mask_orig,
const float normal_co[2],
int threshold,
bool feather,
@@ -63,7 +64,7 @@ bool ED_mask_find_nearest_diff_point(const bContext *C,
ScrArea *sa = CTX_wm_area(C);
ARegion *ar = CTX_wm_region(C);
- MaskLayer *masklay, *point_masklay;
+ MaskLayer *point_masklay;
MaskSpline *point_spline;
MaskSplinePoint *point = NULL;
float dist_best_sq = FLT_MAX, co[2];
@@ -71,31 +72,36 @@ bool ED_mask_find_nearest_diff_point(const bContext *C,
float u = 0.0f;
float scalex, scaley;
+ Depsgraph *depsgraph = CTX_data_evaluated_depsgraph(C);
+ Mask *mask_eval = (Mask *)DEG_get_evaluated_id(depsgraph, &mask_orig->id);
+
ED_mask_get_size(sa, &width, &height);
ED_mask_pixelspace_factor(sa, ar, &scalex, &scaley);
co[0] = normal_co[0] * scalex;
co[1] = normal_co[1] * scaley;
- for (masklay = mask->masklayers.first; masklay; masklay = masklay->next) {
- MaskSpline *spline;
-
- if (masklay->restrictflag & (MASK_RESTRICT_VIEW | MASK_RESTRICT_SELECT)) {
+ for (MaskLayer *masklay_orig = mask_orig->masklayers.first,
+ *masklay_eval = mask_eval->masklayers.first;
+ masklay_orig != NULL;
+ masklay_orig = masklay_orig->next, masklay_eval = masklay_eval->next) {
+ if (masklay_orig->restrictflag & (MASK_RESTRICT_VIEW | MASK_RESTRICT_SELECT)) {
continue;
}
- for (spline = masklay->splines.first; spline; spline = spline->next) {
+ for (MaskSpline *spline_orig = masklay_orig->splines.first,
+ *spline_eval = masklay_eval->splines.first;
+ spline_orig != NULL;
+ spline_orig = spline_orig->next, spline_eval = spline_eval->next) {
int i;
- MaskSplinePoint *cur_point;
+ MaskSplinePoint *cur_point_eval;
- for (i = 0, cur_point = use_deform ? spline->points_deform : spline->points;
- i < spline->tot_point;
- i++, cur_point++) {
- float *diff_points;
+ for (i = 0, cur_point_eval = use_deform ? spline_eval->points_deform : spline_eval->points;
+ i < spline_eval->tot_point;
+ i++, cur_point_eval++) {
unsigned int tot_diff_point;
-
- diff_points = BKE_mask_point_segment_diff(
- spline, cur_point, width, height, &tot_diff_point);
+ float *diff_points = BKE_mask_point_segment_diff(
+ spline_eval, cur_point_eval, width, height, &tot_diff_point);
if (diff_points) {
int j, tot_point;
@@ -104,7 +110,7 @@ bool ED_mask_find_nearest_diff_point(const bContext *C,
if (feather) {
feather_points = BKE_mask_point_segment_feather_diff(
- spline, cur_point, width, height, &tot_feather_point);
+ spline_eval, cur_point_eval, width, height, &tot_feather_point);
points = feather_points;
tot_point = tot_feather_point;
@@ -130,19 +136,19 @@ bool ED_mask_find_nearest_diff_point(const bContext *C,
sub_v2_v2v2(tangent, &diff_points[2 * j + 2], &diff_points[2 * j]);
}
- point_masklay = masklay;
- point_spline = spline;
- point = use_deform ? &spline->points[(cur_point - spline->points_deform)] :
- cur_point;
+ point_masklay = masklay_orig;
+ point_spline = spline_orig;
+ point = use_deform ?
+ &spline_orig->points[(cur_point_eval - spline_eval->points_deform)] :
+ &spline_orig->points[(cur_point_eval - spline_eval->points)];
dist_best_sq = dist_sq;
u = (float)j / tot_point;
}
}
- if (feather_points) {
+ if (feather_points != NULL) {
MEM_freeN(feather_points);
}
-
MEM_freeN(diff_points);
}
}
@@ -580,7 +586,6 @@ static bool add_vertex_new(const bContext *C, Mask *mask, MaskLayer *masklay, co
static int add_vertex_exec(bContext *C, wmOperator *op)
{
- Scene *scene = CTX_data_scene(C);
Mask *mask = CTX_data_edit_mask(C);
MaskLayer *masklay;
@@ -626,8 +631,7 @@ static int add_vertex_exec(bContext *C, wmOperator *op)
BKE_mask_calc_handle_point_auto(spline, point, false);
BKE_mask_calc_handle_point_auto(spline, point_other, false);
- /* TODO: only update this spline */
- BKE_mask_update_display(mask, CFRA);
+ DEG_id_tag_update(&mask->id, ID_RECALC_GEOMETRY);
WM_event_add_notifier(C, NC_MASK | NA_EDITED, mask);
return OPERATOR_FINISHED;
@@ -648,8 +652,7 @@ static int add_vertex_exec(bContext *C, wmOperator *op)
}
}
- /* TODO: only update this spline */
- BKE_mask_update_display(mask, CFRA);
+ DEG_id_tag_update(&mask->id, ID_RECALC_GEOMETRY);
return OPERATOR_FINISHED;
}
@@ -716,7 +719,6 @@ static int add_feather_vertex_exec(bContext *C, wmOperator *op)
if (ED_mask_find_nearest_diff_point(
C, mask, co, threshold, true, NULL, true, true, &masklay, &spline, &point, &u, NULL)) {
- Scene *scene = CTX_data_scene(C);
float w = BKE_mask_point_weight(spline, point, u);
float weight_scalar = BKE_mask_point_weight_scalar(spline, point, u);
@@ -726,12 +728,10 @@ static int add_feather_vertex_exec(bContext *C, wmOperator *op)
BKE_mask_point_add_uw(point, u, w);
- BKE_mask_update_display(mask, scene->r.cfra);
+ DEG_id_tag_update(&mask->id, ID_RECALC_GEOMETRY);
WM_event_add_notifier(C, NC_MASK | NA_EDITED, mask);
- DEG_id_tag_update(&mask->id, 0);
-
return OPERATOR_FINISHED;
}
@@ -786,7 +786,6 @@ static int create_primitive_from_points(
bContext *C, wmOperator *op, const float (*points)[2], int num_points, char handle_type)
{
ScrArea *sa = CTX_wm_area(C);
- Scene *scene = CTX_data_scene(C);
Mask *mask;
MaskLayer *mask_layer;
MaskSpline *new_spline;
@@ -848,8 +847,7 @@ static int create_primitive_from_points(
}
WM_event_add_notifier(C, NC_MASK | NA_EDITED, mask);
- /* TODO: only update this spline */
- BKE_mask_update_display(mask, CFRA);
+ DEG_id_tag_update(&mask->id, ID_RECALC_GEOMETRY);
return OPERATOR_FINISHED;
}
diff --git a/source/blender/editors/mask/mask_draw.c b/source/blender/editors/mask/mask_draw.c
index 305e3a328ab..33e89b1a7c5 100644
--- a/source/blender/editors/mask/mask_draw.c
+++ b/source/blender/editors/mask/mask_draw.c
@@ -52,6 +52,8 @@
#include "UI_resources.h"
#include "UI_view2d.h"
+#include "DEG_depsgraph_query.h"
+
#include "mask_intern.h" /* own include */
static void mask_spline_color_get(MaskLayer *masklay,
@@ -672,7 +674,8 @@ static float *mask_rasterize(Mask *mask, const int width, const int height)
/* sets up the opengl context.
* width, height are to match the values from ED_mask_get_size() */
void ED_mask_draw_region(
- Mask *mask,
+ Depsgraph *depsgraph,
+ Mask *mask_,
ARegion *ar,
const char draw_flag,
const char draw_type,
@@ -690,6 +693,7 @@ void ED_mask_draw_region(
const bContext *C)
{
struct View2D *v2d = &ar->v2d;
+ Mask *mask_eval = (Mask *)DEG_get_evaluated_id(depsgraph, &mask_->id);
/* aspect always scales vertically in movie and image spaces */
const float width = width_i, height = (float)height_i * (aspy / aspx);
@@ -735,7 +739,7 @@ void ED_mask_draw_region(
if (draw_flag & MASK_DRAWFLAG_OVERLAY) {
float red[4] = {1.0f, 0.0f, 0.0f, 0.0f};
- float *buffer = mask_rasterize(mask, width, height);
+ float *buffer = mask_rasterize(mask_eval, width, height);
if (overlay_mode != MASK_OVERLAY_ALPHACHANNEL) {
/* More blending types could be supported in the future. */
@@ -779,7 +783,7 @@ void ED_mask_draw_region(
}
/* draw! */
- draw_masklays(C, mask, draw_flag, draw_type, width, height);
+ draw_masklays(C, mask_eval, draw_flag, draw_type, width, height);
if (do_draw_cb) {
ED_region_draw_cb_draw(C, ar, REGION_DRAW_POST_VIEW);
diff --git a/source/blender/editors/mask/mask_ops.c b/source/blender/editors/mask/mask_ops.c
index 1f825c0bb31..5a7a84dbbc8 100644
--- a/source/blender/editors/mask/mask_ops.c
+++ b/source/blender/editors/mask/mask_ops.c
@@ -31,6 +31,7 @@
#include "BKE_mask.h"
#include "DEG_depsgraph.h"
+#include "DEG_depsgraph_query.h"
#include "DNA_scene_types.h"
#include "DNA_mask_types.h"
@@ -65,7 +66,7 @@ static void mask_point_scaled_handle(/*const*/ MaskSplinePoint *point,
}
MaskSplinePoint *ED_mask_point_find_nearest(const bContext *C,
- Mask *mask,
+ Mask *mask_orig,
const float normal_co[2],
const float threshold,
MaskLayer **masklay_r,
@@ -76,7 +77,6 @@ MaskSplinePoint *ED_mask_point_find_nearest(const bContext *C,
ScrArea *sa = CTX_wm_area(C);
ARegion *ar = CTX_wm_region(C);
- MaskLayer *masklay;
MaskLayer *point_masklay = NULL;
MaskSpline *point_spline = NULL;
MaskSplinePoint *point = NULL;
@@ -86,29 +86,35 @@ MaskSplinePoint *ED_mask_point_find_nearest(const bContext *C,
eMaskWhichHandle which_handle = MASK_WHICH_HANDLE_NONE;
int width, height;
+ Depsgraph *depsgraph = CTX_data_evaluated_depsgraph(C);
+ Mask *mask_eval = (Mask *)DEG_get_evaluated_id(depsgraph, &mask_orig->id);
+
ED_mask_get_size(sa, &width, &height);
ED_mask_pixelspace_factor(sa, ar, &scalex, &scaley);
co[0] = normal_co[0] * scalex;
co[1] = normal_co[1] * scaley;
- for (masklay = mask->masklayers.first; masklay; masklay = masklay->next) {
- MaskSpline *spline;
+ for (MaskLayer *masklay_orig = mask_orig->masklayers.first,
+ *masklay_eval = mask_eval->masklayers.first;
+ masklay_orig != NULL;
+ masklay_orig = masklay_orig->next, masklay_eval = masklay_eval->next) {
- if (masklay->restrictflag & (MASK_RESTRICT_VIEW | MASK_RESTRICT_SELECT)) {
+ if (masklay_orig->restrictflag & (MASK_RESTRICT_VIEW | MASK_RESTRICT_SELECT)) {
continue;
}
- for (spline = masklay->splines.first; spline; spline = spline->next) {
- MaskSplinePoint *points_array = BKE_mask_spline_point_array(spline);
-
- int i;
+ for (MaskSpline *spline_orig = masklay_orig->splines.first,
+ *spline_eval = masklay_eval->splines.first;
+ spline_orig != NULL;
+ spline_orig = spline_orig->next, spline_eval = spline_eval->next) {
+ MaskSplinePoint *points_array = BKE_mask_spline_point_array(spline_eval);
- for (i = 0; i < spline->tot_point; i++) {
- MaskSplinePoint *cur_point = &spline->points[i];
- MaskSplinePoint *cur_point_deform = &points_array[i];
+ for (int i = 0; i < spline_orig->tot_point; i++) {
+ MaskSplinePoint *cur_point_orig = &spline_orig->points[i];
+ MaskSplinePoint *cur_point_deform_eval = &points_array[i];
eMaskWhichHandle cur_which_handle = MASK_WHICH_HANDLE_NONE;
- BezTriple *bezt = &cur_point_deform->bezt;
+ BezTriple *bezt = &cur_point_deform_eval->bezt;
float cur_len_sq, vec[2];
vec[0] = bezt->vec[1][0] * scalex;
@@ -117,17 +123,17 @@ MaskSplinePoint *ED_mask_point_find_nearest(const bContext *C,
cur_len_sq = len_squared_v2v2(co, vec);
if (cur_len_sq < len_sq) {
- point_spline = spline;
- point_masklay = masklay;
- point = cur_point;
+ point_spline = spline_orig;
+ point_masklay = masklay_orig;
+ point = cur_point_orig;
len_sq = cur_len_sq;
which_handle = MASK_WHICH_HANDLE_NONE;
}
- if (BKE_mask_point_handles_mode_get(cur_point_deform) == MASK_HANDLE_MODE_STICK) {
+ if (BKE_mask_point_handles_mode_get(cur_point_deform_eval) == MASK_HANDLE_MODE_STICK) {
float handle[2];
mask_point_scaled_handle(
- cur_point_deform, MASK_WHICH_HANDLE_STICK, scalex, scaley, handle);
+ cur_point_deform_eval, MASK_WHICH_HANDLE_STICK, scalex, scaley, handle);
cur_len_sq = len_squared_v2v2(co, handle);
cur_which_handle = MASK_WHICH_HANDLE_STICK;
}
@@ -135,9 +141,9 @@ MaskSplinePoint *ED_mask_point_find_nearest(const bContext *C,
float handle_left[2], handle_right[2];
float len_left_sq, len_right_sq;
mask_point_scaled_handle(
- cur_point_deform, MASK_WHICH_HANDLE_LEFT, scalex, scaley, handle_left);
+ cur_point_deform_eval, MASK_WHICH_HANDLE_LEFT, scalex, scaley, handle_left);
mask_point_scaled_handle(
- cur_point_deform, MASK_WHICH_HANDLE_RIGHT, scalex, scaley, handle_right);
+ cur_point_deform_eval, MASK_WHICH_HANDLE_RIGHT, scalex, scaley, handle_right);
len_left_sq = len_squared_v2v2(co, handle_left);
len_right_sq = len_squared_v2v2(co, handle_right);
@@ -168,9 +174,9 @@ MaskSplinePoint *ED_mask_point_find_nearest(const bContext *C,
}
if (cur_len_sq <= len_sq && cur_which_handle != MASK_WHICH_HANDLE_NONE) {
- point_masklay = masklay;
- point_spline = spline;
- point = cur_point;
+ point_masklay = masklay_orig;
+ point_spline = spline_orig;
+ point = cur_point_orig;
len_sq = cur_len_sq;
which_handle = cur_which_handle;
}
@@ -214,7 +220,7 @@ MaskSplinePoint *ED_mask_point_find_nearest(const bContext *C,
}
bool ED_mask_feather_find_nearest(const bContext *C,
- Mask *mask,
+ Mask *mask_orig,
const float normal_co[2],
const float threshold,
MaskLayer **masklay_r,
@@ -226,7 +232,7 @@ bool ED_mask_feather_find_nearest(const bContext *C,
ScrArea *sa = CTX_wm_area(C);
ARegion *ar = CTX_wm_region(C);
- MaskLayer *masklay, *point_masklay = NULL;
+ MaskLayer *point_masklay = NULL;
MaskSpline *point_spline = NULL;
MaskSplinePoint *point = NULL;
MaskSplinePointUW *uw = NULL;
@@ -235,32 +241,41 @@ bool ED_mask_feather_find_nearest(const bContext *C,
float scalex, scaley;
int width, height;
+ Depsgraph *depsgraph = CTX_data_evaluated_depsgraph(C);
+ Mask *mask_eval = (Mask *)DEG_get_evaluated_id(depsgraph, &mask_orig->id);
+
ED_mask_get_size(sa, &width, &height);
ED_mask_pixelspace_factor(sa, ar, &scalex, &scaley);
co[0] = normal_co[0] * scalex;
co[1] = normal_co[1] * scaley;
- for (masklay = mask->masklayers.first; masklay; masklay = masklay->next) {
- MaskSpline *spline;
+ for (MaskLayer *masklay_orig = mask_orig->masklayers.first,
+ *masklay_eval = mask_eval->masklayers.first;
+ masklay_orig != NULL;
+ masklay_orig = masklay_orig->next, masklay_eval = masklay_eval->next) {
- for (spline = masklay->splines.first; spline; spline = spline->next) {
+ for (MaskSpline *spline_orig = masklay_orig->splines.first,
+ *spline_eval = masklay_eval->splines.first;
+ spline_orig != NULL;
+ spline_orig = spline_orig->next, spline_eval = spline_eval->next) {
// MaskSplinePoint *points_array = BKE_mask_spline_point_array(spline);
int i, tot_feather_point;
float(*feather_points)[2], (*fp)[2];
- if (masklay->restrictflag & (MASK_RESTRICT_VIEW | MASK_RESTRICT_SELECT)) {
+ if (masklay_orig->restrictflag & (MASK_RESTRICT_VIEW | MASK_RESTRICT_SELECT)) {
continue;
}
- feather_points = fp = BKE_mask_spline_feather_points(spline, &tot_feather_point);
+ feather_points = fp = BKE_mask_spline_feather_points(spline_eval, &tot_feather_point);
- for (i = 0; i < spline->tot_point; i++) {
+ for (i = 0; i < spline_orig->tot_point; i++) {
int j;
- MaskSplinePoint *cur_point = &spline->points[i];
+ MaskSplinePoint *cur_point_orig = &spline_orig->points[i];
+ MaskSplinePoint *cur_point_eval = &spline_eval->points[i];
- for (j = 0; j <= cur_point->tot_uw; j++) {
+ for (j = 0; j <= cur_point_eval->tot_uw; j++) {
float cur_len_sq, vec[2];
vec[0] = (*fp)[0] * scalex;
@@ -273,12 +288,12 @@ bool ED_mask_feather_find_nearest(const bContext *C,
uw = NULL;
}
else {
- uw = &cur_point->uw[j - 1];
+ uw = &cur_point_eval->uw[j - 1];
}
- point_masklay = masklay;
- point_spline = spline;
- point = cur_point;
+ point_masklay = masklay_orig;
+ point_spline = spline_orig;
+ point = cur_point_orig;
len = cur_len_sq;
}
@@ -1648,7 +1663,6 @@ static void delete_feather_points(MaskSplinePoint *point)
static int delete_exec(bContext *C, wmOperator *UNUSED(op))
{
- Scene *scene = CTX_data_scene(C);
Mask *mask = CTX_data_edit_mask(C);
MaskLayer *masklay;
bool changed = false;
@@ -1743,8 +1757,7 @@ static int delete_exec(bContext *C, wmOperator *UNUSED(op))
return OPERATOR_CANCELLED;
}
- /* TODO: only update edited splines */
- BKE_mask_update_display(mask, CFRA);
+ DEG_id_tag_update(&mask->id, ID_RECALC_GEOMETRY);
WM_event_add_notifier(C, NC_MASK | NA_EDITED, mask);
@@ -1801,8 +1814,7 @@ static int mask_switch_direction_exec(bContext *C, wmOperator *UNUSED(op))
}
if (changed) {
- /* TODO: only update this spline */
- BKE_mask_update_display(mask, CFRA);
+ DEG_id_tag_update(&mask->id, ID_RECALC_GEOMETRY);
WM_event_add_notifier(C, NC_MASK | ND_SELECT, mask);
WM_event_add_notifier(C, NC_MASK | NA_EDITED, mask);
@@ -1867,8 +1879,7 @@ static int mask_normals_make_consistent_exec(bContext *C, wmOperator *UNUSED(op)
}
if (changed) {
- /* TODO: only update this spline */
- BKE_mask_update_display(mask, CFRA);
+ DEG_id_tag_update(&mask->id, ID_RECALC_GEOMETRY);
WM_event_add_notifier(C, NC_MASK | ND_SELECT, mask);
WM_event_add_notifier(C, NC_MASK | NA_EDITED, mask);
@@ -2094,7 +2105,6 @@ void MASK_OT_hide_view_set(wmOperatorType *ot)
static int mask_feather_weight_clear_exec(bContext *C, wmOperator *UNUSED(op))
{
- Scene *scene = CTX_data_scene(C);
Mask *mask = CTX_data_edit_mask(C);
MaskLayer *masklay;
bool changed = false;
@@ -2121,8 +2131,7 @@ static int mask_feather_weight_clear_exec(bContext *C, wmOperator *UNUSED(op))
}
if (changed) {
- /* TODO: only update edited splines */
- BKE_mask_update_display(mask, CFRA);
+ DEG_id_tag_update(&mask->id, ID_RECALC_GEOMETRY);
WM_event_add_notifier(C, NC_MASK | ND_DRAW, mask);
DEG_id_tag_update(&mask->id, 0);
@@ -2234,7 +2243,6 @@ void MASK_OT_layer_move(wmOperatorType *ot)
static int mask_duplicate_exec(bContext *C, wmOperator *UNUSED(op))
{
- Scene *scene = CTX_data_scene(C);
Mask *mask = CTX_data_edit_mask(C);
MaskLayer *mask_layer;
@@ -2324,8 +2332,7 @@ static int mask_duplicate_exec(bContext *C, wmOperator *UNUSED(op))
}
}
- /* TODO: only update edited splines */
- BKE_mask_update_display(mask, CFRA);
+ DEG_id_tag_update(&mask->id, ID_RECALC_GEOMETRY);
WM_event_add_notifier(C, NC_MASK | NA_EDITED, mask);
@@ -2391,7 +2398,6 @@ static bool paste_splines_poll(bContext *C)
static int paste_splines_exec(bContext *C, wmOperator *UNUSED(op))
{
- Scene *scene = CTX_data_scene(C);
Mask *mask = CTX_data_edit_mask(C);
MaskLayer *mask_layer = BKE_mask_layer_active(mask);
@@ -2401,8 +2407,7 @@ static int paste_splines_exec(bContext *C, wmOperator *UNUSED(op))
BKE_mask_clipboard_paste_to_layer(CTX_data_main(C), mask_layer);
- /* TODO: only update edited splines */
- BKE_mask_update_display(mask, CFRA);
+ DEG_id_tag_update(&mask->id, ID_RECALC_GEOMETRY);
WM_event_add_notifier(C, NC_MASK | NA_EDITED, mask);
diff --git a/source/blender/editors/mask/mask_select.c b/source/blender/editors/mask/mask_select.c
index a592f39d24b..717ce9fd72e 100644
--- a/source/blender/editors/mask/mask_select.c
+++ b/source/blender/editors/mask/mask_select.c
@@ -43,6 +43,8 @@
#include "RNA_access.h"
#include "RNA_define.h"
+#include "DEG_depsgraph.h"
+
#include "mask_intern.h" /* own include */
/* -------------------------------------------------------------------- */
@@ -223,6 +225,7 @@ static int select_all_exec(bContext *C, wmOperator *op)
ED_mask_select_toggle_all(mask, action);
ED_mask_select_flush_all(mask);
+ DEG_id_tag_update(&mask->id, ID_RECALC_SELECT);
WM_event_add_notifier(C, NC_MASK | ND_SELECT, mask);
return OPERATOR_FINISHED;
@@ -326,6 +329,7 @@ static int select_exec(bContext *C, wmOperator *op)
ED_mask_select_flush_all(mask);
+ DEG_id_tag_update(&mask->id, ID_RECALC_SELECT);
WM_event_add_notifier(C, NC_MASK | ND_SELECT, mask);
return OPERATOR_FINISHED;
@@ -365,6 +369,7 @@ static int select_exec(bContext *C, wmOperator *op)
ED_mask_select_flush_all(mask);
+ DEG_id_tag_update(&mask->id, ID_RECALC_SELECT);
WM_event_add_notifier(C, NC_MASK | ND_SELECT, mask);
return OPERATOR_FINISHED;
@@ -374,6 +379,7 @@ static int select_exec(bContext *C, wmOperator *op)
ED_mask_select_flush_all(mask);
+ DEG_id_tag_update(&mask->id, ID_RECALC_SELECT);
WM_event_add_notifier(C, NC_MASK | ND_SELECT, mask);
return OPERATOR_FINISHED;
@@ -488,6 +494,7 @@ static int box_select_exec(bContext *C, wmOperator *op)
if (changed) {
ED_mask_select_flush_all(mask);
+ DEG_id_tag_update(&mask->id, ID_RECALC_SELECT);
WM_event_add_notifier(C, NC_MASK | ND_SELECT, mask);
return OPERATOR_FINISHED;
@@ -592,6 +599,7 @@ static bool do_lasso_select_mask(bContext *C,
if (changed) {
ED_mask_select_flush_all(mask);
+ DEG_id_tag_update(&mask->id, ID_RECALC_SELECT);
WM_event_add_notifier(C, NC_MASK | ND_SELECT, mask);
}
@@ -719,6 +727,7 @@ static int circle_select_exec(bContext *C, wmOperator *op)
if (changed) {
ED_mask_select_flush_all(mask);
+ DEG_id_tag_update(&mask->id, ID_RECALC_SELECT);
WM_event_add_notifier(C, NC_MASK | ND_SELECT, mask);
return OPERATOR_FINISHED;
@@ -783,6 +792,7 @@ static int mask_select_linked_pick_invoke(bContext *C, wmOperator *op, const wmE
if (changed) {
ED_mask_select_flush_all(mask);
+ DEG_id_tag_update(&mask->id, ID_RECALC_SELECT);
WM_event_add_notifier(C, NC_MASK | ND_SELECT, mask);
return OPERATOR_FINISHED;
@@ -840,6 +850,7 @@ static int mask_select_linked_exec(bContext *C, wmOperator *UNUSED(op))
if (changed) {
ED_mask_select_flush_all(mask);
+ DEG_id_tag_update(&mask->id, ID_RECALC_SELECT);
WM_event_add_notifier(C, NC_MASK | ND_SELECT, mask);
return OPERATOR_FINISHED;
@@ -940,6 +951,7 @@ static int mask_select_more_less(bContext *C, bool more)
}
}
+ DEG_id_tag_update(&mask->id, ID_RECALC_SELECT);
WM_event_add_notifier(C, NC_MASK | ND_SELECT, mask);
return OPERATOR_FINISHED;
diff --git a/source/blender/editors/mesh/editface.c b/source/blender/editors/mesh/editface.c
index fdbcc3449b2..d61c340f7a2 100644
--- a/source/blender/editors/mesh/editface.c
+++ b/source/blender/editors/mesh/editface.c
@@ -441,74 +441,6 @@ bool paintface_mouse_select(
return true;
}
-bool do_paintface_box_select(ViewContext *vc, const rcti *rect, int sel_op)
-{
- Object *ob = vc->obact;
- Mesh *me;
-
- me = BKE_mesh_from_object(ob);
- if ((me == NULL) || (me->totpoly == 0)) {
- return false;
- }
-
- bool changed = false;
- if (SEL_OP_USE_PRE_DESELECT(sel_op)) {
- changed |= paintface_deselect_all_visible(vc->C, vc->obact, SEL_DESELECT, false);
- }
-
- if (BLI_rcti_is_empty(rect)) {
- /* pass */
- }
- else {
- MPoly *mpoly;
- uint *rt, *buf, buf_len;
- int a, index;
-
- char *selar = MEM_callocN(me->totpoly + 1, "selar");
-
- ED_view3d_select_id_validate(vc);
- buf = ED_view3d_select_id_read_rect(vc, rect, &buf_len);
-
- rt = buf;
-
- a = buf_len;
- while (a--) {
- if (*rt) {
- index = *rt;
- if (index <= me->totpoly) {
- selar[index] = 1;
- }
- }
- rt++;
- }
-
- mpoly = me->mpoly;
- for (a = 1; a <= me->totpoly; a++, mpoly++) {
- if ((mpoly->flag & ME_HIDE) == 0) {
- const bool is_select = mpoly->flag & ME_FACE_SEL;
- const bool is_inside = (selar[a] != 0);
- const int sel_op_result = ED_select_op_action_deselected(sel_op, is_select, is_inside);
- if (sel_op_result != -1) {
- SET_FLAG_FROM_TEST(mpoly->flag, sel_op_result, ME_FACE_SEL);
- changed = true;
- }
- }
- }
-
- MEM_freeN(buf);
- MEM_freeN(selar);
-
-#ifdef __APPLE__
- glReadBuffer(GL_BACK);
-#endif
- }
-
- if (changed) {
- paintface_flush_flags(vc->C, vc->obact, SELECT);
- }
- return changed;
-}
-
/* (similar to void paintface_flush_flags(Object *ob))
* copy the vertex flags, most importantly selection from the mesh to the final derived mesh,
* use in object mode when selecting vertices (while painting) */
diff --git a/source/blender/editors/mesh/editmesh_bisect.c b/source/blender/editors/mesh/editmesh_bisect.c
index bc60ff9274f..1d173d8e396 100644
--- a/source/blender/editors/mesh/editmesh_bisect.c
+++ b/source/blender/editors/mesh/editmesh_bisect.c
@@ -148,7 +148,7 @@ static int mesh_bisect_invoke(bContext *C, wmOperator *op, const wmEvent *event)
BisectData *opdata;
opdata = MEM_mallocN(sizeof(BisectData), "inset_operator_data");
- gesture->userdata = opdata;
+ gesture->user_data.data = opdata;
opdata->backup_len = objects_len;
opdata->backup = MEM_callocN(sizeof(*opdata->backup) * objects_len, __func__);
@@ -193,7 +193,7 @@ static void edbm_bisect_exit(bContext *C, BisectData *opdata)
static int mesh_bisect_modal(bContext *C, wmOperator *op, const wmEvent *event)
{
wmGesture *gesture = op->customdata;
- BisectData *opdata = gesture->userdata;
+ BisectData *opdata = gesture->user_data.data;
BisectData opdata_back = *opdata; /* annoyance, WM_gesture_straightline_modal, frees */
int ret;
@@ -276,7 +276,7 @@ static int mesh_bisect_exec(bContext *C, wmOperator *op)
}
wmGesture *gesture = op->customdata;
- BisectData *opdata = (gesture != NULL) ? gesture->userdata : NULL;
+ BisectData *opdata = (gesture != NULL) ? gesture->user_data.data : NULL;
/* -------------------------------------------------------------------- */
/* Modal support */
diff --git a/source/blender/editors/mesh/editmesh_extrude_spin_gizmo.c b/source/blender/editors/mesh/editmesh_extrude_spin_gizmo.c
index 269ead7b23f..74700e59e99 100644
--- a/source/blender/editors/mesh/editmesh_extrude_spin_gizmo.c
+++ b/source/blender/editors/mesh/editmesh_extrude_spin_gizmo.c
@@ -295,7 +295,8 @@ static void gizmo_mesh_spin_init_draw_prepare(const bContext *C, wmGizmoGroup *g
static void gizmo_mesh_spin_init_invoke_prepare(const bContext *UNUSED(C),
wmGizmoGroup *gzgroup,
- wmGizmo *gz)
+ wmGizmo *gz,
+ const wmEvent *UNUSED(event))
{
/* Set the initial ortho axis. */
GizmoGroupData_SpinInit *ggd = gzgroup->customdata;
diff --git a/source/blender/editors/mesh/editmesh_knife.c b/source/blender/editors/mesh/editmesh_knife.c
index e45c15b3e53..976dbe01a22 100644
--- a/source/blender/editors/mesh/editmesh_knife.c
+++ b/source/blender/editors/mesh/editmesh_knife.c
@@ -1156,19 +1156,20 @@ static void knifetool_draw(const bContext *UNUSED(C), ARegion *UNUSED(ar), void
GPUBatch *batch = GPU_batch_create_ex(GPU_PRIM_POINTS, vert, NULL, GPU_BATCH_OWNS_VBO);
GPU_batch_program_set_builtin(batch, GPU_SHADER_3D_UNIFORM_COLOR);
+ GPU_batch_bind(batch);
/* draw any snapped verts first */
rgba_uchar_to_float(fcol, kcd->colors.point_a);
GPU_batch_uniform_4fv(batch, "color", fcol);
GPU_matrix_bind(batch->interface);
GPU_point_size(11);
- GPU_batch_draw_range_ex(batch, 0, v - 1, false);
+ GPU_batch_draw_advanced(batch, 0, v - 1, 0, 0);
/* now draw the rest */
rgba_uchar_to_float(fcol, kcd->colors.curpoint_a);
GPU_batch_uniform_4fv(batch, "color", fcol);
GPU_point_size(7);
- GPU_batch_draw_range_ex(batch, vs + 1, kcd->totlinehit - (vs + 1), false);
+ GPU_batch_draw_advanced(batch, vs + 1, kcd->totlinehit - (vs + 1), 0, 0);
GPU_batch_program_use_end(batch);
GPU_batch_discard(batch);
diff --git a/source/blender/editors/mesh/editmesh_path.c b/source/blender/editors/mesh/editmesh_path.c
index f8ec4334427..6fd0ee83b6c 100644
--- a/source/blender/editors/mesh/editmesh_path.c
+++ b/source/blender/editors/mesh/editmesh_path.c
@@ -63,6 +63,15 @@
/** \name Path Select Struct & Properties
* \{ */
+enum {
+ EDGE_MODE_SELECT = 0,
+ EDGE_MODE_TAG_SEAM = 1,
+ EDGE_MODE_TAG_SHARP = 2,
+ EDGE_MODE_TAG_CREASE = 3,
+ EDGE_MODE_TAG_BEVEL = 4,
+ EDGE_MODE_TAG_FREESTYLE = 5,
+};
+
struct PathSelectParams {
/** ensure the active element is the last selected item (handy for picking) */
bool track_active;
@@ -75,6 +84,23 @@ struct PathSelectParams {
static void path_select_properties(wmOperatorType *ot)
{
+ static const EnumPropertyItem edge_tag_items[] = {
+ {EDGE_MODE_SELECT, "SELECT", 0, "Select", ""},
+ {EDGE_MODE_TAG_SEAM, "SEAM", 0, "Tag Seam", ""},
+ {EDGE_MODE_TAG_SHARP, "SHARP", 0, "Tag Sharp", ""},
+ {EDGE_MODE_TAG_CREASE, "CREASE", 0, "Tag Crease", ""},
+ {EDGE_MODE_TAG_BEVEL, "BEVEL", 0, "Tag Bevel", ""},
+ {EDGE_MODE_TAG_FREESTYLE, "FREESTYLE", 0, "Tag Freestyle Edge Mark", ""},
+ {0, NULL, 0, NULL, NULL},
+ };
+
+ RNA_def_enum(ot->srna,
+ "edge_mode",
+ edge_tag_items,
+ EDGE_MODE_SELECT,
+ "Edge Tag",
+ "The edge flag to tag when selecting the shortest path");
+
RNA_def_boolean(ot->srna,
"use_face_step",
false,
@@ -93,9 +119,24 @@ static void path_select_properties(wmOperatorType *ot)
WM_operator_properties_checker_interval(ot, true);
}
-static void path_select_params_from_op(wmOperator *op, struct PathSelectParams *op_params)
+static void path_select_params_from_op(wmOperator *op,
+ ToolSettings *ts,
+ struct PathSelectParams *op_params)
{
- op_params->edge_mode = EDGE_MODE_SELECT;
+ {
+ PropertyRNA *prop = RNA_struct_find_property(op->ptr, "edge_mode");
+ if (RNA_property_is_set(op->ptr, prop)) {
+ op_params->edge_mode = RNA_property_enum_get(op->ptr, prop);
+ if (op->flag & OP_IS_INVOKE) {
+ ts->edge_mode = op_params->edge_mode;
+ }
+ }
+ else {
+ op_params->edge_mode = ts->edge_mode;
+ RNA_property_enum_set(op->ptr, prop, op_params->edge_mode);
+ }
+ }
+
op_params->track_active = false;
op_params->use_face_step = RNA_boolean_get(op->ptr, "use_face_step");
op_params->use_fill = RNA_boolean_get(op->ptr, "use_fill");
@@ -103,6 +144,21 @@ static void path_select_params_from_op(wmOperator *op, struct PathSelectParams *
WM_operator_properties_checker_interval_from_op(op, &op_params->interval_params);
}
+static bool path_select_poll_property(const bContext *C,
+ wmOperator *UNUSED(op),
+ const PropertyRNA *prop)
+{
+ const char *prop_id = RNA_property_identifier(prop);
+ if (STREQ(prop_id, "edge_mode")) {
+ const Scene *scene = CTX_data_scene(C);
+ ToolSettings *ts = scene->toolsettings;
+ if ((ts->selectmode & SCE_SELECT_EDGE) == 0) {
+ return false;
+ }
+ }
+ return true;
+}
+
struct UserData {
BMesh *bm;
Mesh *me;
@@ -319,7 +375,7 @@ static void edgetag_ensure_cd_flag(Mesh *me, const char edge_mode)
/* mesh shortest path select, uses prev-selected edge */
/* since you want to create paths with multiple selects, it doesn't have extend option */
-static void mouse_mesh_shortest_path_edge(Scene *UNUSED(scene),
+static void mouse_mesh_shortest_path_edge(Scene *scene,
Object *obedit,
const struct PathSelectParams *op_params,
BMEdge *e_act,
@@ -421,6 +477,10 @@ static void mouse_mesh_shortest_path_edge(Scene *UNUSED(scene),
}
EDBM_update_generic(em, false, false);
+
+ if (op_params->edge_mode == EDGE_MODE_TAG_SEAM) {
+ ED_uvedit_live_unwrap(scene, &obedit, 1);
+ }
}
/** \} */
@@ -649,12 +709,14 @@ static int edbm_shortest_path_pick_invoke(bContext *C, wmOperator *op, const wmE
return OPERATOR_FINISHED;
}
+ struct PathSelectParams op_params;
+ path_select_params_from_op(op, vc.scene->toolsettings, &op_params);
+
BMElem *ele_src, *ele_dst;
if (!(ele_src = edbm_elem_active_elem_or_face_get(em->bm)) ||
!(ele_dst = edbm_elem_find_nearest(&vc, ele_src->head.htype))) {
/* special case, toggle edge tags even when we don't have a path */
- if (((em->selectmode & SCE_SELECT_EDGE) &&
- (vc.scene->toolsettings->edge_mode != EDGE_MODE_SELECT)) &&
+ if (((em->selectmode & SCE_SELECT_EDGE) && (op_params.edge_mode != EDGE_MODE_SELECT)) &&
/* check if we only have a destination edge */
((ele_src == NULL) && (ele_dst = edbm_elem_find_nearest(&vc, BM_EDGE)))) {
ele_src = ele_dst;
@@ -665,11 +727,7 @@ static int edbm_shortest_path_pick_invoke(bContext *C, wmOperator *op, const wmE
}
}
- struct PathSelectParams op_params;
-
- path_select_params_from_op(op, &op_params);
op_params.track_active = track_active;
- op_params.edge_mode = vc.scene->toolsettings->edge_mode;
if (!edbm_shortest_path_pick_ex(vc.scene, vc.obedit, &op_params, ele_src, ele_dst)) {
return OPERATOR_PASS_THROUGH;
@@ -707,9 +765,8 @@ static int edbm_shortest_path_pick_exec(bContext *C, wmOperator *op)
}
struct PathSelectParams op_params;
- path_select_params_from_op(op, &op_params);
+ path_select_params_from_op(op, scene->toolsettings, &op_params);
op_params.track_active = true;
- op_params.edge_mode = scene->toolsettings->edge_mode;
if (!edbm_shortest_path_pick_ex(scene, obedit, &op_params, ele_src, ele_dst)) {
return OPERATOR_CANCELLED;
@@ -731,6 +788,7 @@ void MESH_OT_shortest_path_pick(wmOperatorType *ot)
ot->invoke = edbm_shortest_path_pick_invoke;
ot->exec = edbm_shortest_path_pick_exec;
ot->poll = ED_operator_editmesh_region_view3d;
+ ot->poll_property = path_select_poll_property;
/* flags */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
@@ -832,7 +890,7 @@ static int edbm_shortest_path_select_exec(bContext *C, wmOperator *op)
if (ele_src && ele_dst) {
struct PathSelectParams op_params;
- path_select_params_from_op(op, &op_params);
+ path_select_params_from_op(op, scene->toolsettings, &op_params);
edbm_shortest_path_pick_ex(scene, obedit, &op_params, ele_src, ele_dst);
@@ -860,6 +918,7 @@ void MESH_OT_shortest_path_select(wmOperatorType *ot)
/* api callbacks */
ot->exec = edbm_shortest_path_select_exec;
ot->poll = ED_operator_editmesh;
+ ot->poll_property = path_select_poll_property;
/* flags */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
diff --git a/source/blender/editors/mesh/editmesh_select.c b/source/blender/editors/mesh/editmesh_select.c
index 485d855e18e..6a91fcb8327 100644
--- a/source/blender/editors/mesh/editmesh_select.c
+++ b/source/blender/editors/mesh/editmesh_select.c
@@ -53,6 +53,7 @@
#include "ED_mesh.h"
#include "ED_screen.h"
#include "ED_transform.h"
+#include "ED_select_buffer_utils.h"
#include "ED_select_utils.h"
#include "ED_view3d.h"
@@ -199,8 +200,19 @@ void EDBM_automerge(Scene *scene, Object *obedit, bool update, const char hflag)
* \{ */
struct EDBMBaseOffset {
- uint face;
- uint edge;
+ /* For convenience only. */
+ union {
+ uint offset;
+ uint face_start;
+ };
+ union {
+ uint face;
+ uint edge_start;
+ };
+ union {
+ uint edge;
+ uint vert_start;
+ };
uint vert;
};
@@ -209,18 +221,21 @@ struct EDBMSelectID_Context {
/** Borrow from caller (not freed). */
struct Base **bases;
uint bases_len;
+ /** Total number of items `base_array_index_offsets[bases_len - 1].vert`. */
+ uint base_array_index_len;
};
static bool check_ob_drawface_dot(short select_mode, const View3D *v3d, char dt)
{
if (select_mode & SCE_SELECT_FACE) {
- if (dt < OB_SOLID) {
+ if ((dt < OB_SOLID) || XRAY_FLAG_ENABLED(v3d)) {
return true;
}
if (v3d->overlay.edit_flag & V3D_OVERLAY_EDIT_FACE_DOT) {
return true;
}
- if (XRAY_FLAG_ENABLED(v3d)) {
+ if ((v3d->overlay.edit_flag & V3D_OVERLAY_EDIT_EDGES) == 0) {
+ /* Since we can't deduce face selection when edges aren't visible - show dots. */
return true;
}
}
@@ -234,7 +249,7 @@ static void edbm_select_pick_draw_bases(struct EDBMSelectID_Context *sel_id_ctx,
Scene *scene_eval = (Scene *)DEG_get_evaluated_id(vc->depsgraph, &vc->scene->id);
DRW_framebuffer_select_id_setup(vc->ar, true);
- uint offset = 0;
+ uint offset = 1;
for (uint base_index = 0; base_index < sel_id_ctx->bases_len; base_index++) {
Object *ob_eval = DEG_get_evaluated_object(vc->depsgraph,
sel_id_ctx->bases[base_index]->object);
@@ -252,9 +267,12 @@ static void edbm_select_pick_draw_bases(struct EDBMSelectID_Context *sel_id_ctx,
&base_ofs->edge,
&base_ofs->face);
+ base_ofs->offset = offset;
offset = base_ofs->vert;
}
+ sel_id_ctx->base_array_index_len = offset;
+
DRW_framebuffer_select_id_release(vc->ar);
}
@@ -262,28 +280,26 @@ BMElem *EDBM_select_id_bm_elem_get(struct EDBMSelectID_Context *sel_id_ctx,
const uint sel_id,
uint *r_base_index)
{
- char elem_type;
+ char elem_type = 0;
uint elem_id;
- uint prev_offs = 0;
uint base_index = 0;
for (; base_index < sel_id_ctx->bases_len; base_index++) {
struct EDBMBaseOffset *base_ofs = &sel_id_ctx->base_array_index_offsets[base_index];
if (base_ofs->face > sel_id) {
- elem_id = sel_id - (prev_offs + 1);
+ elem_id = sel_id - base_ofs->face_start;
elem_type = BM_FACE;
break;
}
if (base_ofs->edge > sel_id) {
- elem_id = sel_id - base_ofs->face;
+ elem_id = sel_id - base_ofs->edge_start;
elem_type = BM_EDGE;
break;
}
if (base_ofs->vert > sel_id) {
- elem_id = sel_id - base_ofs->edge;
+ elem_id = sel_id - base_ofs->vert_start;
elem_type = BM_VERT;
break;
}
- prev_offs = base_ofs->vert;
}
if (r_base_index) {
@@ -306,9 +322,32 @@ BMElem *EDBM_select_id_bm_elem_get(struct EDBMSelectID_Context *sel_id_ctx,
}
}
+uint EDBM_select_id_context_offset_for_object_elem(const struct EDBMSelectID_Context *sel_id_ctx,
+ int base_index,
+ char htype)
+{
+ struct EDBMBaseOffset *base_ofs = &sel_id_ctx->base_array_index_offsets[base_index];
+ if (htype == BM_VERT) {
+ return base_ofs->vert_start - 1;
+ }
+ if (htype == BM_EDGE) {
+ return base_ofs->edge_start - 1;
+ }
+ if (htype == BM_FACE) {
+ return base_ofs->face_start - 1;
+ }
+ BLI_assert(0);
+ return 0;
+}
+
+uint EDBM_select_id_context_elem_len(const struct EDBMSelectID_Context *sel_id_ctx)
+{
+ return sel_id_ctx->base_array_index_len;
+}
+
struct EDBMSelectID_Context *EDBM_select_id_context_create(ViewContext *vc,
Base **bases,
- uint bases_len,
+ const uint bases_len,
short select_mode)
{
struct EDBMSelectID_Context *sel_id_ctx = MEM_mallocN(sizeof(*sel_id_ctx), __func__);
@@ -328,192 +367,6 @@ void EDBM_select_id_context_destroy(struct EDBMSelectID_Context *sel_id_ctx)
MEM_freeN(sel_id_ctx);
}
-/* set in view3d_draw_legacy.c ... for colorindices */
-unsigned int bm_solidoffs = 0, bm_wireoffs = 0, bm_vertoffs = 0;
-
-/* facilities for box select and circle select */
-static BLI_bitmap *selbuf = NULL;
-
-static BLI_bitmap *edbm_backbuf_alloc(const int size)
-{
- return BLI_BITMAP_NEW(size, "selbuf");
-}
-
-/* reads rect, and builds selection array for quick lookup */
-/* returns if all is OK */
-bool EDBM_backbuf_border_init(ViewContext *vc, short xmin, short ymin, short xmax, short ymax)
-{
- uint *buf, *dr, buf_len;
-
- if (vc->obedit == NULL || XRAY_FLAG_ENABLED(vc->v3d)) {
- return false;
- }
-
- ED_view3d_select_id_validate(vc);
- buf = ED_view3d_select_id_read(vc, xmin, ymin, xmax, ymax, &buf_len);
- if ((buf == NULL) || (bm_vertoffs == 0)) {
- return false;
- }
-
- dr = buf;
-
- /* build selection lookup */
- selbuf = edbm_backbuf_alloc(bm_vertoffs + 1);
-
- while (buf_len--) {
- if (*dr > 0 && *dr <= bm_vertoffs) {
- BLI_BITMAP_ENABLE(selbuf, *dr);
- }
- dr++;
- }
- MEM_freeN(buf);
- return true;
-}
-
-bool EDBM_backbuf_check(unsigned int index)
-{
- /* odd logic, if selbuf is NULL we assume no zbuf-selection is enabled
- * and just ignore the depth buffer, this is error prone since its possible
- * code doesn't set the depth buffer by accident, but leave for now. - Campbell */
- if (selbuf == NULL) {
- return true;
- }
-
- if (index > 0 && index <= bm_vertoffs) {
- return BLI_BITMAP_TEST_BOOL(selbuf, index);
- }
-
- return false;
-}
-
-void EDBM_backbuf_free(void)
-{
- if (selbuf) {
- MEM_freeN(selbuf);
- }
- selbuf = NULL;
-}
-
-struct LassoMaskData {
- unsigned int *px;
- int width;
-};
-
-static void edbm_mask_lasso_px_cb(int x, int x_end, int y, void *user_data)
-{
- struct LassoMaskData *data = user_data;
- unsigned int *px = &data->px[(y * data->width) + x];
- do {
- *px = true;
- px++;
- } while (++x != x_end);
-}
-
-/* mcords is a polygon mask
- * - grab backbuffer,
- * - draw with black in backbuffer,
- * - grab again and compare
- * returns 'OK'
- */
-bool EDBM_backbuf_border_mask_init(ViewContext *vc,
- const int mcords[][2],
- short tot,
- short xmin,
- short ymin,
- short xmax,
- short ymax)
-{
- uint *buf, *dr, *dr_mask, *dr_mask_arr, buf_len;
- struct LassoMaskData lasso_mask_data;
-
- /* method in use for face selecting too */
- if (vc->obedit == NULL) {
- if (!BKE_paint_select_elem_test(vc->obact)) {
- return false;
- }
- }
- else if (XRAY_FLAG_ENABLED(vc->v3d)) {
- return false;
- }
-
- ED_view3d_select_id_validate(vc);
- buf = ED_view3d_select_id_read(vc, xmin, ymin, xmax, ymax, &buf_len);
- if ((buf == NULL) || (bm_vertoffs == 0)) {
- return false;
- }
-
- dr = buf;
-
- dr_mask = dr_mask_arr = MEM_callocN(sizeof(*dr_mask) * buf_len, __func__);
- lasso_mask_data.px = dr_mask;
- lasso_mask_data.width = (xmax - xmin) + 1;
-
- BLI_bitmap_draw_2d_poly_v2i_n(
- xmin, ymin, xmax + 1, ymax + 1, mcords, tot, edbm_mask_lasso_px_cb, &lasso_mask_data);
-
- /* build selection lookup */
- selbuf = edbm_backbuf_alloc(bm_vertoffs + 1);
-
- while (buf_len--) {
- if (*dr > 0 && *dr <= bm_vertoffs && *dr_mask == true) {
- BLI_BITMAP_ENABLE(selbuf, *dr);
- }
- dr++;
- dr_mask++;
- }
- MEM_freeN(buf);
- MEM_freeN(dr_mask_arr);
-
- return true;
-}
-
-/* circle shaped sample area */
-bool EDBM_backbuf_circle_init(ViewContext *vc, short xs, short ys, short rads)
-{
- uint *buf, *dr;
- short xmin, ymin, xmax, ymax, xc, yc;
- int radsq;
-
- /* method in use for face selecting too */
- if (vc->obedit == NULL) {
- if (!BKE_paint_select_elem_test(vc->obact)) {
- return false;
- }
- }
- else if (XRAY_FLAG_ENABLED(vc->v3d)) {
- return false;
- }
-
- xmin = xs - rads;
- xmax = xs + rads;
- ymin = ys - rads;
- ymax = ys + rads;
-
- ED_view3d_select_id_validate(vc);
- buf = ED_view3d_select_id_read(vc, xmin, ymin, xmax, ymax, NULL);
- if ((buf == NULL) || (bm_vertoffs == 0)) {
- return false;
- }
-
- dr = buf;
-
- /* build selection lookup */
- selbuf = edbm_backbuf_alloc(bm_vertoffs + 1);
- radsq = rads * rads;
- for (yc = -rads; yc <= rads; yc++) {
- for (xc = -rads; xc <= rads; xc++, dr++) {
- if (xc * xc + yc * yc < radsq) {
- if (*dr > 0 && *dr <= bm_vertoffs) {
- BLI_BITMAP_ENABLE(selbuf, *dr);
- }
- }
- }
- }
-
- MEM_freeN(buf);
- return true;
-}
-
/** \} */
/* -------------------------------------------------------------------- */
@@ -625,7 +478,7 @@ BMVert *EDBM_vert_find_nearest_ex(ViewContext *vc,
struct EDBMSelectID_Context *sel_id_ctx = EDBM_select_id_context_create(
vc, bases, bases_len, select_mode);
- index = ED_view3d_select_id_read_nearest(vc, vc->mval, 1, UINT_MAX, &dist_px);
+ index = ED_select_buffer_find_nearest_to_point(vc->mval, 1, UINT_MAX, &dist_px);
if (index) {
eve = (BMVert *)EDBM_select_id_bm_elem_get(sel_id_ctx, index, &base_index);
@@ -652,7 +505,7 @@ BMVert *EDBM_vert_find_nearest_ex(ViewContext *vc,
}
else {
struct NearestVertUserData data = {{0}};
- const struct NearestVertUserData_Hit *hit;
+ const struct NearestVertUserData_Hit *hit = NULL;
const eV3DProjTest clip_flag = V3D_PROJ_TEST_CLIP_DEFAULT;
BMesh *prev_select_bm = NULL;
@@ -697,6 +550,10 @@ BMVert *EDBM_vert_find_nearest_ex(ViewContext *vc,
}
}
+ if (hit == NULL) {
+ return NULL;
+ }
+
prev_select.index = hit->index;
prev_select.elem = hit->vert;
prev_select.bm = prev_select_bm;
@@ -850,7 +707,7 @@ BMEdge *EDBM_edge_find_nearest_ex(ViewContext *vc,
struct EDBMSelectID_Context *sel_id_ctx = EDBM_select_id_context_create(
vc, bases, bases_len, select_mode);
- index = ED_view3d_select_id_read_nearest(vc, vc->mval, 1, UINT_MAX, &dist_px);
+ index = ED_select_buffer_find_nearest_to_point(vc->mval, 1, UINT_MAX, &dist_px);
if (index) {
eed = (BMEdge *)EDBM_select_id_bm_elem_get(sel_id_ctx, index, &base_index);
@@ -899,7 +756,7 @@ BMEdge *EDBM_edge_find_nearest_ex(ViewContext *vc,
}
else {
struct NearestEdgeUserData data = {{0}};
- const struct NearestEdgeUserData_Hit *hit;
+ const struct NearestEdgeUserData_Hit *hit = NULL;
/* interpolate along the edge before doing a clipping plane test */
const eV3DProjTest clip_flag = V3D_PROJ_TEST_CLIP_DEFAULT & ~V3D_PROJ_TEST_CLIP_BB;
BMesh *prev_select_bm = NULL;
@@ -946,6 +803,10 @@ BMEdge *EDBM_edge_find_nearest_ex(ViewContext *vc,
}
}
+ if (hit == NULL) {
+ return NULL;
+ }
+
if (r_dist_center) {
*r_dist_center = hit->dist_center;
}
@@ -1059,7 +920,7 @@ BMFace *EDBM_face_find_nearest_ex(ViewContext *vc,
struct EDBMSelectID_Context *sel_id_ctx = EDBM_select_id_context_create(
vc, bases, bases_len, select_mode);
- index = ED_view3d_select_id_sample(vc, vc->mval[0], vc->mval[1]);
+ index = ED_select_buffer_sample_point(vc->mval);
if (index) {
efa = (BMFace *)EDBM_select_id_bm_elem_get(sel_id_ctx, index, &base_index);
@@ -1108,7 +969,7 @@ BMFace *EDBM_face_find_nearest_ex(ViewContext *vc,
}
else {
struct NearestFaceUserData data = {{0}};
- const struct NearestFaceUserData_Hit *hit;
+ const struct NearestFaceUserData_Hit *hit = NULL;
const eV3DProjTest clip_flag = V3D_PROJ_TEST_CLIP_DEFAULT;
BMesh *prev_select_bm = NULL;
@@ -1153,6 +1014,10 @@ BMFace *EDBM_face_find_nearest_ex(ViewContext *vc,
}
}
+ if (hit == NULL) {
+ return NULL;
+ }
+
if (r_dist_center) {
*r_dist_center = hit->dist;
}
diff --git a/source/blender/editors/mesh/editmesh_tools.c b/source/blender/editors/mesh/editmesh_tools.c
index 331be744932..60c6994eb2e 100644
--- a/source/blender/editors/mesh/editmesh_tools.c
+++ b/source/blender/editors/mesh/editmesh_tools.c
@@ -7688,6 +7688,7 @@ static int point_normals_init(bContext *C, wmOperator *op, const wmEvent *UNUSED
BMEditMesh *em = BKE_editmesh_from_object(obedit);
BMesh *bm = em->bm;
+ BKE_editmesh_ensure_autosmooth(em);
BKE_editmesh_lnorspace_update(em);
BMLoopNorEditDataArray *lnors_ed_arr = BM_loop_normal_editdata_array_init(bm);
@@ -8077,7 +8078,7 @@ void MESH_OT_point_normals(struct wmOperatorType *ot)
ot->exec = edbm_point_normals_exec;
ot->invoke = edbm_point_normals_invoke;
ot->modal = edbm_point_normals_modal;
- ot->poll = ED_operator_editmesh_auto_smooth;
+ ot->poll = ED_operator_editmesh;
ot->ui = edbm_point_normals_ui;
ot->cancel = point_normals_free;
@@ -8243,6 +8244,7 @@ static int normals_split_merge(bContext *C, const bool do_merge)
BMEdge *e;
BMIter eiter;
+ BKE_editmesh_ensure_autosmooth(em);
BKE_editmesh_lnorspace_update(em);
BMLoopNorEditDataArray *lnors_ed_arr = do_merge ? BM_loop_normal_editdata_array_init(bm) : NULL;
@@ -8288,7 +8290,7 @@ void MESH_OT_merge_normals(struct wmOperatorType *ot)
/* api callbacks */
ot->exec = edbm_merge_normals_exec;
- ot->poll = ED_operator_editmesh_auto_smooth;
+ ot->poll = ED_operator_editmesh;
/* flags */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
@@ -8308,7 +8310,7 @@ void MESH_OT_split_normals(struct wmOperatorType *ot)
/* api callbacks */
ot->exec = edbm_split_normals_exec;
- ot->poll = ED_operator_editmesh_auto_smooth;
+ ot->poll = ED_operator_editmesh;
/* flags */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
@@ -8346,6 +8348,7 @@ static int edbm_average_normals_exec(bContext *C, wmOperator *op)
BMLoop *l, *l_curr, *l_first;
BMIter fiter;
+ BKE_editmesh_ensure_autosmooth(em);
bm->spacearr_dirty |= BM_SPACEARR_DIRTY_ALL;
BKE_editmesh_lnorspace_update(em);
@@ -8506,7 +8509,7 @@ void MESH_OT_average_normals(struct wmOperatorType *ot)
/* api callbacks */
ot->exec = edbm_average_normals_exec;
- ot->poll = ED_operator_editmesh_auto_smooth;
+ ot->poll = ED_operator_editmesh;
ot->ui = edbm_average_normals_ui;
/* flags */
@@ -8569,6 +8572,7 @@ static int edbm_normals_tools_exec(bContext *C, wmOperator *op)
const int mode = RNA_enum_get(op->ptr, "mode");
const bool absolute = RNA_boolean_get(op->ptr, "absolute");
+ BKE_editmesh_ensure_autosmooth(em);
BKE_editmesh_lnorspace_update(em);
BMLoopNorEditDataArray *lnors_ed_arr = BM_loop_normal_editdata_array_init(bm);
BMLoopNorEditData *lnor_ed = lnors_ed_arr->lnor_editdata;
@@ -8725,7 +8729,7 @@ void MESH_OT_normals_tools(struct wmOperatorType *ot)
/* api callbacks */
ot->exec = edbm_normals_tools_exec;
- ot->poll = ED_operator_editmesh_auto_smooth;
+ ot->poll = ED_operator_editmesh;
ot->ui = edbm_normals_tools_ui;
/* flags */
@@ -8765,6 +8769,7 @@ static int edbm_set_normals_from_faces_exec(bContext *C, wmOperator *op)
const bool keep_sharp = RNA_boolean_get(op->ptr, "keep_sharp");
+ BKE_editmesh_ensure_autosmooth(em);
BKE_editmesh_lnorspace_update(em);
float(*vnors)[3] = MEM_callocN(sizeof(*vnors) * bm->totvert, __func__);
@@ -8830,6 +8835,7 @@ static int edbm_set_normals_from_faces_exec(bContext *C, wmOperator *op)
MEM_freeN(vnors);
EDBM_update_generic(em, true, false);
}
+ MEM_freeN(objects);
return OPERATOR_FINISHED;
}
@@ -8843,7 +8849,7 @@ void MESH_OT_set_normals_from_faces(struct wmOperatorType *ot)
/* api callbacks */
ot->exec = edbm_set_normals_from_faces_exec;
- ot->poll = ED_operator_editmesh_auto_smooth;
+ ot->poll = ED_operator_editmesh;
/* flags */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
@@ -8860,6 +8866,7 @@ static int edbm_smoothen_normals_exec(bContext *C, wmOperator *op)
BMLoop *l;
BMIter fiter, liter;
+ BKE_editmesh_ensure_autosmooth(em);
BKE_editmesh_lnorspace_update(em);
BMLoopNorEditDataArray *lnors_ed_arr = BM_loop_normal_editdata_array_init(bm);
@@ -8935,7 +8942,7 @@ void MESH_OT_smoothen_normals(struct wmOperatorType *ot)
/* api callbacks */
ot->exec = edbm_smoothen_normals_exec;
- ot->poll = ED_operator_editmesh_auto_smooth;
+ ot->poll = ED_operator_editmesh;
/* flags */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
@@ -9018,7 +9025,7 @@ void MESH_OT_mod_weighted_strength(struct wmOperatorType *ot)
/* api callbacks */
ot->exec = edbm_mod_weighted_strength_exec;
- ot->poll = ED_operator_editmesh_auto_smooth;
+ ot->poll = ED_operator_editmesh;
/* flags */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
diff --git a/source/blender/editors/mesh/meshtools.c b/source/blender/editors/mesh/meshtools.c
index e29cfa6b6e0..41736fb9a14 100644
--- a/source/blender/editors/mesh/meshtools.c
+++ b/source/blender/editors/mesh/meshtools.c
@@ -61,6 +61,7 @@
#include "DEG_depsgraph_query.h"
#include "ED_mesh.h"
+#include "ED_select_buffer_utils.h"
#include "ED_object.h"
#include "ED_view3d.h"
@@ -1114,11 +1115,11 @@ bool ED_mesh_pick_face(bContext *C, Object *ob, const int mval[2], uint dist_px,
if (dist_px) {
/* sample rect to increase chances of selecting, so that when clicking
* on an edge in the backbuf, we can still select a face */
- *r_index = ED_view3d_select_id_read_nearest(&vc, mval, 1, me->totpoly + 1, &dist_px);
+ *r_index = ED_select_buffer_find_nearest_to_point(mval, 1, me->totpoly + 1, &dist_px);
}
else {
/* sample only on the exact position */
- *r_index = ED_view3d_select_id_sample(&vc, mval[0], mval[1]);
+ *r_index = ED_select_buffer_sample_point(mval);
}
if ((*r_index) == 0 || (*r_index) > (unsigned int)me->totpoly) {
@@ -1295,11 +1296,11 @@ bool ED_mesh_pick_vert(
if (dist_px > 0) {
/* sample rect to increase chances of selecting, so that when clicking
* on an face in the backbuf, we can still select a vert */
- *r_index = ED_view3d_select_id_read_nearest(&vc, mval, 1, me->totvert + 1, &dist_px);
+ *r_index = ED_select_buffer_find_nearest_to_point(mval, 1, me->totvert + 1, &dist_px);
}
else {
/* sample only on the exact position */
- *r_index = ED_view3d_select_id_sample(&vc, mval[0], mval[1]);
+ *r_index = ED_select_buffer_sample_point(mval);
}
if ((*r_index) == 0 || (*r_index) > (uint)me->totvert) {
diff --git a/source/blender/editors/object/object_add.c b/source/blender/editors/object/object_add.c
index 293b3a57fdb..dc2a353bd86 100644
--- a/source/blender/editors/object/object_add.c
+++ b/source/blender/editors/object/object_add.c
@@ -1962,7 +1962,7 @@ static void convert_ensure_curve_cache(Depsgraph *depsgraph, Scene *scene, Objec
if (ELEM(ob->type, OB_SURF, OB_CURVE, OB_FONT)) {
/* We need 'for render' ON here, to enable computing bevel dipslist if needed.
* Also makes sense anyway, we would not want e.g. to loose hidden parts etc. */
- BKE_displist_make_curveTypes(depsgraph, scene, ob, true, false, NULL);
+ BKE_displist_make_curveTypes(depsgraph, scene, ob, true, false);
}
else if (ob->type == OB_MBALL) {
BKE_displist_make_mball(depsgraph, scene, ob);
@@ -1970,13 +1970,30 @@ static void convert_ensure_curve_cache(Depsgraph *depsgraph, Scene *scene, Objec
}
}
-static void curvetomesh(Main *bmain, Depsgraph *depsgraph, Scene *scene, Object *ob)
+static void curvetomesh(Main *bmain, Depsgraph *depsgraph, Object *ob)
{
- convert_ensure_curve_cache(depsgraph, scene, ob);
- BKE_mesh_from_nurbs(bmain, ob); /* also does users */
+ Object *object_eval = DEG_get_evaluated_object(depsgraph, ob);
+ Curve *curve = ob->data;
+ Mesh *mesh = BKE_mesh_new_from_object_to_bmain(bmain, depsgraph, object_eval, true);
+ BKE_object_free_modifiers(ob, 0);
+ /* Replace curve used by the object itself. */
+ ob->data = mesh;
+ ob->type = OB_MESH;
+ id_us_min(&curve->id);
+ id_us_plus(&mesh->id);
+ /* Change objects which are using same curve.
+ * A bit annoying, but:
+ * - It's possible to have multiple curve objects selected which are sharing the same curve
+ * datablock. We don't want mesh to be created for every of those objects.
+ * - This is how conversion worked for a long long time. */
+ LISTBASE_FOREACH (Object *, other_object, &bmain->objects) {
+ if (other_object->data == curve) {
+ other_object->type = OB_MESH;
- if (ob->type == OB_MESH) {
- BKE_object_free_modifiers(ob, 0);
+ id_us_min((ID *)other_object->data);
+ other_object->data = ob->data;
+ id_us_plus((ID *)other_object->data);
+ }
}
}
@@ -2052,7 +2069,8 @@ static int convert_exec(bContext *C, wmOperator *op)
FOREACH_SCENE_OBJECT_END;
}
- ListBase selected_editable_bases = CTX_data_collection_get(C, "selected_editable_bases");
+ ListBase selected_editable_bases;
+ CTX_data_selected_editable_bases(C, &selected_editable_bases);
/* Ensure we get all meshes calculated with a sufficient data-mask,
* needed since re-evaluating single modifiers causes bugs if they depend
@@ -2232,7 +2250,7 @@ static int convert_exec(bContext *C, wmOperator *op)
BKE_curve_curve_dimension_update(cu);
if (target == OB_MESH) {
- curvetomesh(bmain, depsgraph, scene, newob);
+ curvetomesh(bmain, depsgraph, newob);
/* meshes doesn't use displist */
BKE_object_free_curve_cache(newob);
@@ -2256,7 +2274,7 @@ static int convert_exec(bContext *C, wmOperator *op)
newob = ob;
}
- curvetomesh(bmain, depsgraph, scene, newob);
+ curvetomesh(bmain, depsgraph, newob);
/* meshes doesn't use displist */
BKE_object_free_curve_cache(newob);
diff --git a/source/blender/editors/object/object_bake_api.c b/source/blender/editors/object/object_bake_api.c
index f87342a14ad..2f5a4b44412 100644
--- a/source/blender/editors/object/object_bake_api.c
+++ b/source/blender/editors/object/object_bake_api.c
@@ -707,7 +707,7 @@ static size_t initialize_internal_images(BakeImages *bake_images, ReportList *re
/* create new mesh with edit mode changes and modifiers applied */
static Mesh *bake_mesh_new_from_object(Object *object)
{
- Mesh *me = BKE_object_to_mesh(object);
+ Mesh *me = BKE_object_to_mesh(NULL, object, false);
if (me->flag & ME_AUTOSMOOTH) {
BKE_mesh_split_faces(me, true);
@@ -946,7 +946,7 @@ static int bake(Render *re,
md = md_next;
}
- me_cage = BKE_object_to_mesh(ob_low_eval);
+ me_cage = BKE_object_to_mesh(NULL, ob_low_eval, false);
RE_bake_pixels_populate(me_cage, pixel_array_low, num_pixels, &bake_images, uv_layer);
}
@@ -965,7 +965,7 @@ static int bake(Render *re,
highpoly[i].ob_eval = DEG_get_evaluated_object(depsgraph, ob_iter);
highpoly[i].ob_eval->restrictflag &= ~OB_RESTRICT_RENDER;
highpoly[i].ob_eval->base_flag |= (BASE_VISIBLE | BASE_ENABLED_RENDER);
- highpoly[i].me = BKE_object_to_mesh(highpoly[i].ob_eval);
+ highpoly[i].me = BKE_object_to_mesh(NULL, highpoly[i].ob_eval, false);
/* lowpoly to highpoly transformation matrix */
copy_m4_m4(highpoly[i].obmat, highpoly[i].ob->obmat);
@@ -1088,7 +1088,7 @@ static int bake(Render *re,
}
/* Evaluate modifiers again. */
- me_nores = BKE_object_to_mesh(ob_low_eval);
+ me_nores = BKE_object_to_mesh(NULL, ob_low_eval, false);
RE_bake_pixels_populate(me_nores, pixel_array_low, num_pixels, &bake_images, uv_layer);
RE_bake_normal_world_to_tangent(pixel_array_low,
diff --git a/source/blender/editors/object/object_modifier.c b/source/blender/editors/object/object_modifier.c
index e555f0d940d..8d3a636671a 100644
--- a/source/blender/editors/object/object_modifier.c
+++ b/source/blender/editors/object/object_modifier.c
@@ -108,7 +108,7 @@ static void object_force_modifier_update_for_bind(Depsgraph *depsgraph, Object *
BKE_displist_make_mball(depsgraph, scene_eval, ob_eval);
}
else if (ELEM(ob->type, OB_CURVE, OB_SURF, OB_FONT)) {
- BKE_displist_make_curveTypes(depsgraph, scene_eval, ob_eval, false, false, NULL);
+ BKE_displist_make_curveTypes(depsgraph, scene_eval, ob_eval, false, false);
}
}
diff --git a/source/blender/editors/object/object_relations.c b/source/blender/editors/object/object_relations.c
index e15d85a7953..6df012cdc80 100644
--- a/source/blender/editors/object/object_relations.c
+++ b/source/blender/editors/object/object_relations.c
@@ -697,7 +697,7 @@ bool ED_object_parent_set(ReportList *reports,
cu->flag |= CU_PATH | CU_FOLLOW;
cu_eval->flag |= CU_PATH | CU_FOLLOW;
/* force creation of path data */
- BKE_displist_make_curveTypes(depsgraph, scene, par, false, false, NULL);
+ BKE_displist_make_curveTypes(depsgraph, scene, par, false, false);
}
else {
cu->flag |= CU_FOLLOW;
diff --git a/source/blender/editors/object/object_transform.c b/source/blender/editors/object/object_transform.c
index 8836d913475..00f5dffb3cc 100644
--- a/source/blender/editors/object/object_transform.c
+++ b/source/blender/editors/object/object_transform.c
@@ -1335,6 +1335,11 @@ static int object_origin_set_exec(bContext *C, wmOperator *op)
BKE_object_batch_cache_dirty_tag(tob);
DEG_id_tag_update(&tob->id, ID_RECALC_TRANSFORM | ID_RECALC_GEOMETRY);
}
+ /* special support for dupligroups */
+ else if (tob->instance_collection && tob->instance_collection->id.tag & LIB_TAG_DOIT) {
+ DEG_id_tag_update(&tob->id, ID_RECALC_TRANSFORM);
+ DEG_id_tag_update(&tob->instance_collection->id, ID_RECALC_COPY_ON_WRITE);
+ }
}
if (tot_change) {
diff --git a/source/blender/editors/render/render_opengl.c b/source/blender/editors/render/render_opengl.c
index 342c6269419..20229b63258 100644
--- a/source/blender/editors/render/render_opengl.c
+++ b/source/blender/editors/render/render_opengl.c
@@ -114,7 +114,6 @@ typedef struct OGLRender {
GPUOffScreen *ofs;
int ofs_samples;
- bool ofs_full_samples;
int sizex, sizey;
int write_still;
@@ -356,9 +355,6 @@ static void screen_opengl_render_doit(const bContext *C, OGLRender *oglrender, R
ImBuf *ibuf_view;
const int alpha_mode = (draw_sky) ? R_ADDSKY : R_ALPHAPREMUL;
- unsigned int draw_flags = V3D_OFSDRAW_NONE;
- draw_flags |= (oglrender->ofs_full_samples) ? V3D_OFSDRAW_USE_FULL_SAMPLE : 0;
-
if (view_context) {
ibuf_view = ED_view3d_draw_offscreen_imbuf(depsgraph,
scene,
@@ -368,7 +364,6 @@ static void screen_opengl_render_doit(const bContext *C, OGLRender *oglrender, R
sizex,
sizey,
IB_rectfloat,
- draw_flags,
alpha_mode,
oglrender->ofs_samples,
viewname,
@@ -381,7 +376,6 @@ static void screen_opengl_render_doit(const bContext *C, OGLRender *oglrender, R
}
}
else {
- draw_flags |= V3D_OFSDRAW_SHOW_ANNOTATION;
ibuf_view = ED_view3d_draw_offscreen_imbuf_simple(depsgraph,
scene,
NULL,
@@ -390,7 +384,7 @@ static void screen_opengl_render_doit(const bContext *C, OGLRender *oglrender, R
oglrender->sizex,
oglrender->sizey,
IB_rectfloat,
- draw_flags,
+ V3D_OFSDRAW_SHOW_ANNOTATION,
alpha_mode,
oglrender->ofs_samples,
viewname,
@@ -532,6 +526,7 @@ static bool screen_opengl_render_init(bContext *C, wmOperator *op)
const bool is_animation = RNA_boolean_get(op->ptr, "animation");
const bool is_sequencer = RNA_boolean_get(op->ptr, "sequencer");
const bool is_write_still = RNA_boolean_get(op->ptr, "write_still");
+ const int samples = U.ogl_multisamples;
char err_out[256] = "unknown";
if (G.background) {
@@ -576,7 +571,7 @@ static bool screen_opengl_render_init(bContext *C, wmOperator *op)
/* corrects render size with actual size, not every card supports non-power-of-two dimensions */
DRW_opengl_context_enable(); /* Offscreen creation needs to be done in DRW context. */
- ofs = GPU_offscreen_create(sizex, sizey, 0, true, true, err_out);
+ ofs = GPU_offscreen_create(sizex, sizey, samples, true, true, err_out);
DRW_opengl_context_disable();
if (!ofs) {
@@ -597,6 +592,7 @@ static bool screen_opengl_render_init(bContext *C, wmOperator *op)
oglrender->view_layer = CTX_data_view_layer(C);
oglrender->depsgraph = CTX_data_depsgraph(C);
oglrender->cfrao = scene->r.cfra;
+ oglrender->ofs_samples = samples;
oglrender->write_still = is_write_still && !is_animation;
oglrender->is_animation = is_animation;
diff --git a/source/blender/editors/render/render_shading.c b/source/blender/editors/render/render_shading.c
index 8819b7a541d..f7a1d7187f1 100644
--- a/source/blender/editors/render/render_shading.c
+++ b/source/blender/editors/render/render_shading.c
@@ -595,7 +595,7 @@ static int new_material_exec(bContext *C, wmOperator *UNUSED(op))
id_us_min(&ma->id);
RNA_id_pointer_create(&ma->id, &idptr);
- RNA_property_pointer_set(NULL, &ptr, prop, idptr);
+ RNA_property_pointer_set(&ptr, prop, idptr, NULL);
RNA_property_update(C, &ptr, prop);
}
@@ -644,7 +644,7 @@ static int new_texture_exec(bContext *C, wmOperator *UNUSED(op))
id_us_min(&tex->id);
RNA_id_pointer_create(&tex->id, &idptr);
- RNA_property_pointer_set(NULL, &ptr, prop, idptr);
+ RNA_property_pointer_set(&ptr, prop, idptr, NULL);
RNA_property_update(C, &ptr, prop);
}
@@ -695,7 +695,7 @@ static int new_world_exec(bContext *C, wmOperator *UNUSED(op))
id_us_min(&wo->id);
RNA_id_pointer_create(&wo->id, &idptr);
- RNA_property_pointer_set(NULL, &ptr, prop, idptr);
+ RNA_property_pointer_set(&ptr, prop, idptr, NULL);
RNA_property_update(C, &ptr, prop);
}
diff --git a/source/blender/editors/screen/area.c b/source/blender/editors/screen/area.c
index c2f9beb5d78..83058f2bc95 100644
--- a/source/blender/editors/screen/area.c
+++ b/source/blender/editors/screen/area.c
@@ -1612,9 +1612,9 @@ static void ed_default_handlers(
keymap = WM_keymap_ensure(wm->defaultconf, "Markers", 0, 0);
WM_event_add_keymap_handler_poll(handlers, keymap, event_in_markers_region);
- /* time-scrubbing */
- keymap = WM_keymap_ensure(wm->defaultconf, "Scrubbing", 0, 0);
- WM_event_add_keymap_handler_poll(handlers, keymap, ED_event_in_scrubbing_region);
+ /* time-scrub */
+ keymap = WM_keymap_ensure(wm->defaultconf, "Time Scrub", 0, 0);
+ WM_event_add_keymap_handler_poll(handlers, keymap, ED_time_scrub_event_in_region);
/* frame changing and timeline operators (for time spaces) */
keymap = WM_keymap_ensure(wm->defaultconf, "Animation", 0, 0);
@@ -2292,7 +2292,7 @@ static void ed_panel_draw(const bContext *C,
}
}
- UI_panel_end(block, w, h);
+ UI_panel_end(block, w, h, open);
}
/**
diff --git a/source/blender/editors/screen/screen_context.c b/source/blender/editors/screen/screen_context.c
index c60469e092f..6a5df8a3776 100644
--- a/source/blender/editors/screen/screen_context.c
+++ b/source/blender/editors/screen/screen_context.c
@@ -69,15 +69,10 @@ const char *screen_context_dir[] = {
"scene",
"view_layer",
"visible_objects",
- "visible_bases",
"selectable_objects",
- "selectable_bases",
"selected_objects",
- "selected_bases",
"editable_objects",
- "editable_bases",
"selected_editable_objects",
- "selected_editable_bases",
"objects_in_mode",
"objects_in_mode_unique_data",
"visible_bones",
@@ -89,7 +84,6 @@ const char *screen_context_dir[] = {
"selected_pose_bones_from_active_object",
"active_bone",
"active_pose_bone",
- "active_base",
"active_object",
"object",
"edit_object",
@@ -179,52 +173,6 @@ int ed_screen_context(const bContext *C, const char *member, bContextDataResult
CTX_data_type_set(result, CTX_DATA_TYPE_COLLECTION);
return 1;
}
- else if (CTX_data_equals(member, "visible_bases")) {
- for (Base *base = view_layer->object_bases.first; base; base = base->next) {
- if (BASE_VISIBLE(v3d, base)) {
- CTX_data_list_add(result, &scene->id, &RNA_ObjectBase, base);
- }
- }
- CTX_data_type_set(result, CTX_DATA_TYPE_COLLECTION);
- return 1;
- }
- else if (CTX_data_equals(member, "selectable_bases")) {
- for (Base *base = view_layer->object_bases.first; base; base = base->next) {
- if (BASE_SELECTABLE(v3d, base)) {
- CTX_data_list_add(result, &scene->id, &RNA_ObjectBase, base);
- }
- }
- CTX_data_type_set(result, CTX_DATA_TYPE_COLLECTION);
- return 1;
- }
- else if (CTX_data_equals(member, "selected_bases")) {
- for (Base *base = view_layer->object_bases.first; base; base = base->next) {
- if (BASE_SELECTED(v3d, base)) {
- CTX_data_list_add(result, &scene->id, &RNA_ObjectBase, base);
- }
- }
- CTX_data_type_set(result, CTX_DATA_TYPE_COLLECTION);
- return 1;
- }
- else if (CTX_data_equals(member, "selected_editable_bases")) {
- for (Base *base = view_layer->object_bases.first; base; base = base->next) {
- if (BASE_SELECTED_EDITABLE(v3d, base)) {
- CTX_data_list_add(result, &scene->id, &RNA_ObjectBase, base);
- }
- }
- CTX_data_type_set(result, CTX_DATA_TYPE_COLLECTION);
- return 1;
- }
- else if (CTX_data_equals(member, "editable_bases")) {
- /* Visible + Editable, but not necessarily selected */
- for (Base *base = view_layer->object_bases.first; base; base = base->next) {
- if (BASE_EDITABLE(v3d, base)) {
- CTX_data_list_add(result, &scene->id, &RNA_ObjectBase, base);
- }
- }
- CTX_data_type_set(result, CTX_DATA_TYPE_COLLECTION);
- return 1;
- }
else if (CTX_data_equals(member, "objects_in_mode")) {
if (obact && (obact->mode != OB_MODE_OBJECT)) {
FOREACH_OBJECT_IN_MODE_BEGIN (view_layer, v3d, obact->type, obact->mode, ob_iter) {
@@ -455,13 +403,6 @@ int ed_screen_context(const bContext *C, const char *member, bContextDataResult
return 1;
}
}
- else if (CTX_data_equals(member, "active_base")) {
- if (view_layer->basact) {
- CTX_data_pointer_set(result, &scene->id, &RNA_ObjectBase, view_layer->basact);
- }
-
- return 1;
- }
else if (CTX_data_equals(member, "active_object")) {
if (obact) {
CTX_data_id_pointer_set(result, &obact->id);
diff --git a/source/blender/editors/screen/screen_edit.c b/source/blender/editors/screen/screen_edit.c
index 07a87982890..3a90532aa56 100644
--- a/source/blender/editors/screen/screen_edit.c
+++ b/source/blender/editors/screen/screen_edit.c
@@ -675,6 +675,12 @@ void ED_screen_set_active_region(bContext *C, wmWindow *win, const int xy[2])
bool do_draw = false;
for (ar = area_iter->regionbase.first; ar; ar = ar->next) {
+
+ /* call old area's deactivate if assigned */
+ if (ar == old_ar && area_iter->type->deactivate) {
+ area_iter->type->deactivate(area_iter);
+ }
+
if (ar == old_ar || ar == scr->active_region) {
do_draw = true;
}
diff --git a/source/blender/editors/screen/screen_user_menu.c b/source/blender/editors/screen/screen_user_menu.c
index 0ec989db12b..08b9d010f79 100644
--- a/source/blender/editors/screen/screen_user_menu.c
+++ b/source/blender/editors/screen/screen_user_menu.c
@@ -194,6 +194,10 @@ void ED_screen_user_menu_item_remove(ListBase *lb, bUserMenuItem *umi)
static void screen_user_menu_draw(const bContext *C, Menu *menu)
{
+ /* Enable when we have the ability to edit menus. */
+ const bool show_missing = false;
+ char label[512];
+
uint um_array_len;
bUserMenu **um_array = ED_screen_user_menus_find(C, &um_array_len);
bool is_empty = true;
@@ -206,15 +210,32 @@ static void screen_user_menu_draw(const bContext *C, Menu *menu)
const char *ui_name = umi->ui_name[0] ? umi->ui_name : NULL;
if (umi->type == USER_MENU_TYPE_OPERATOR) {
bUserMenuItem_Op *umi_op = (bUserMenuItem_Op *)umi;
- IDProperty *prop = umi_op->prop ? IDP_CopyProperty(umi_op->prop) : NULL;
- uiItemFullO(
- menu->layout, umi_op->op_idname, ui_name, ICON_NONE, prop, umi_op->opcontext, 0, NULL);
- is_empty = false;
+ wmOperatorType *ot = WM_operatortype_find(umi_op->op_idname, false);
+ if (ot != NULL) {
+ IDProperty *prop = umi_op->prop ? IDP_CopyProperty(umi_op->prop) : NULL;
+ uiItemFullO_ptr(menu->layout, ot, ui_name, ICON_NONE, prop, umi_op->opcontext, 0, NULL);
+ is_empty = false;
+ }
+ else {
+ if (show_missing) {
+ SNPRINTF(label, "Missing: %s", umi_op->op_idname);
+ uiItemL(menu->layout, label, ICON_NONE);
+ }
+ }
}
else if (umi->type == USER_MENU_TYPE_MENU) {
bUserMenuItem_Menu *umi_mt = (bUserMenuItem_Menu *)umi;
- uiItemM(menu->layout, umi_mt->mt_idname, ui_name, ICON_NONE);
- is_empty = false;
+ MenuType *mt = WM_menutype_find(umi_mt->mt_idname, false);
+ if (mt != NULL) {
+ uiItemM_ptr(menu->layout, mt, ui_name, ICON_NONE);
+ is_empty = false;
+ }
+ else {
+ if (show_missing) {
+ SNPRINTF(label, "Missing: %s", umi_mt->mt_idname);
+ uiItemL(menu->layout, label, ICON_NONE);
+ }
+ }
}
else if (umi->type == USER_MENU_TYPE_PROP) {
bUserMenuItem_Prop *umi_pr = (bUserMenuItem_Prop *)umi;
@@ -252,9 +273,10 @@ static void screen_user_menu_draw(const bContext *C, Menu *menu)
}
}
if (!ok) {
- char label[512];
- SNPRINTF(label, "Missing: %s.%s", umi_pr->context_data_path, umi_pr->prop_id);
- uiItemL(menu->layout, label, ICON_NONE);
+ if (show_missing) {
+ SNPRINTF(label, "Missing: %s.%s", umi_pr->context_data_path, umi_pr->prop_id);
+ uiItemL(menu->layout, label, ICON_NONE);
+ }
}
}
else if (umi->type == USER_MENU_TYPE_SEP) {
diff --git a/source/blender/editors/sculpt_paint/paint_image_proj.c b/source/blender/editors/sculpt_paint/paint_image_proj.c
index d7553d18d3b..303c3fac363 100644
--- a/source/blender/editors/sculpt_paint/paint_image_proj.c
+++ b/source/blender/editors/sculpt_paint/paint_image_proj.c
@@ -6188,7 +6188,6 @@ static int texture_paint_image_from_view_exec(bContext *C, wmOperator *op)
w,
h,
IB_rect,
- V3D_OFSDRAW_NONE,
R_ALPHAPREMUL,
0,
NULL,
diff --git a/source/blender/editors/sculpt_paint/paint_utils.c b/source/blender/editors/sculpt_paint/paint_utils.c
index 84b4a130183..c8ad1b5781d 100644
--- a/source/blender/editors/sculpt_paint/paint_utils.c
+++ b/source/blender/editors/sculpt_paint/paint_utils.c
@@ -71,6 +71,7 @@
#include "BLI_sys_types.h"
#include "ED_mesh.h" /* for face mask functions */
+#include "ED_select_buffer_utils.h"
#include "WM_api.h"
#include "WM_types.h"
@@ -390,7 +391,7 @@ static int imapaint_pick_face(ViewContext *vc,
/* sample only on the exact position */
ED_view3d_select_id_validate(vc);
- *r_index = ED_view3d_select_id_sample(vc, mval[0], mval[1]);
+ *r_index = ED_select_buffer_sample_point(mval);
if ((*r_index) == 0 || (*r_index) > (unsigned int)totpoly) {
return 0;
diff --git a/source/blender/editors/sculpt_paint/paint_vertex_weight_ops.c b/source/blender/editors/sculpt_paint/paint_vertex_weight_ops.c
index c904bf2005b..b6a6c897606 100644
--- a/source/blender/editors/sculpt_paint/paint_vertex_weight_ops.c
+++ b/source/blender/editors/sculpt_paint/paint_vertex_weight_ops.c
@@ -695,7 +695,7 @@ static void gradientVertInit__mapFunc(void *userData,
static int paint_weight_gradient_modal(bContext *C, wmOperator *op, const wmEvent *event)
{
wmGesture *gesture = op->customdata;
- WPGradient_vertStoreBase *vert_cache = gesture->userdata;
+ WPGradient_vertStoreBase *vert_cache = gesture->user_data.data;
int ret = WM_gesture_straightline_modal(C, op, event);
if (ret & OPERATOR_RUNNING_MODAL) {
@@ -751,15 +751,15 @@ static int paint_weight_gradient_exec(bContext *C, wmOperator *op)
WPGradient_userData data = {NULL};
if (is_interactive) {
- if (gesture->userdata == NULL) {
- gesture->userdata = MEM_mallocN(sizeof(WPGradient_vertStoreBase) +
- (sizeof(WPGradient_vertStore) * me->totvert),
- __func__);
- gesture->userdata_free = false;
+ if (gesture->user_data.data == NULL) {
+ gesture->user_data.data = MEM_mallocN(sizeof(WPGradient_vertStoreBase) +
+ (sizeof(WPGradient_vertStore) * me->totvert),
+ __func__);
+ gesture->user_data.use_free = false;
data.is_init = true;
wpaint_prev_create(
- &((WPGradient_vertStoreBase *)gesture->userdata)->wpp, me->dvert, me->totvert);
+ &((WPGradient_vertStoreBase *)gesture->user_data.data)->wpp, me->dvert, me->totvert);
/* on init only, convert face -> vert sel */
if (me->editflag & ME_EDIT_PAINT_FACE_SEL) {
@@ -767,7 +767,7 @@ static int paint_weight_gradient_exec(bContext *C, wmOperator *op)
}
}
- vert_cache = gesture->userdata;
+ vert_cache = gesture->user_data.data;
}
else {
if (ED_wpaint_ensure_data(C, op->reports, 0, NULL) == false) {
diff --git a/source/blender/editors/sound/sound_ops.c b/source/blender/editors/sound/sound_ops.c
index 692681cecb7..381173999c4 100644
--- a/source/blender/editors/sound/sound_ops.c
+++ b/source/blender/editors/sound/sound_ops.c
@@ -136,7 +136,7 @@ static int sound_open_exec(bContext *C, wmOperator *op)
id_us_min(&sound->id);
RNA_id_pointer_create(&sound->id, &idptr);
- RNA_property_pointer_set(NULL, &pprop->ptr, pprop->prop, idptr);
+ RNA_property_pointer_set(&pprop->ptr, pprop->prop, idptr, NULL);
RNA_property_update(C, &pprop->ptr, pprop->prop);
}
diff --git a/source/blender/editors/space_action/action_data.c b/source/blender/editors/space_action/action_data.c
index d3e5c011579..bc7f8a0f79d 100644
--- a/source/blender/editors/space_action/action_data.c
+++ b/source/blender/editors/space_action/action_data.c
@@ -155,7 +155,7 @@ static void actedit_change_action(bContext *C, bAction *act)
RNA_id_pointer_create((ID *)act, &idptr);
/* set the new pointer, and force a refresh */
- RNA_property_pointer_set(NULL, &ptr, prop, idptr);
+ RNA_property_pointer_set(&ptr, prop, idptr, NULL);
RNA_property_update(C, &ptr, prop);
}
@@ -261,7 +261,7 @@ static int action_new_exec(bContext *C, wmOperator *UNUSED(op))
* NOTE: we can't use actedit_change_action, as this function is also called from the NLA
*/
RNA_id_pointer_create(&action->id, &idptr);
- RNA_property_pointer_set(NULL, &ptr, prop, idptr);
+ RNA_property_pointer_set(&ptr, prop, idptr, NULL);
RNA_property_update(C, &ptr, prop);
}
@@ -619,7 +619,7 @@ void ED_animedit_unlink_action(
prop = RNA_struct_find_property(&ptr, "action");
/* clear... */
- RNA_property_pointer_set(NULL, &ptr, prop, PointerRNA_NULL);
+ RNA_property_pointer_set(&ptr, prop, PointerRNA_NULL, NULL);
RNA_property_update(C, &ptr, prop);
}
}
diff --git a/source/blender/editors/space_action/space_action.c b/source/blender/editors/space_action/space_action.c
index 972f19bb643..3c879b03126 100644
--- a/source/blender/editors/space_action/space_action.c
+++ b/source/blender/editors/space_action/space_action.c
@@ -237,7 +237,7 @@ static void action_main_region_draw(const bContext *C, ARegion *ar)
UI_view2d_view_restore(C);
/* scrubbing region */
- ED_scrubbing_draw(ar, scene, saction->flag & SACTION_DRAWTIME, true);
+ ED_time_scrub_draw(ar, scene, saction->flag & SACTION_DRAWTIME, true);
/* scrollers */
scrollers = UI_view2d_scrollers_calc(v2d, NULL);
@@ -281,7 +281,7 @@ static void action_channel_region_draw(const bContext *C, ARegion *ar)
}
/* channel filter next to scrubbing area */
- ED_channel_search_draw(C, ar, ac.ads);
+ ED_time_scrub_channel_search_draw(C, ar, ac.ads);
/* reset view matrix */
UI_view2d_view_restore(C);
diff --git a/source/blender/editors/space_clip/clip_buttons.c b/source/blender/editors/space_clip/clip_buttons.c
index c985d61a8b8..2496b16ffae 100644
--- a/source/blender/editors/space_clip/clip_buttons.c
+++ b/source/blender/editors/space_clip/clip_buttons.c
@@ -808,12 +808,13 @@ void uiTemplateMovieclipInformation(uiLayout *layout,
user = userptr->data;
col = uiLayoutColumn(layout, false);
+ uiLayoutSetAlignment(col, UI_LAYOUT_ALIGN_RIGHT);
ibuf = BKE_movieclip_get_ibuf_flag(clip, user, clip->flag, MOVIECLIP_CACHE_SKIP);
/* Display frame dimensions, channels number and byffer type. */
BKE_movieclip_get_size(clip, user, &width, &height);
- ofs += BLI_snprintf(str + ofs, sizeof(str) - ofs, IFACE_("Size %d x %d"), width, height);
+ ofs += BLI_snprintf(str + ofs, sizeof(str) - ofs, IFACE_("%d x %d"), width, height);
if (ibuf) {
if (ibuf->rect_float) {
diff --git a/source/blender/editors/space_clip/clip_intern.h b/source/blender/editors/space_clip/clip_intern.h
index 081515ca4bc..7683823a79f 100644
--- a/source/blender/editors/space_clip/clip_intern.h
+++ b/source/blender/editors/space_clip/clip_intern.h
@@ -35,7 +35,7 @@ struct bContext;
struct wmOperatorType;
/* channel heights */
-#define CHANNEL_FIRST (-UI_SCRUBBING_MARGIN_Y - CHANNEL_HEIGHT_HALF - CHANNEL_SKIP)
+#define CHANNEL_FIRST (-UI_TIME_SCRUB_MARGIN_Y - CHANNEL_HEIGHT_HALF - CHANNEL_SKIP)
#define CHANNEL_HEIGHT (0.8f * U.widget_unit)
#define CHANNEL_HEIGHT_HALF (0.4f * U.widget_unit)
#define CHANNEL_SKIP (0.1f * U.widget_unit)
diff --git a/source/blender/editors/space_clip/clip_ops.c b/source/blender/editors/space_clip/clip_ops.c
index e5698ede59a..710a46fdd51 100644
--- a/source/blender/editors/space_clip/clip_ops.c
+++ b/source/blender/editors/space_clip/clip_ops.c
@@ -245,7 +245,7 @@ static int open_exec(bContext *C, wmOperator *op)
id_us_min(&clip->id);
RNA_id_pointer_create(&clip->id, &idptr);
- RNA_property_pointer_set(NULL, &pprop->ptr, pprop->prop, idptr);
+ RNA_property_pointer_set(&pprop->ptr, pprop->prop, idptr, NULL);
RNA_property_update(C, &pprop->ptr, pprop->prop);
}
else if (sc) {
diff --git a/source/blender/editors/space_clip/space_clip.c b/source/blender/editors/space_clip/space_clip.c
index 13d190e6861..4df435270ce 100644
--- a/source/blender/editors/space_clip/space_clip.c
+++ b/source/blender/editors/space_clip/space_clip.c
@@ -926,7 +926,8 @@ static void clip_main_region_draw(const bContext *C, ARegion *ar)
ScrArea *sa = CTX_wm_area(C);
int mask_width, mask_height;
ED_mask_get_size(sa, &mask_width, &mask_height);
- ED_mask_draw_region(mask,
+ ED_mask_draw_region(CTX_data_depsgraph(C),
+ mask,
ar,
sc->mask_info.draw_flag,
sc->mask_info.draw_type,
@@ -1006,8 +1007,8 @@ static void clip_preview_region_init(wmWindowManager *wm, ARegion *ar)
keymap = WM_keymap_ensure(wm->defaultconf, "Clip", SPACE_CLIP, 0);
WM_event_add_keymap_handler_v2d_mask(&ar->handlers, keymap);
- keymap = WM_keymap_ensure(wm->defaultconf, "Clip Scrubbing", SPACE_CLIP, RGN_TYPE_PREVIEW);
- WM_event_add_keymap_handler_poll(&ar->handlers, keymap, ED_event_in_scrubbing_region);
+ keymap = WM_keymap_ensure(wm->defaultconf, "Clip Time Scrub", SPACE_CLIP, RGN_TYPE_PREVIEW);
+ WM_event_add_keymap_handler_poll(&ar->handlers, keymap, ED_time_scrub_event_in_region);
keymap = WM_keymap_ensure(wm->defaultconf, "Clip Graph Editor", SPACE_CLIP, 0);
WM_event_add_keymap_handler_v2d_mask(&ar->handlers, keymap);
@@ -1047,7 +1048,7 @@ static void graph_region_draw(const bContext *C, ARegion *ar)
UI_view2d_view_restore(C);
/* time-scrubbing */
- ED_scrubbing_draw(ar, scene, sc->flag & SC_SHOW_SECONDS, true);
+ ED_time_scrub_draw(ar, scene, sc->flag & SC_SHOW_SECONDS, true);
/* scrollers */
scrollers = UI_view2d_scrollers_calc(v2d, NULL);
@@ -1061,7 +1062,7 @@ static void graph_region_draw(const bContext *C, ARegion *ar)
0,
15 * UI_DPI_FAC,
15 * UI_DPI_FAC,
- UI_DPI_FAC * ar->sizey - UI_SCRUBBING_MARGIN_Y);
+ UI_DPI_FAC * ar->sizey - UI_TIME_SCRUB_MARGIN_Y);
UI_view2d_draw_scale_y__values(ar, v2d, &rect, TH_TEXT);
}
}
@@ -1101,7 +1102,7 @@ static void dopesheet_region_draw(const bContext *C, ARegion *ar)
UI_view2d_view_restore(C);
/* time-scrubbing */
- ED_scrubbing_draw(ar, scene, sc->flag & SC_SHOW_SECONDS, true);
+ ED_time_scrub_draw(ar, scene, sc->flag & SC_SHOW_SECONDS, true);
/* scrollers */
scrollers = UI_view2d_scrollers_calc(v2d, NULL);
@@ -1371,7 +1372,7 @@ void ED_spacetype_clip(void)
/* regions: properties */
art = MEM_callocN(sizeof(ARegionType), "spacetype clip region properties");
art->regionid = RGN_TYPE_UI;
- art->prefsizex = UI_COMPACT_PANEL_WIDTH;
+ art->prefsizex = UI_SIDEBAR_PANEL_WIDTH;
art->keymapflag = ED_KEYMAP_FRAMES | ED_KEYMAP_UI;
art->init = clip_properties_region_init;
art->draw = clip_properties_region_draw;
@@ -1382,7 +1383,7 @@ void ED_spacetype_clip(void)
/* regions: tools */
art = MEM_callocN(sizeof(ARegionType), "spacetype clip region tools");
art->regionid = RGN_TYPE_TOOLS;
- art->prefsizex = UI_COMPACT_PANEL_WIDTH;
+ art->prefsizex = UI_SIDEBAR_PANEL_WIDTH;
art->keymapflag = ED_KEYMAP_FRAMES | ED_KEYMAP_UI;
art->listener = clip_props_region_listener;
art->init = clip_tools_region_init;
diff --git a/source/blender/editors/space_clip/tracking_ops.c b/source/blender/editors/space_clip/tracking_ops.c
index b51baafbcf5..0425d6da3d8 100644
--- a/source/blender/editors/space_clip/tracking_ops.c
+++ b/source/blender/editors/space_clip/tracking_ops.c
@@ -1466,6 +1466,7 @@ static int join_tracks_exec(bContext *C, wmOperator *op)
}
BLI_gset_free(point_tracks, NULL);
+ DEG_id_tag_update(&clip->id, 0);
WM_event_add_notifier(C, NC_MOVIECLIP | NA_EDITED, clip);
@@ -1625,6 +1626,7 @@ static int track_copy_color_exec(bContext *C, wmOperator *UNUSED(op))
}
}
+ DEG_id_tag_update(&clip->id, 0);
WM_event_add_notifier(C, NC_MOVIECLIP | ND_DISPLAY, clip);
return OPERATOR_FINISHED;
@@ -1806,6 +1808,7 @@ static int clean_tracks_exec(bContext *C, wmOperator *op)
}
}
+ DEG_id_tag_update(&clip->id, 0);
BKE_tracking_dopesheet_tag_update(tracking);
WM_event_add_notifier(C, NC_MOVIECLIP | ND_SELECT, clip);
diff --git a/source/blender/editors/space_graph/graph_edit.c b/source/blender/editors/space_graph/graph_edit.c
index 8329218eea9..b68efdc0ea0 100644
--- a/source/blender/editors/space_graph/graph_edit.c
+++ b/source/blender/editors/space_graph/graph_edit.c
@@ -55,6 +55,7 @@
#include "DEG_depsgraph_build.h"
#include "UI_view2d.h"
+#include "UI_interface.h"
#include "ED_anim_api.h"
#include "ED_keyframing.h"
@@ -282,10 +283,18 @@ static int graphkeys_viewall(bContext *C,
do_sel_only,
include_handles);
+ /* Give some more space at the borders. */
BLI_rctf_scale(&cur_new, 1.1f);
- UI_view2d_smooth_view(C, ac.ar, &cur_new, smooth_viewtx);
+ /* Take regions into account, that could block the view. */
+ float pad_top = UI_TIME_SCRUB_MARGIN_Y;
+ float pad_bottom = 0;
+ if (!BLI_listbase_is_empty(ED_context_get_markers(C))) {
+ pad_bottom = UI_MARKER_MARGIN_Y;
+ }
+ BLI_rctf_pad_y(&cur_new, ac.ar->sizey * UI_DPI_FAC, pad_bottom, pad_top);
+ UI_view2d_smooth_view(C, ac.ar, &cur_new, smooth_viewtx);
return OPERATOR_FINISHED;
}
diff --git a/source/blender/editors/space_graph/space_graph.c b/source/blender/editors/space_graph/space_graph.c
index 4e131c653f8..6c5ebf77bf4 100644
--- a/source/blender/editors/space_graph/space_graph.c
+++ b/source/blender/editors/space_graph/space_graph.c
@@ -314,7 +314,7 @@ static void graph_main_region_draw(const bContext *C, ARegion *ar)
UI_view2d_view_restore(C);
/* time-scrubbing */
- ED_scrubbing_draw(ar, scene, display_seconds, false);
+ ED_time_scrub_draw(ar, scene, display_seconds, false);
/* scrollers */
// FIXME: args for scrollers depend on the type of data being shown...
@@ -329,7 +329,7 @@ static void graph_main_region_draw(const bContext *C, ARegion *ar)
0,
15 * UI_DPI_FAC,
15 * UI_DPI_FAC,
- UI_DPI_FAC * ar->sizey - UI_SCRUBBING_MARGIN_Y);
+ UI_DPI_FAC * ar->sizey - UI_TIME_SCRUB_MARGIN_Y);
UI_view2d_draw_scale_y__values(ar, v2d, &rect, TH_SCROLL_TEXT);
}
}
@@ -376,7 +376,7 @@ static void graph_channel_region_draw(const bContext *C, ARegion *ar)
}
/* channel filter next to scrubbing area */
- ED_channel_search_draw(C, ar, ac.ads);
+ ED_time_scrub_channel_search_draw(C, ar, ac.ads);
/* reset view matrix */
UI_view2d_view_restore(C);
diff --git a/source/blender/editors/space_image/image_buttons.c b/source/blender/editors/space_image/image_buttons.c
index 68af854e367..26512cb232d 100644
--- a/source/blender/editors/space_image/image_buttons.c
+++ b/source/blender/editors/space_image/image_buttons.c
@@ -42,6 +42,7 @@
#include "RE_pipeline.h"
+#include "IMB_colormanagement.h"
#include "IMB_imbuf.h"
#include "IMB_imbuf_types.h"
@@ -62,81 +63,6 @@
#define B_NOP -1
#define MAX_IMAGE_INFO_LEN 128
-/* proto */
-
-static void image_info(
- Scene *scene, ImageUser *iuser, Image *ima, ImBuf *ibuf, char *str, size_t len)
-{
- size_t ofs = 0;
-
- str[0] = 0;
- if (ima == NULL) {
- return;
- }
-
- if (ibuf == NULL) {
- ofs += BLI_strncpy_rlen(str + ofs, IFACE_("Can't Load Image"), len - ofs);
- }
- else {
- if (ima->source == IMA_SRC_MOVIE) {
- ofs += BLI_strncpy_rlen(str + ofs, IFACE_("Movie"), len - ofs);
- if (BKE_image_has_anim(ima)) {
- ofs += BLI_snprintf(
- str + ofs,
- len - ofs,
- IFACE_(" %d frs"),
- IMB_anim_get_duration(((ImageAnim *)ima->anims.first)->anim, IMB_TC_RECORD_RUN));
- }
- }
- else {
- ofs += BLI_strncpy_rlen(str, IFACE_("Image"), len - ofs);
- }
-
- ofs += BLI_snprintf(str + ofs, len - ofs, IFACE_(": size %d x %d,"), ibuf->x, ibuf->y);
-
- if (ibuf->rect_float) {
- if (ibuf->channels != 4) {
- ofs += BLI_snprintf(str + ofs, len - ofs, IFACE_("%d float channel(s)"), ibuf->channels);
- }
- else if (ibuf->planes == R_IMF_PLANES_RGBA) {
- ofs += BLI_strncpy_rlen(str + ofs, IFACE_(" RGBA float"), len - ofs);
- }
- else {
- ofs += BLI_strncpy_rlen(str + ofs, IFACE_(" RGB float"), len - ofs);
- }
- }
- else {
- if (ibuf->planes == R_IMF_PLANES_RGBA) {
- ofs += BLI_strncpy_rlen(str + ofs, IFACE_(" RGBA byte"), len - ofs);
- }
- else {
- ofs += BLI_strncpy_rlen(str + ofs, IFACE_(" RGB byte"), len - ofs);
- }
- }
- if (ibuf->zbuf || ibuf->zbuf_float) {
- ofs += BLI_strncpy_rlen(str + ofs, IFACE_(" + Z"), len - ofs);
- }
-
- if (ima->source == IMA_SRC_SEQUENCE) {
- const char *file = BLI_last_slash(ibuf->name);
- if (file == NULL) {
- file = ibuf->name;
- }
- else {
- file++;
- }
- ofs += BLI_snprintf(str + ofs, len - ofs, ", %s", file);
- }
- }
-
- /* the frame number, even if we cant */
- if (ima->source == IMA_SRC_SEQUENCE) {
- /* don't use iuser->framenr directly because it may not be updated if auto-refresh is off */
- const int framenr = BKE_image_user_frame_get(iuser, CFRA, NULL);
- ofs += BLI_snprintf(str + ofs, len - ofs, IFACE_(", Frame: %d"), framenr);
- }
-}
-
/* gets active viewer user */
struct ImageUser *ntree_get_active_iuser(bNodeTree *ntree)
{
@@ -822,6 +748,22 @@ static void rna_update_cb(bContext *C, void *arg_cb, void *UNUSED(arg))
RNA_property_update(C, &cb->ptr, cb->prop);
}
+static bool image_has_alpha(Image *ima, ImageUser *iuser)
+{
+ ImBuf *ibuf = BKE_image_acquire_ibuf(ima, iuser, NULL);
+ if (ibuf == NULL) {
+ return false;
+ }
+
+ int imtype = BKE_image_ftype_to_imtype(ibuf->ftype, &ibuf->foptions);
+ char valid_channels = BKE_imtype_valid_channels(imtype, false);
+ bool has_alpha = (valid_channels & IMA_CHAN_FLAG_ALPHA) != 0;
+
+ BKE_image_release_ibuf(ima, ibuf, NULL);
+
+ return has_alpha;
+}
+
void uiTemplateImage(uiLayout *layout,
bContext *C,
PointerRNA *ptr,
@@ -830,24 +772,11 @@ void uiTemplateImage(uiLayout *layout,
bool compact,
bool multiview)
{
- PropertyRNA *prop;
- PointerRNA imaptr;
- RNAUpdateCb *cb;
- Image *ima;
- ImageUser *iuser;
- Scene *scene = CTX_data_scene(C);
- SpaceImage *space_image = CTX_wm_space_image(C);
- uiLayout *row, *split, *col;
- uiBlock *block;
- char str[MAX_IMAGE_INFO_LEN];
-
- void *lock;
-
if (!ptr->data) {
return;
}
- prop = RNA_struct_find_property(ptr, propname);
+ PropertyRNA *prop = RNA_struct_find_property(ptr, propname);
if (!prop) {
printf(
"%s: property not found: %s.%s\n", __func__, RNA_struct_identifier(ptr->type), propname);
@@ -862,22 +791,19 @@ void uiTemplateImage(uiLayout *layout,
return;
}
- block = uiLayoutGetBlock(layout);
+ uiBlock *block = uiLayoutGetBlock(layout);
- imaptr = RNA_property_pointer_get(ptr, prop);
- ima = imaptr.data;
- iuser = userptr->data;
+ PointerRNA imaptr = RNA_property_pointer_get(ptr, prop);
+ Image *ima = imaptr.data;
+ ImageUser *iuser = userptr->data;
+ Scene *scene = CTX_data_scene(C);
BKE_image_user_frame_calc(iuser, (int)scene->r.cfra);
- cb = MEM_callocN(sizeof(RNAUpdateCb), "RNAUpdateCb");
- cb->ptr = *ptr;
- cb->prop = prop;
- cb->iuser = iuser;
-
uiLayoutSetContextPointer(layout, "edit_image", &imaptr);
uiLayoutSetContextPointer(layout, "edit_image_user", userptr);
+ SpaceImage *space_image = CTX_wm_space_image(C);
if (!compact && (space_image == NULL || iuser != &space_image->iuser)) {
uiTemplateID(layout,
C,
@@ -888,164 +814,178 @@ void uiTemplateImage(uiLayout *layout,
NULL,
UI_TEMPLATE_ID_FILTER_ALL,
false);
+
+ if (ima != NULL) {
+ uiItemS(layout);
+ }
}
- if (ima) {
- UI_block_funcN_set(block, rna_update_cb, MEM_dupallocN(cb), NULL);
+ if (ima == NULL) {
+ return;
+ }
- if (ima->source == IMA_SRC_VIEWER) {
- ImBuf *ibuf = BKE_image_acquire_ibuf(ima, iuser, &lock);
- image_info(scene, iuser, ima, ibuf, str, MAX_IMAGE_INFO_LEN);
- BKE_image_release_ibuf(ima, ibuf, lock);
+ if (ima->source == IMA_SRC_VIEWER) {
+ /* Viewer images. */
+ uiTemplateImageInfo(layout, C, ima, iuser);
- uiItemL(layout, ima->id.name + 2, ICON_NONE);
- uiItemL(layout, str, ICON_NONE);
+ if (ima->type == IMA_TYPE_COMPOSITE) {
+ }
+ else if (ima->type == IMA_TYPE_R_RESULT) {
+ /* browse layer/passes */
+ RenderResult *rr;
+ const float dpi_fac = UI_DPI_FAC;
+ const int menus_width = 230 * dpi_fac;
+
+ /* use BKE_image_acquire_renderresult so we get the correct slot in the menu */
+ rr = BKE_image_acquire_renderresult(scene, ima);
+ uiblock_layer_pass_buttons(layout, ima, rr, iuser, menus_width, &ima->render_slot);
+ BKE_image_release_renderresult(scene, ima);
+ }
- if (ima->type == IMA_TYPE_COMPOSITE) {
- }
- else if (ima->type == IMA_TYPE_R_RESULT) {
- /* browse layer/passes */
- RenderResult *rr;
- const float dpi_fac = UI_DPI_FAC;
- const int menus_width = 230 * dpi_fac;
-
- /* use BKE_image_acquire_renderresult so we get the correct slot in the menu */
- rr = BKE_image_acquire_renderresult(scene, ima);
- uiblock_layer_pass_buttons(layout, ima, rr, iuser, menus_width, &ima->render_slot);
- BKE_image_release_renderresult(scene, ima);
- }
+ return;
+ }
+
+ /* Set custom callback for property updates. */
+ RNAUpdateCb *cb = MEM_callocN(sizeof(RNAUpdateCb), "RNAUpdateCb");
+ cb->ptr = *ptr;
+ cb->prop = prop;
+ cb->iuser = iuser;
+ UI_block_funcN_set(block, rna_update_cb, cb, NULL);
+
+ /* Disable editing if image was modified, to avoid losing changes. */
+ const bool is_dirty = BKE_image_is_dirty(ima);
+ if (is_dirty) {
+ uiLayout *row = uiLayoutRow(layout, true);
+ uiItemO(row, IFACE_("Save"), ICON_NONE, "image.save");
+ uiItemO(row, IFACE_("Discard"), ICON_NONE, "image.reload");
+ uiItemS(layout);
+ }
+
+ layout = uiLayoutColumn(layout, false);
+ uiLayoutSetEnabled(layout, !is_dirty);
+ uiLayoutSetPropDecorate(layout, false);
+
+ /* Image source */
+ {
+ uiLayout *col = uiLayoutColumn(layout, false);
+ uiLayoutSetPropSep(col, true);
+ uiItemR(col, &imaptr, "source", 0, NULL, ICON_NONE);
+ }
+
+ /* Filepath */
+ const bool is_packed = BKE_image_has_packedfile(ima);
+ const bool no_filepath = is_packed && !BKE_image_has_filepath(ima);
+
+ if ((ima->source != IMA_SRC_GENERATED) && !no_filepath) {
+ uiItemS(layout);
+
+ uiLayout *row = uiLayoutRow(layout, true);
+ if (is_packed) {
+ uiItemO(row, "", ICON_PACKAGE, "image.unpack");
}
else {
- /* Disable editing if image was modified, to avoid losing changes. */
- const bool is_dirty = BKE_image_is_dirty(ima);
- if (is_dirty) {
- row = uiLayoutRow(layout, true);
- uiItemO(row, IFACE_("Save"), ICON_NONE, "image.save");
- uiItemO(row, IFACE_("Discard Changes"), ICON_NONE, "image.reload");
- uiItemS(layout);
- }
+ uiItemO(row, "", ICON_UGLYPACKAGE, "image.pack");
+ }
- layout = uiLayoutColumn(layout, false);
- uiLayoutSetEnabled(layout, !is_dirty);
+ row = uiLayoutRow(row, true);
+ uiLayoutSetEnabled(row, is_packed == false);
+ uiItemR(row, &imaptr, "filepath", 0, "", ICON_NONE);
+ uiItemO(row, "", ICON_FILE_REFRESH, "image.reload");
+ }
- /* Image source */
- uiItemR(layout, &imaptr, "source", 0, NULL, ICON_NONE);
+ /* Image layers and Info */
+ if (ima->type == IMA_TYPE_MULTILAYER && ima->rr) {
+ uiItemS(layout);
- /* Filepath */
- const bool is_packed = BKE_image_has_packedfile(ima);
- const bool no_filepath = is_packed && !BKE_image_has_filepath(ima);
+ const float dpi_fac = UI_DPI_FAC;
+ uiblock_layer_pass_buttons(layout, ima, ima->rr, iuser, 230 * dpi_fac, NULL);
+ }
+ else if (ima->source == IMA_SRC_GENERATED) {
+ uiItemS(layout);
- if ((ima->source != IMA_SRC_GENERATED) && !no_filepath) {
- row = uiLayoutRow(layout, true);
- if (is_packed) {
- uiItemO(row, "", ICON_PACKAGE, "image.unpack");
- }
- else {
- uiItemO(row, "", ICON_UGLYPACKAGE, "image.pack");
- }
+ /* Generated */
+ uiLayout *col = uiLayoutColumn(layout, false);
+ uiLayoutSetPropSep(col, true);
- row = uiLayoutRow(row, true);
- uiLayoutSetEnabled(row, is_packed == false);
- uiItemR(row, &imaptr, "filepath", 0, "", ICON_NONE);
- uiItemO(row, "", ICON_FILE_REFRESH, "image.reload");
- }
+ uiLayout *sub = uiLayoutColumn(col, true);
+ uiItemR(sub, &imaptr, "generated_width", 0, "X", ICON_NONE);
+ uiItemR(sub, &imaptr, "generated_height", 0, "Y", ICON_NONE);
- /* Image layers and Info */
- if (ima->type == IMA_TYPE_MULTILAYER && ima->rr) {
- const float dpi_fac = UI_DPI_FAC;
- uiblock_layer_pass_buttons(layout, ima, ima->rr, iuser, 230 * dpi_fac, NULL);
- }
- else if (ima->source != IMA_SRC_GENERATED) {
- if (compact == 0) {
- uiTemplateImageInfo(layout, C, ima, iuser);
- }
- }
+ uiItemR(col, &imaptr, "use_generated_float", 0, NULL, ICON_NONE);
- uiItemS(layout);
+ uiItemS(col);
- col = uiLayoutColumn(layout, false);
- uiTemplateColorspaceSettings(col, &imaptr, "colorspace_settings");
- uiItemR(col, &imaptr, "use_view_as_render", 0, NULL, ICON_NONE);
+ uiItemR(col, &imaptr, "generated_type", UI_ITEM_R_EXPAND, IFACE_("Type"), ICON_NONE);
+ if (ima->gen_type == IMA_GENTYPE_BLANK) {
+ uiItemR(col, &imaptr, "generated_color", 0, NULL, ICON_NONE);
+ }
+ }
+ else if (compact == 0) {
+ uiTemplateImageInfo(layout, C, ima, iuser);
+ }
- uiItemS(layout);
+ if (BKE_image_is_animated(ima)) {
+ /* Animation */
+ uiItemS(layout);
- if (ima->source != IMA_SRC_GENERATED) {
- if (compact == 0) { /* background image view doesn't need these */
- ImBuf *ibuf = BKE_image_acquire_ibuf(ima, iuser, NULL);
- bool has_alpha = true;
-
- if (ibuf) {
- int imtype = BKE_image_ftype_to_imtype(ibuf->ftype, &ibuf->foptions);
- char valid_channels = BKE_imtype_valid_channels(imtype, false);
-
- has_alpha = (valid_channels & IMA_CHAN_FLAG_ALPHA) != 0;
-
- BKE_image_release_ibuf(ima, ibuf, NULL);
- }
-
- if (multiview) {
- if ((scene->r.scemode & R_MULTIVIEW) != 0) {
- uiItemR(layout, &imaptr, "use_multiview", 0, NULL, ICON_NONE);
-
- if (RNA_boolean_get(&imaptr, "use_multiview")) {
- uiTemplateImageViews(layout, &imaptr);
- }
- }
- }
-
- if (has_alpha) {
- col = uiLayoutColumn(layout, false);
- uiItemR(col, &imaptr, "use_alpha", 0, NULL, ICON_NONE);
- row = uiLayoutRow(col, false);
- uiLayoutSetActive(row, RNA_boolean_get(&imaptr, "use_alpha"));
- uiItemR(row, &imaptr, "alpha_mode", 0, IFACE_("Alpha"), ICON_NONE);
- }
-
- if (ima->source == IMA_SRC_MOVIE) {
- col = uiLayoutColumn(layout, false);
- uiItemR(col, &imaptr, "use_deinterlace", 0, IFACE_("Deinterlace"), ICON_NONE);
- }
- }
- }
+ uiLayout *col = uiLayoutColumn(layout, true);
+ uiLayoutSetPropSep(col, true);
+
+ uiLayout *sub = uiLayoutColumn(col, true);
+ uiLayout *row = uiLayoutRow(sub, true);
+ uiItemR(row, userptr, "frame_duration", 0, IFACE_("Frames"), ICON_NONE);
+ uiItemO(row, "", ICON_FILE_REFRESH, "IMAGE_OT_match_movie_length");
+
+ uiItemR(sub, userptr, "frame_start", 0, IFACE_("Start"), ICON_NONE);
+ uiItemR(sub, userptr, "frame_offset", 0, NULL, ICON_NONE);
- if (BKE_image_is_animated(ima)) {
- uiItemS(layout);
+ uiItemR(col, userptr, "use_cyclic", 0, NULL, ICON_NONE);
+ uiItemR(col, userptr, "use_auto_refresh", 0, NULL, ICON_NONE);
- split = uiLayoutSplit(layout, 0.0f, false);
+ if (ima->source == IMA_SRC_MOVIE && compact == 0) {
+ uiItemR(col, &imaptr, "use_deinterlace", 0, IFACE_("Deinterlace"), ICON_NONE);
+ }
+ }
- col = uiLayoutColumn(split, false);
+ /* Multiview */
+ if (multiview && compact == 0) {
+ if ((scene->r.scemode & R_MULTIVIEW) != 0) {
+ uiItemS(layout);
- BLI_snprintf(str, sizeof(str), IFACE_("(%d) Frames"), iuser->framenr);
- uiItemR(col, userptr, "frame_duration", 0, str, ICON_NONE);
- uiItemR(col, userptr, "frame_start", 0, IFACE_("Start"), ICON_NONE);
- uiItemR(col, userptr, "frame_offset", 0, NULL, ICON_NONE);
+ uiLayout *col = uiLayoutColumn(layout, false);
+ uiLayoutSetPropSep(col, true);
+ uiItemR(col, &imaptr, "use_multiview", 0, NULL, ICON_NONE);
- col = uiLayoutColumn(split, false);
- uiItemO(col, NULL, ICON_NONE, "IMAGE_OT_match_movie_length");
- uiItemR(col, userptr, "use_auto_refresh", 0, NULL, ICON_NONE);
- uiItemR(col, userptr, "use_cyclic", 0, NULL, ICON_NONE);
+ if (RNA_boolean_get(&imaptr, "use_multiview")) {
+ uiTemplateImageViews(layout, &imaptr);
}
- else if (ima->source == IMA_SRC_GENERATED) {
- split = uiLayoutSplit(layout, 0.0f, false);
+ }
+ }
- col = uiLayoutColumn(split, true);
- uiItemR(col, &imaptr, "generated_width", 0, "X", ICON_NONE);
- uiItemR(col, &imaptr, "generated_height", 0, "Y", ICON_NONE);
+ /* Colorspace and alpha */
+ {
+ uiItemS(layout);
- uiItemR(col, &imaptr, "use_generated_float", 0, NULL, ICON_NONE);
+ uiLayout *col = uiLayoutColumn(layout, false);
+ uiLayoutSetPropSep(col, true);
+ uiTemplateColorspaceSettings(col, &imaptr, "colorspace_settings");
- uiItemR(split, &imaptr, "generated_type", UI_ITEM_R_EXPAND, NULL, ICON_NONE);
+ if (compact == 0) {
+ if (ima->source != IMA_SRC_GENERATED) {
+ if (image_has_alpha(ima, iuser)) {
+ uiLayout *sub = uiLayoutColumn(col, false);
+ uiItemR(sub, &imaptr, "alpha_mode", 0, IFACE_("Alpha"), ICON_NONE);
- if (ima->gen_type == IMA_GENTYPE_BLANK) {
- uiItemR(layout, &imaptr, "generated_color", 0, NULL, ICON_NONE);
+ bool is_data = IMB_colormanagement_space_name_is_data(ima->colorspace_settings.name);
+ uiLayoutSetActive(sub, !is_data);
}
}
- }
- UI_block_funcN_set(block, NULL, NULL, NULL);
+ uiItemR(col, &imaptr, "use_view_as_render", 0, NULL, ICON_NONE);
+ }
}
- MEM_freeN(cb);
+ UI_block_funcN_set(block, NULL, NULL, NULL);
}
void uiTemplateImageSettings(uiLayout *layout, PointerRNA *imfptr, bool color_management)
@@ -1215,25 +1155,24 @@ void uiTemplateImageFormatViews(uiLayout *layout, PointerRNA *imfptr, PointerRNA
{
ImageFormatData *imf = imfptr->data;
- if (ptr == NULL) {
- return;
+ if (ptr != NULL) {
+ uiItemR(layout, ptr, "use_multiview", 0, NULL, ICON_NONE);
+ if (!RNA_boolean_get(ptr, "use_multiview")) {
+ return;
+ }
}
- uiItemR(layout, ptr, "use_multiview", 0, NULL, ICON_NONE);
-
- if (RNA_boolean_get(ptr, "use_multiview")) {
- if (imf->imtype != R_IMF_IMTYPE_MULTILAYER) {
- PropertyRNA *prop;
- PointerRNA stereo3d_format_ptr;
+ if (imf->imtype != R_IMF_IMTYPE_MULTILAYER) {
+ PropertyRNA *prop;
+ PointerRNA stereo3d_format_ptr;
- prop = RNA_struct_find_property(imfptr, "stereo_3d_format");
- stereo3d_format_ptr = RNA_property_pointer_get(imfptr, prop);
+ prop = RNA_struct_find_property(imfptr, "stereo_3d_format");
+ stereo3d_format_ptr = RNA_property_pointer_get(imfptr, prop);
- uiTemplateViewsFormat(layout, imfptr, &stereo3d_format_ptr);
- }
- else {
- uiTemplateViewsFormat(layout, imfptr, NULL);
- }
+ uiTemplateViewsFormat(layout, imfptr, &stereo3d_format_ptr);
+ }
+ else {
+ uiTemplateViewsFormat(layout, imfptr, NULL);
}
}
@@ -1258,21 +1197,87 @@ void uiTemplateImageLayers(uiLayout *layout, bContext *C, Image *ima, ImageUser
void uiTemplateImageInfo(uiLayout *layout, bContext *C, Image *ima, ImageUser *iuser)
{
- Scene *scene = CTX_data_scene(C);
- ImBuf *ibuf;
- char str[MAX_IMAGE_INFO_LEN];
+ if (ima == NULL || iuser == NULL) {
+ return;
+ }
+
+ /* Acquire image buffer. */
void *lock;
+ ImBuf *ibuf = BKE_image_acquire_ibuf(ima, iuser, &lock);
- if (!ima || !iuser) {
- return;
+ uiLayout *col = uiLayoutColumn(layout, true);
+ uiLayoutSetAlignment(col, UI_LAYOUT_ALIGN_RIGHT);
+
+ if (ibuf == NULL) {
+ uiItemL(col, IFACE_("Can't Load Image"), ICON_NONE);
}
+ else {
+ char str[MAX_IMAGE_INFO_LEN] = {0};
+ const int len = MAX_IMAGE_INFO_LEN;
+ int ofs = 0;
- ibuf = BKE_image_acquire_ibuf(ima, iuser, &lock);
+ ofs += BLI_snprintf(str + ofs, len - ofs, IFACE_("%d x %d, "), ibuf->x, ibuf->y);
+
+ if (ibuf->rect_float) {
+ if (ibuf->channels != 4) {
+ ofs += BLI_snprintf(str + ofs, len - ofs, IFACE_("%d float channel(s)"), ibuf->channels);
+ }
+ else if (ibuf->planes == R_IMF_PLANES_RGBA) {
+ ofs += BLI_strncpy_rlen(str + ofs, IFACE_(" RGBA float"), len - ofs);
+ }
+ else {
+ ofs += BLI_strncpy_rlen(str + ofs, IFACE_(" RGB float"), len - ofs);
+ }
+ }
+ else {
+ if (ibuf->planes == R_IMF_PLANES_RGBA) {
+ ofs += BLI_strncpy_rlen(str + ofs, IFACE_(" RGBA byte"), len - ofs);
+ }
+ else {
+ ofs += BLI_strncpy_rlen(str + ofs, IFACE_(" RGB byte"), len - ofs);
+ }
+ }
+ if (ibuf->zbuf || ibuf->zbuf_float) {
+ ofs += BLI_strncpy_rlen(str + ofs, IFACE_(" + Z"), len - ofs);
+ }
+
+ uiItemL(col, str, ICON_NONE);
+ }
+
+ /* Frame number, even if we can't load the image. */
+ if (ELEM(ima->source, IMA_SRC_SEQUENCE, IMA_SRC_MOVIE)) {
+ /* don't use iuser->framenr directly because it may not be updated if auto-refresh is off */
+ Scene *scene = CTX_data_scene(C);
+ const int framenr = BKE_image_user_frame_get(iuser, CFRA, NULL);
+ char str[MAX_IMAGE_INFO_LEN];
+ int duration = 0;
+
+ if (ima->source == IMA_SRC_MOVIE && BKE_image_has_anim(ima)) {
+ struct anim *anim = ((ImageAnim *)ima->anims.first)->anim;
+ if (anim) {
+ duration = IMB_anim_get_duration(anim, IMB_TC_RECORD_RUN);
+ }
+ }
+
+ if (duration > 0) {
+ /* Movie duration */
+ BLI_snprintf(str, MAX_IMAGE_INFO_LEN, IFACE_("Frame %d / %d"), framenr, duration);
+ }
+ else if (ima->source == IMA_SRC_SEQUENCE && ibuf) {
+ /* Image sequence frame number + filename */
+ const char *filename = BLI_last_slash(ibuf->name);
+ filename = (filename == NULL) ? ibuf->name : filename + 1;
+ BLI_snprintf(str, MAX_IMAGE_INFO_LEN, IFACE_("Frame %d: %s"), framenr, filename);
+ }
+ else {
+ /* Frame number */
+ BLI_snprintf(str, MAX_IMAGE_INFO_LEN, IFACE_("Frame %d"), framenr);
+ }
+
+ uiItemL(col, str, ICON_NONE);
+ }
- BKE_image_user_frame_calc(iuser, (int)scene->r.cfra);
- image_info(scene, iuser, ima, ibuf, str, MAX_IMAGE_INFO_LEN);
BKE_image_release_ibuf(ima, ibuf, lock);
- uiItemL(layout, str, ICON_NONE);
}
#undef MAX_IMAGE_INFO_LEN
@@ -1304,6 +1309,7 @@ void image_buttons_register(ARegionType *art)
strcpy(pt->label, N_("Metadata"));
strcpy(pt->category, "Image");
strcpy(pt->translation_context, BLT_I18NCONTEXT_DEFAULT_BPYRNA);
+ pt->order = 10;
pt->poll = metadata_panel_context_poll;
pt->draw = metadata_panel_context_draw;
pt->flag |= PNL_DEFAULT_CLOSED;
diff --git a/source/blender/editors/space_image/image_ops.c b/source/blender/editors/space_image/image_ops.c
index 07c2d216a93..8121c577706 100644
--- a/source/blender/editors/space_image/image_ops.c
+++ b/source/blender/editors/space_image/image_ops.c
@@ -1320,7 +1320,7 @@ static int image_open_exec(bContext *C, wmOperator *op)
PointerRNA imaptr;
RNA_id_pointer_create(&ima->id, &imaptr);
- RNA_property_pointer_set(NULL, &iod->pprop.ptr, iod->pprop.prop, imaptr);
+ RNA_property_pointer_set(&iod->pprop.ptr, iod->pprop.prop, imaptr, NULL);
RNA_property_update(C, &iod->pprop.ptr, iod->pprop.prop);
}
@@ -1869,8 +1869,7 @@ static int image_save_as_invoke(bContext *C, wmOperator *op, const wmEvent *UNUS
Scene *scene = CTX_data_scene(C);
ImageSaveOptions opts;
PropertyRNA *prop;
- const bool save_as_render = ((ima->source == IMA_SRC_VIEWER) ||
- (ima->flag & IMA_VIEW_AS_RENDER));
+ const bool save_as_render = (ima->source == IMA_SRC_VIEWER);
if (RNA_struct_property_is_set(op->ptr, "filepath")) {
return image_save_as_exec(C, op);
@@ -2474,7 +2473,7 @@ static int image_new_exec(bContext *C, wmOperator *op)
PointerRNA imaptr;
RNA_id_pointer_create(&ima->id, &imaptr);
- RNA_property_pointer_set(NULL, &data->pprop.ptr, data->pprop.prop, imaptr);
+ RNA_property_pointer_set(&data->pprop.ptr, data->pprop.prop, imaptr, NULL);
RNA_property_update(C, &data->pprop.ptr, data->pprop.prop);
}
else if (sima) {
diff --git a/source/blender/editors/space_image/space_image.c b/source/blender/editors/space_image/space_image.c
index a8be93ad213..73baf1540f7 100644
--- a/source/blender/editors/space_image/space_image.c
+++ b/source/blender/editors/space_image/space_image.c
@@ -658,7 +658,8 @@ static void image_main_region_draw(const bContext *C, ARegion *ar)
BLI_thread_unlock(LOCK_DRAW_IMAGE);
}
- ED_mask_draw_region(mask,
+ ED_mask_draw_region(depsgraph,
+ mask,
ar,
sima->mask_info.draw_flag,
sima->mask_info.draw_type,
diff --git a/source/blender/editors/space_nla/space_nla.c b/source/blender/editors/space_nla/space_nla.c
index 4b7dfe5d653..3bdd2804efc 100644
--- a/source/blender/editors/space_nla/space_nla.c
+++ b/source/blender/editors/space_nla/space_nla.c
@@ -205,7 +205,7 @@ static void nla_channel_region_draw(const bContext *C, ARegion *ar)
}
/* channel filter next to scrubbing area */
- ED_channel_search_draw(C, ar, ac.ads);
+ ED_time_scrub_channel_search_draw(C, ar, ac.ads);
/* reset view matrix */
UI_view2d_view_restore(C);
@@ -290,7 +290,7 @@ static void nla_main_region_draw(const bContext *C, ARegion *ar)
/* reset view matrix */
UI_view2d_view_restore(C);
- ED_scrubbing_draw(ar, scene, snla->flag & SNLA_DRAWTIME, true);
+ ED_time_scrub_draw(ar, scene, snla->flag & SNLA_DRAWTIME, true);
/* scrollers */
scrollers = UI_view2d_scrollers_calc(v2d, NULL);
diff --git a/source/blender/editors/space_node/drawnode.c b/source/blender/editors/space_node/drawnode.c
index bf6ec961a5d..e39e024e44a 100644
--- a/source/blender/editors/space_node/drawnode.c
+++ b/source/blender/editors/space_node/drawnode.c
@@ -713,6 +713,11 @@ static void node_buts_image_user(uiLayout *layout,
PointerRNA colorspace_settings_ptr = RNA_pointer_get(imaptr, "colorspace_settings");
uiItemL(split, IFACE_("Color Space"), ICON_NONE);
uiItemR(split, &colorspace_settings_ptr, "name", 0, "", ICON_NONE);
+
+ /* Avoid losing changes image is painted. */
+ if (BKE_image_is_dirty(imaptr->data)) {
+ uiLayoutSetEnabled(split, false);
+ }
}
static void node_shader_buts_mapping(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
diff --git a/source/blender/editors/space_node/node_add.c b/source/blender/editors/space_node/node_add.c
index e677c649fb4..01a30f677a3 100644
--- a/source/blender/editors/space_node/node_add.c
+++ b/source/blender/editors/space_node/node_add.c
@@ -521,7 +521,7 @@ static int new_node_tree_exec(bContext *C, wmOperator *op)
id_us_min(&ntree->id);
RNA_id_pointer_create(&ntree->id, &idptr);
- RNA_property_pointer_set(NULL, &ptr, prop, idptr);
+ RNA_property_pointer_set(&ptr, prop, idptr, NULL);
RNA_property_update(C, &ptr, prop);
}
else if (snode) {
diff --git a/source/blender/editors/space_node/node_select.c b/source/blender/editors/space_node/node_select.c
index a8331c26ce6..aab328249fe 100644
--- a/source/blender/editors/space_node/node_select.c
+++ b/source/blender/editors/space_node/node_select.c
@@ -495,17 +495,7 @@ static int node_mouse_select(bContext *C,
}
}
- /* In case we do two-steps selection, we do not want to select the node if some valid socket
- * is below the mouse, as that would prevent draging from sockets (NODE_OT_link)
- * to be properly triggered. See T64660. */
- if (wait_to_deselect_others) {
- if (node_find_indicated_socket(snode, &node, &sock, cursor, SOCK_IN) ||
- node_find_indicated_socket(snode, &node, &sock, cursor, SOCK_OUT)) {
- ret_value = OPERATOR_CANCELLED;
- }
- }
-
- if (sock == NULL) {
+ if (!sock) {
/* find the closest visible node */
node = node_under_mouse_select(snode->edittree, (int)cursor[0], (int)cursor[1]);
diff --git a/source/blender/editors/space_outliner/outliner_draw.c b/source/blender/editors/space_outliner/outliner_draw.c
index 6a7795393c9..aed7af3911f 100644
--- a/source/blender/editors/space_outliner/outliner_draw.c
+++ b/source/blender/editors/space_outliner/outliner_draw.c
@@ -2802,7 +2802,11 @@ static void outliner_draw_tree_element(bContext *C,
BKE_view_layer_base_find(view_layer, ob);
const bool is_selected = (base != NULL) && ((base->flag & BASE_SELECTED) != 0);
- if (ob == obact || is_selected) {
+ if (ob == obact) {
+ active = OL_DRAWSEL_ACTIVE;
+ }
+
+ if (is_selected) {
if (ob == obact) {
/* active selected object */
UI_GetThemeColor3ubv(TH_ACTIVE_OBJECT, text_color);
diff --git a/source/blender/editors/space_outliner/outliner_edit.c b/source/blender/editors/space_outliner/outliner_edit.c
index 90180c4ea47..c32b2b051f8 100644
--- a/source/blender/editors/space_outliner/outliner_edit.c
+++ b/source/blender/editors/space_outliner/outliner_edit.c
@@ -88,6 +88,11 @@
static int outliner_highlight_update(bContext *C, wmOperator *UNUSED(op), const wmEvent *event)
{
+ /* stop highlighting if out of area */
+ if (!ED_screen_area_active(C)) {
+ return OPERATOR_PASS_THROUGH;
+ }
+
/* Drag and drop does own highlighting. */
wmWindowManager *wm = CTX_wm_manager(C);
if (wm->drags.first) {
diff --git a/source/blender/editors/space_outliner/outliner_select.c b/source/blender/editors/space_outliner/outliner_select.c
index c6fcf1d8cf7..bee615108f9 100644
--- a/source/blender/editors/space_outliner/outliner_select.c
+++ b/source/blender/editors/space_outliner/outliner_select.c
@@ -450,32 +450,6 @@ static eOLDrawState tree_element_active_material(bContext *C,
return OL_DRAWSEL_NONE;
}
-static eOLDrawState tree_element_active_light(bContext *UNUSED(C),
- Scene *UNUSED(scene),
- ViewLayer *view_layer,
- SpaceOutliner *soops,
- TreeElement *te,
- const eOLSetState set)
-{
- Object *ob;
-
- /* we search for the object parent */
- ob = (Object *)outliner_search_back(soops, te, ID_OB);
- if (ob == NULL || ob != OBACT(view_layer)) {
- /* just paranoia */
- return OL_DRAWSEL_NONE;
- }
-
- if (set != OL_SETSEL_NONE) {
- // XXX extern_set_butspace(F5KEY, 0);
- }
- else {
- return OL_DRAWSEL_NORMAL;
- }
-
- return OL_DRAWSEL_NONE;
-}
-
static eOLDrawState tree_element_active_camera(bContext *UNUSED(C),
Scene *scene,
ViewLayer *UNUSED(sl),
@@ -1041,8 +1015,6 @@ eOLDrawState tree_element_active(bContext *C,
return tree_element_active_material(C, scene, view_layer, soops, te, set);
case ID_WO:
return tree_element_active_world(C, scene, view_layer, soops, te, set);
- case ID_LA:
- return tree_element_active_light(C, scene, view_layer, soops, te, set);
case ID_TXT:
return tree_element_active_text(C, scene, view_layer, soops, te, set);
case ID_CA:
@@ -1160,7 +1132,7 @@ static void do_outliner_item_activate_tree_element(bContext *C,
WM_window_set_active_scene(CTX_data_main(C), C, CTX_wm_window(C), (Scene *)tselem->id);
}
}
- else if (te->idcode == ID_GR) {
+ else if ((te->idcode == ID_GR) && (soops->outlinevis != SO_VIEW_LAYER)) {
Collection *gr = (Collection *)tselem->id;
if (extend) {
diff --git a/source/blender/editors/space_outliner/outliner_tree.c b/source/blender/editors/space_outliner/outliner_tree.c
index 80424f021e2..6da2e913003 100644
--- a/source/blender/editors/space_outliner/outliner_tree.c
+++ b/source/blender/editors/space_outliner/outliner_tree.c
@@ -1808,7 +1808,7 @@ static void outliner_collections_children_sort(ListBase *lb)
}
for (te = lb->first; te; te = te->next) {
- outliner_sort(&te->subtree);
+ outliner_collections_children_sort(&te->subtree);
}
}
diff --git a/source/blender/editors/space_outliner/space_outliner.c b/source/blender/editors/space_outliner/space_outliner.c
index 4c591a61f67..091efc56c09 100644
--- a/source/blender/editors/space_outliner/space_outliner.c
+++ b/source/blender/editors/space_outliner/space_outliner.c
@@ -303,6 +303,7 @@ static SpaceLink *outliner_new(const ScrArea *UNUSED(area), const Scene *UNUSED(
soutliner->spacetype = SPACE_OUTLINER;
soutliner->filter_id_type = ID_GR;
soutliner->show_restrict_flags = SO_RESTRICT_ENABLE | SO_RESTRICT_HIDE;
+ soutliner->outlinevis = SO_VIEW_LAYER;
/* header */
ar = MEM_callocN(sizeof(ARegion), "header for outliner");
@@ -384,6 +385,14 @@ static void outliner_id_remap(ScrArea *UNUSED(sa), SpaceLink *slink, ID *old_id,
}
}
+static void outliner_deactivate(struct ScrArea *sa)
+{
+ /* Remove hover highlights */
+ SpaceOutliner *soops = sa->spacedata.first;
+ outliner_flag_set(&soops->tree, TSE_HIGHLIGHTED, false);
+ ED_region_tag_redraw(BKE_area_find_region_type(sa, RGN_TYPE_WINDOW));
+}
+
/* only called once, from space_api/spacetypes.c */
void ED_spacetype_outliner(void)
{
@@ -401,6 +410,7 @@ void ED_spacetype_outliner(void)
st->keymap = outliner_keymap;
st->dropboxes = outliner_dropboxes;
st->id_remap = outliner_id_remap;
+ st->deactivate = outliner_deactivate;
/* regions: main window */
art = MEM_callocN(sizeof(ARegionType), "spacetype outliner region");
diff --git a/source/blender/editors/space_sequencer/sequencer_add.c b/source/blender/editors/space_sequencer/sequencer_add.c
index b5bb79fb430..e8f18eeebc7 100644
--- a/source/blender/editors/space_sequencer/sequencer_add.c
+++ b/source/blender/editors/space_sequencer/sequencer_add.c
@@ -149,7 +149,7 @@ static int sequencer_generic_invoke_xy_guess_channel(bContext *C, int type)
int proximity = INT_MAX;
if (!ed || !ed->seqbasep) {
- return 1;
+ return 2;
}
for (seq = ed->seqbasep->first; seq; seq = seq->next) {
@@ -161,9 +161,9 @@ static int sequencer_generic_invoke_xy_guess_channel(bContext *C, int type)
}
if (tgt) {
- return tgt->machine;
+ return tgt->machine + 1;
}
- return 1;
+ return 2;
}
static void sequencer_generic_invoke_xy__internal(bContext *C, wmOperator *op, int flag, int type)
@@ -173,7 +173,7 @@ static void sequencer_generic_invoke_xy__internal(bContext *C, wmOperator *op, i
int cfra = (int)CFRA;
/* effect strips don't need a channel initialized from the mouse */
- if (!(flag & SEQPROP_NOCHAN)) {
+ if (!(flag & SEQPROP_NOCHAN) && RNA_struct_property_is_set(op->ptr, "channel") == 0) {
RNA_int_set(op->ptr, "channel", sequencer_generic_invoke_xy_guess_channel(C, type));
}
diff --git a/source/blender/editors/space_sequencer/sequencer_draw.c b/source/blender/editors/space_sequencer/sequencer_draw.c
index 805ec26950a..a59cc36f28e 100644
--- a/source/blender/editors/space_sequencer/sequencer_draw.c
+++ b/source/blender/editors/space_sequencer/sequencer_draw.c
@@ -1121,8 +1121,7 @@ static void sequencer_display_size(Scene *scene, float r_viewrect[2])
r_viewrect[0] = (float)scene->r.xsch;
r_viewrect[1] = (float)scene->r.ysch;
- /* Aspect ratio seems to have no effect on output image*/
- /* r_viewrect[0] *= scene->r.xasp / scene->r.yasp; */
+ r_viewrect[0] *= scene->r.xasp / scene->r.yasp;
}
static void sequencer_draw_gpencil(const bContext *C)
@@ -1822,7 +1821,7 @@ typedef struct CacheDrawData {
/* Called as a callback */
static bool draw_cache_view_cb(
- void *userdata, struct Sequence *seq, int cfra, int cache_type, float UNUSED(cost))
+ void *userdata, struct Sequence *seq, int nfra, int cache_type, float UNUSED(cost))
{
CacheDrawData *drawdata = userdata;
const bContext *C = drawdata->C;
@@ -1902,6 +1901,7 @@ static bool draw_cache_view_cb(
}
}
+ int cfra = seq->start + nfra;
immUniformColor4f(color[0], color[1], color[2], color[3]);
immRectf(pos, cfra, stripe_bot, cfra + 1, stripe_top);
@@ -2087,7 +2087,7 @@ void draw_timeline_seq(const bContext *C, ARegion *ar)
UI_view2d_view_restore(C);
/* scrubbing region */
- ED_scrubbing_draw(ar, scene, !(sseq->flag & SEQ_DRAWFRAMES), true);
+ ED_time_scrub_draw(ar, scene, !(sseq->flag & SEQ_DRAWFRAMES), true);
/* scrollers */
scrollers = UI_view2d_scrollers_calc(v2d, NULL);
@@ -2101,7 +2101,7 @@ void draw_timeline_seq(const bContext *C, ARegion *ar)
0,
15 * UI_DPI_FAC,
15 * UI_DPI_FAC,
- UI_DPI_FAC * ar->sizey - UI_SCRUBBING_MARGIN_Y);
+ UI_DPI_FAC * ar->sizey - UI_TIME_SCRUB_MARGIN_Y);
UI_view2d_draw_scale_y__block(ar, v2d, &rect, TH_SCROLL_TEXT);
}
}
diff --git a/source/blender/editors/space_sequencer/sequencer_edit.c b/source/blender/editors/space_sequencer/sequencer_edit.c
index a3030153e6c..a998ae7a7b3 100644
--- a/source/blender/editors/space_sequencer/sequencer_edit.c
+++ b/source/blender/editors/space_sequencer/sequencer_edit.c
@@ -2680,7 +2680,7 @@ static int sequencer_meta_make_exec(bContext *C, wmOperator *op)
while (seq) {
next = seq->next;
if (seq != seqm && (seq->flag & SELECT)) {
- BKE_sequence_invalidate_cache(scene, seq);
+ BKE_sequence_invalidate_dependent(scene, seq);
channel_max = max_ii(seq->machine, channel_max);
BLI_remlink(ed->seqbasep, seq);
BLI_addtail(&seqm->seqbase, seq);
@@ -2755,7 +2755,7 @@ static int sequencer_meta_separate_exec(bContext *C, wmOperator *UNUSED(op))
}
for (seq = last_seq->seqbase.first; seq != NULL; seq = seq->next) {
- BKE_sequence_invalidate_cache(scene, seq);
+ BKE_sequence_invalidate_dependent(scene, seq);
}
BLI_movelisttolist(ed->seqbasep, &last_seq->seqbase);
@@ -3518,8 +3518,8 @@ static int sequencer_swap_data_exec(bContext *C, wmOperator *op)
BKE_sound_add_scene_sound_defaults(scene, seq_other);
}
- BKE_sequence_invalidate_cache(scene, seq_act);
- BKE_sequence_invalidate_cache(scene, seq_other);
+ BKE_sequence_invalidate_cache_raw(scene, seq_act);
+ BKE_sequence_invalidate_cache_raw(scene, seq_other);
WM_event_add_notifier(C, NC_SCENE | ND_SEQUENCER, scene);
diff --git a/source/blender/editors/space_sequencer/sequencer_modifier.c b/source/blender/editors/space_sequencer/sequencer_modifier.c
index e00d33853a3..f262c6518aa 100644
--- a/source/blender/editors/space_sequencer/sequencer_modifier.c
+++ b/source/blender/editors/space_sequencer/sequencer_modifier.c
@@ -64,7 +64,7 @@ static int strip_modifier_add_exec(bContext *C, wmOperator *op)
BKE_sequence_modifier_new(seq, NULL, type);
- BKE_sequence_invalidate_cache(scene, seq);
+ BKE_sequence_invalidate_cache_preprocessed(scene, seq);
WM_event_add_notifier(C, NC_SCENE | ND_SEQUENCER, scene);
return OPERATOR_FINISHED;
@@ -115,7 +115,7 @@ static int strip_modifier_remove_exec(bContext *C, wmOperator *op)
BLI_remlink(&seq->modifiers, smd);
BKE_sequence_modifier_free(smd);
- BKE_sequence_invalidate_cache(scene, seq);
+ BKE_sequence_invalidate_cache_preprocessed(scene, seq);
WM_event_add_notifier(C, NC_SCENE | ND_SEQUENCER, scene);
return OPERATOR_FINISHED;
@@ -175,7 +175,7 @@ static int strip_modifier_move_exec(bContext *C, wmOperator *op)
}
}
- BKE_sequence_invalidate_cache(scene, seq);
+ BKE_sequence_invalidate_cache_preprocessed(scene, seq);
WM_event_add_notifier(C, NC_SCENE | ND_SEQUENCER, scene);
return OPERATOR_FINISHED;
@@ -249,7 +249,7 @@ static int strip_modifier_copy_exec(bContext *C, wmOperator *op)
}
SEQ_END;
- BKE_sequence_invalidate_cache(scene, seq);
+ BKE_sequence_invalidate_cache_preprocessed(scene, seq);
WM_event_add_notifier(C, NC_SCENE | ND_SEQUENCER, scene);
return OPERATOR_FINISHED;
diff --git a/source/blender/editors/space_sequencer/sequencer_view.c b/source/blender/editors/space_sequencer/sequencer_view.c
index e16029395bd..593dd86477a 100644
--- a/source/blender/editors/space_sequencer/sequencer_view.c
+++ b/source/blender/editors/space_sequencer/sequencer_view.c
@@ -108,6 +108,8 @@ static void sample_apply(bContext *C, wmOperator *op, const wmEvent *event)
UI_view2d_region_to_view(&ar->v2d, event->mval[0], event->mval[1], &fx, &fy);
+ fx /= scene->r.xasp / scene->r.yasp;
+
fx += (float)scene->r.xsch / 2.0f;
fy += (float)scene->r.ysch / 2.0f;
fx *= (float)ibuf->x / (float)scene->r.xsch;
diff --git a/source/blender/editors/space_sequencer/space_sequencer.c b/source/blender/editors/space_sequencer/space_sequencer.c
index 7a02b1850ae..6ab44ded046 100644
--- a/source/blender/editors/space_sequencer/space_sequencer.c
+++ b/source/blender/editors/space_sequencer/space_sequencer.c
@@ -729,6 +729,7 @@ static void sequencer_buttons_region_init(wmWindowManager *wm, ARegion *ar)
keymap = WM_keymap_ensure(wm->defaultconf, "SequencerCommon", SPACE_SEQ, 0);
WM_event_add_keymap_handler_v2d_mask(&ar->handlers, keymap);
+ UI_panel_category_active_set_default(ar, "Strip");
ED_region_panels_init(wm, ar);
}
diff --git a/source/blender/editors/space_text/text_ops.c b/source/blender/editors/space_text/text_ops.c
index a9dd2a59d1e..2593571d9a3 100644
--- a/source/blender/editors/space_text/text_ops.c
+++ b/source/blender/editors/space_text/text_ops.c
@@ -247,7 +247,7 @@ static int text_new_exec(bContext *C, wmOperator *UNUSED(op))
if (prop) {
RNA_id_pointer_create(&text->id, &idptr);
- RNA_property_pointer_set(NULL, &ptr, prop, idptr);
+ RNA_property_pointer_set(&ptr, prop, idptr, NULL);
RNA_property_update(C, &ptr, prop);
}
else if (st) {
@@ -326,7 +326,7 @@ static int text_open_exec(bContext *C, wmOperator *op)
if (pprop->prop) {
RNA_id_pointer_create(&text->id, &idptr);
- RNA_property_pointer_set(NULL, &pprop->ptr, pprop->prop, idptr);
+ RNA_property_pointer_set(&pprop->ptr, pprop->prop, idptr, NULL);
RNA_property_update(C, &pprop->ptr, pprop->prop);
}
else if (st) {
diff --git a/source/blender/editors/space_userpref/userpref_ops.c b/source/blender/editors/space_userpref/userpref_ops.c
index a67e6c27acb..04ef2ed8118 100644
--- a/source/blender/editors/space_userpref/userpref_ops.c
+++ b/source/blender/editors/space_userpref/userpref_ops.c
@@ -48,7 +48,7 @@ static int reset_default_theme_exec(bContext *C, wmOperator *UNUSED(op))
UI_theme_init_default();
UI_style_init_default();
WM_event_add_notifier(C, NC_WINDOW, NULL);
-
+ U.runtime.is_dirty = true;
return OPERATOR_FINISHED;
}
diff --git a/source/blender/editors/space_view3d/view3d_draw.c b/source/blender/editors/space_view3d/view3d_draw.c
index afc3b80fe3e..2ce67bfbe4c 100644
--- a/source/blender/editors/space_view3d/view3d_draw.c
+++ b/source/blender/editors/space_view3d/view3d_draw.c
@@ -105,7 +105,8 @@ void ED_view3d_update_viewmat(Depsgraph *depsgraph,
ARegion *ar,
float viewmat[4][4],
float winmat[4][4],
- const rcti *rect)
+ const rcti *rect,
+ bool offscreen)
{
RegionView3D *rv3d = ar->regiondata;
@@ -138,7 +139,7 @@ void ED_view3d_update_viewmat(Depsgraph *depsgraph,
/* calculate GLSL view dependent values */
/* store window coordinates scaling/offset */
- if (rv3d->persp == RV3D_CAMOB && v3d->camera) {
+ if (!offscreen && rv3d->persp == RV3D_CAMOB && v3d->camera) {
rctf cameraborder;
ED_view3d_calc_camera_border(scene, depsgraph, ar, v3d, rv3d, &cameraborder, false);
rv3d->viewcamtexcofac[0] = (float)ar->winx / BLI_rctf_size_x(&cameraborder);
@@ -184,7 +185,22 @@ static void view3d_main_region_setup_view(Depsgraph *depsgraph,
{
RegionView3D *rv3d = ar->regiondata;
- ED_view3d_update_viewmat(depsgraph, scene, v3d, ar, viewmat, winmat, rect);
+ ED_view3d_update_viewmat(depsgraph, scene, v3d, ar, viewmat, winmat, rect, false);
+
+ /* set for opengl */
+ GPU_matrix_projection_set(rv3d->winmat);
+ GPU_matrix_set(rv3d->viewmat);
+}
+
+static void view3d_main_region_setup_offscreen(Depsgraph *depsgraph,
+ Scene *scene,
+ View3D *v3d,
+ ARegion *ar,
+ float viewmat[4][4],
+ float winmat[4][4])
+{
+ RegionView3D *rv3d = ar->regiondata;
+ ED_view3d_update_viewmat(depsgraph, scene, v3d, ar, viewmat, winmat, NULL, true);
/* set for opengl */
GPU_matrix_projection_set(rv3d->winmat);
@@ -1480,14 +1496,14 @@ static void view3d_stereo3d_setup_offscreen(Depsgraph *depsgraph,
const bool is_left = STREQ(viewname, STEREO_LEFT_NAME);
BKE_camera_multiview_view_matrix(&scene->r, v3d->camera, is_left, viewmat);
- view3d_main_region_setup_view(depsgraph, scene, v3d, ar, viewmat, winmat, NULL);
+ view3d_main_region_setup_offscreen(depsgraph, scene, v3d, ar, viewmat, winmat);
}
else { /* SCE_VIEWS_FORMAT_MULTIVIEW */
float viewmat[4][4];
Object *camera = BKE_camera_multiview_render(scene, v3d->camera, viewname);
BKE_camera_multiview_view_matrix(&scene->r, camera, false, viewmat);
- view3d_main_region_setup_view(depsgraph, scene, v3d, ar, viewmat, winmat, NULL);
+ view3d_main_region_setup_offscreen(depsgraph, scene, v3d, ar, viewmat, winmat);
}
}
@@ -1545,7 +1561,7 @@ void ED_view3d_draw_offscreen(Depsgraph *depsgraph,
view3d_stereo3d_setup_offscreen(depsgraph, scene, v3d, ar, winmat, viewname);
}
else {
- view3d_main_region_setup_view(depsgraph, scene, v3d, ar, viewmat, winmat, NULL);
+ view3d_main_region_setup_offscreen(depsgraph, scene, v3d, ar, viewmat, winmat);
}
/* main drawing call */
@@ -1579,7 +1595,6 @@ ImBuf *ED_view3d_draw_offscreen_imbuf(Depsgraph *depsgraph,
int sizex,
int sizey,
uint flag,
- uint draw_flags,
int alpha_mode,
int samples,
const char *viewname,
@@ -1589,7 +1604,6 @@ ImBuf *ED_view3d_draw_offscreen_imbuf(Depsgraph *depsgraph,
{
RegionView3D *rv3d = ar->regiondata;
const bool draw_sky = (alpha_mode == R_ADDSKY);
- const bool use_full_sample = (draw_flags & V3D_OFSDRAW_USE_FULL_SAMPLE);
/* view state */
bool is_ortho = false;
@@ -1611,7 +1625,7 @@ ImBuf *ED_view3d_draw_offscreen_imbuf(Depsgraph *depsgraph,
if (own_ofs) {
/* bind */
- ofs = GPU_offscreen_create(sizex, sizey, use_full_sample ? 0 : samples, true, false, err_out);
+ ofs = GPU_offscreen_create(sizex, sizey, samples, true, false, err_out);
if (ofs == NULL) {
DRW_opengl_context_disable();
return NULL;
@@ -1667,120 +1681,28 @@ ImBuf *ED_view3d_draw_offscreen_imbuf(Depsgraph *depsgraph,
}
}
- if ((samples && use_full_sample) == 0) {
- const bool do_color_management = (ibuf->rect_float == NULL);
- /* Single-pass render, common case */
- ED_view3d_draw_offscreen(depsgraph,
- scene,
- drawtype,
- v3d,
- ar,
- sizex,
- sizey,
- NULL,
- winmat,
- draw_sky,
- !is_ortho,
- viewname,
- do_color_management,
- ofs,
- NULL);
-
- if (ibuf->rect_float) {
- GPU_offscreen_read_pixels(ofs, GL_FLOAT, ibuf->rect_float);
- }
- else if (ibuf->rect) {
- GPU_offscreen_read_pixels(ofs, GL_UNSIGNED_BYTE, ibuf->rect);
- }
- }
- else {
- /* Multi-pass render, use accumulation buffer & jitter for 'full' oversampling.
- * Use because OpenGL may use a lower quality MSAA, and only over-sample edges. */
- static float jit_ofs[32][2];
- float winmat_jitter[4][4];
- float *rect_temp = (ibuf->rect_float) ?
- ibuf->rect_float :
- MEM_mallocN(sizex * sizey * sizeof(float[4]), "rect_temp");
- float *accum_buffer = MEM_mallocN(sizex * sizey * sizeof(float[4]), "accum_buffer");
- GPUViewport *viewport = GPU_viewport_create_from_offscreen(ofs);
-
- BLI_jitter_init(jit_ofs, samples);
-
- /* first sample buffer, also initializes 'rv3d->persmat' */
- ED_view3d_draw_offscreen(depsgraph,
- scene,
- drawtype,
- v3d,
- ar,
- sizex,
- sizey,
- NULL,
- winmat,
- draw_sky,
- !is_ortho,
- viewname,
- false,
- ofs,
- viewport);
- GPU_offscreen_read_pixels(ofs, GL_FLOAT, accum_buffer);
-
- /* skip the first sample */
- for (int j = 1; j < samples; j++) {
- copy_m4_m4(winmat_jitter, winmat);
- window_translate_m4(winmat_jitter,
- rv3d->persmat,
- (jit_ofs[j][0] * 2.0f) / sizex,
- (jit_ofs[j][1] * 2.0f) / sizey);
-
- ED_view3d_draw_offscreen(depsgraph,
- scene,
- drawtype,
- v3d,
- ar,
- sizex,
- sizey,
- NULL,
- winmat_jitter,
- draw_sky,
- !is_ortho,
- viewname,
- false,
- ofs,
- viewport);
- GPU_offscreen_read_pixels(ofs, GL_FLOAT, rect_temp);
-
- uint i = sizex * sizey * 4;
- while (i--) {
- accum_buffer[i] += rect_temp[i];
- }
- }
-
- {
- /* don't free data owned by 'ofs' */
- GPU_viewport_clear_from_offscreen(viewport);
- GPU_viewport_free(viewport);
- }
+ const bool do_color_management = (ibuf->rect_float == NULL);
+ ED_view3d_draw_offscreen(depsgraph,
+ scene,
+ drawtype,
+ v3d,
+ ar,
+ sizex,
+ sizey,
+ NULL,
+ winmat,
+ draw_sky,
+ !is_ortho,
+ viewname,
+ do_color_management,
+ ofs,
+ NULL);
- if (ibuf->rect_float == NULL) {
- MEM_freeN(rect_temp);
- }
-
- if (ibuf->rect_float) {
- float *rect_float = ibuf->rect_float;
- uint i = sizex * sizey * 4;
- while (i--) {
- rect_float[i] = accum_buffer[i] / samples;
- }
- }
- else {
- uchar *rect_ub = (uchar *)ibuf->rect;
- uint i = sizex * sizey * 4;
- while (i--) {
- rect_ub[i] = (uchar)(255.0f * accum_buffer[i] / samples);
- }
- }
-
- MEM_freeN(accum_buffer);
+ if (ibuf->rect_float) {
+ GPU_offscreen_read_pixels(ofs, GL_FLOAT, ibuf->rect_float);
+ }
+ else if (ibuf->rect) {
+ GPU_offscreen_read_pixels(ofs, GL_UNSIGNED_BYTE, ibuf->rect);
}
/* unbind */
@@ -1889,7 +1811,6 @@ ImBuf *ED_view3d_draw_offscreen_imbuf_simple(Depsgraph *depsgraph,
width,
height,
flag,
- draw_flags,
alpha_mode,
samples,
viewname,
diff --git a/source/blender/editors/space_view3d/view3d_draw_legacy.c b/source/blender/editors/space_view3d/view3d_draw_legacy.c
index e0dbe1f6543..755852a2e18 100644
--- a/source/blender/editors/space_view3d/view3d_draw_legacy.c
+++ b/source/blender/editors/space_view3d/view3d_draw_legacy.c
@@ -152,13 +152,11 @@ void ED_view3d_clipping_enable(void)
/* *********************** backdraw for selection *************** */
-static void validate_object_select_id(struct Depsgraph *depsgraph,
- Scene *scene,
- ARegion *ar,
- View3D *v3d,
- Object *obact,
- Object *obedit,
- short select_mode)
+/**
+ * \note Only use in object mode.
+ */
+static void validate_object_select_id(
+ struct Depsgraph *depsgraph, Scene *scene, ARegion *ar, View3D *v3d, Object *obact)
{
RegionView3D *rv3d = ar->regiondata;
Scene *scene_eval = (Scene *)DEG_get_evaluated_id(depsgraph, &scene->id);
@@ -178,9 +176,6 @@ static void validate_object_select_id(struct Depsgraph *depsgraph,
else if ((obact_eval && (obact_eval->mode & OB_MODE_PARTICLE_EDIT)) && !XRAY_ENABLED(v3d)) {
/* do nothing */
}
- else if ((obedit && (obedit->mode & OB_MODE_EDIT)) && !XRAY_FLAG_ENABLED(v3d)) {
- /* do nothing */
- }
else {
v3d->flag &= ~V3D_INVALID_BACKBUF;
return;
@@ -190,34 +185,18 @@ static void validate_object_select_id(struct Depsgraph *depsgraph,
return;
}
-#if 0
- if (test) {
- if (qtest()) {
- addafterqueue(ar->win, BACKBUFDRAW, 1);
- return;
- }
- }
-#endif
-
-#if 0 /* v3d->zbuf deprecated */
- if (v3d->shading.type > OB_WIRE) {
- v3d->zbuf = true;
- }
-#endif
-
- G.f |= G_FLAG_BACKBUFSEL;
-
if (obact_eval && ((obact_eval->base_flag & BASE_VISIBLE) != 0)) {
+ uint dummy_vert_ofs, dummy_edge_ofs, dummy_face_ofs;
DRW_framebuffer_select_id_setup(ar, true);
DRW_draw_select_id_object(scene_eval,
rv3d,
obact_eval,
- select_mode,
+ scene->toolsettings->selectmode,
false,
- 0,
- &bm_vertoffs,
- &bm_wireoffs,
- &bm_solidoffs);
+ 1,
+ &dummy_vert_ofs,
+ &dummy_edge_ofs,
+ &dummy_face_ofs);
DRW_framebuffer_select_id_release(ar);
}
@@ -225,8 +204,6 @@ static void validate_object_select_id(struct Depsgraph *depsgraph,
/* TODO: Create a flag in `DRW_manager` because the drawing is no longer
* made on the backbuffer in this case. */
v3d->flag &= ~V3D_INVALID_BACKBUF;
-
- G.f &= ~G_FLAG_BACKBUFSEL;
}
/* TODO: Creating, attaching texture, and destroying a framebuffer is quite slow.
@@ -251,21 +228,15 @@ static void view3d_opengl_read_Z_pixels(GPUViewport *viewport, rcti *rect, void
GPU_framebuffer_free(tmp_fb);
}
-void ED_view3d_select_id_validate_with_select_mode(ViewContext *vc, short select_mode)
+void ED_view3d_select_id_validate(ViewContext *vc)
{
/* TODO: Create a flag in `DRW_manager` because the drawing is no longer
* made on the backbuffer in this case. */
if (vc->v3d->flag & V3D_INVALID_BACKBUF) {
- validate_object_select_id(
- vc->depsgraph, vc->scene, vc->ar, vc->v3d, vc->obact, vc->obedit, select_mode);
+ validate_object_select_id(vc->depsgraph, vc->scene, vc->ar, vc->v3d, vc->obact);
}
}
-void ED_view3d_select_id_validate(ViewContext *vc)
-{
- ED_view3d_select_id_validate_with_select_mode(vc, -1);
-}
-
void ED_view3d_backbuf_depth_validate(ViewContext *vc)
{
if (vc->v3d->flag & V3D_INVALID_BACKBUF) {
@@ -281,7 +252,7 @@ void ED_view3d_backbuf_depth_validate(ViewContext *vc)
}
}
-uint *ED_view3d_select_id_read_rect(ViewContext *UNUSED(vc), const rcti *clip, uint *r_buf_len)
+uint *ED_view3d_select_id_read_rect(const rcti *clip, uint *r_buf_len)
{
uint width = BLI_rcti_size_x(clip);
uint height = BLI_rcti_size_y(clip);
@@ -306,25 +277,8 @@ int ED_view3d_backbuf_sample_size_clamp(ARegion *ar, const float dist)
return (int)min_ff(ceilf(dist), (float)max_ii(ar->winx, ar->winx));
}
-/* samples a single pixel (copied from vpaint) */
-uint ED_view3d_select_id_sample(ViewContext *vc, int x, int y)
-{
- if (x >= vc->ar->winx || y >= vc->ar->winy) {
- return 0;
- }
-
- uint buf_len;
- uint *buf = ED_view3d_select_id_read(vc, x, y, x, y, &buf_len);
- BLI_assert(0 != buf_len);
- uint ret = buf[0];
- MEM_freeN(buf);
-
- return ret;
-}
-
/* reads full rect, converts indices */
-uint *ED_view3d_select_id_read(
- ViewContext *vc, int xmin, int ymin, int xmax, int ymax, uint *r_buf_len)
+uint *ED_view3d_select_id_read(int xmin, int ymin, int xmax, int ymax, uint *r_buf_len)
{
if (UNLIKELY((xmin > xmax) || (ymin > ymax))) {
return NULL;
@@ -338,7 +292,7 @@ uint *ED_view3d_select_id_read(
};
uint buf_len;
- uint *buf = ED_view3d_select_id_read_rect(vc, &rect, &buf_len);
+ uint *buf = ED_view3d_select_id_read_rect(&rect, &buf_len);
if (r_buf_len) {
*r_buf_len = buf_len;
@@ -347,85 +301,6 @@ uint *ED_view3d_select_id_read(
return buf;
}
-/* smart function to sample a rect spiralling outside, nice for backbuf selection */
-uint ED_view3d_select_id_read_nearest(struct ViewContext *UNUSED(vc),
- const int mval[2],
- const uint id_min,
- const uint id_max,
- uint *r_dist)
-{
- /* Create region around mouse cursor. This must be square and have an odd
- * width, the spiraling algorithm does not work with arbitrary rectangles. */
- rcti rect;
- BLI_rcti_init_pt_radius(&rect, mval, *r_dist);
- rect.xmax += 1;
- rect.ymax += 1;
-
- int width = BLI_rcti_size_x(&rect);
- int height = width;
- BLI_assert(width == height);
-
- /* Read from selection framebuffer. */
- uint *buf = MEM_mallocN(width * height * sizeof(*buf), __func__);
- DRW_framebuffer_select_id_read(&rect, buf);
-
- /* Spiral, starting from center of buffer. */
- int spiral_offset = height * (int)(width / 2) + (height / 2);
- int spiral_direction = 0;
-
- uint index = 0;
-
- for (int nr = 1; nr <= height; nr++) {
- for (int a = 0; a < 2; a++) {
- for (int b = 0; b < nr; b++) {
- /* Find hit within the specified range. */
- uint hit_id = buf[spiral_offset];
-
- if (hit_id && hit_id >= id_min && hit_id < id_max) {
- /* Get x/y from spiral offset. */
- int hit_x = spiral_offset % width;
- int hit_y = spiral_offset / width;
-
- int center_x = width / 2;
- int center_y = height / 2;
-
- /* Manhatten distance in keeping with other screen-based selection. */
- *r_dist = (uint)(abs(hit_x - center_x) + abs(hit_y - center_y));
-
- /* Indices start at 1 here. */
- index = (hit_id - id_min) + 1;
- goto exit;
- }
-
- /* Next spiral step. */
- if (spiral_direction == 0) {
- spiral_offset += 1; /* right */
- }
- else if (spiral_direction == 1) {
- spiral_offset -= width; /* down */
- }
- else if (spiral_direction == 2) {
- spiral_offset -= 1; /* left */
- }
- else {
- spiral_offset += width; /* up */
- }
-
- /* Stop if we are outside the buffer. */
- if (spiral_offset < 0 || spiral_offset >= width * height) {
- goto exit;
- }
- }
-
- spiral_direction = (spiral_direction + 1) % 4;
- }
- }
-
-exit:
- MEM_freeN(buf);
- return index;
-}
-
/* ************************************************************* */
static void view3d_stereo_bgpic_setup(Scene *scene, View3D *v3d, Image *ima, ImageUser *iuser)
diff --git a/source/blender/editors/space_view3d/view3d_gizmo_navigate.c b/source/blender/editors/space_view3d/view3d_gizmo_navigate.c
index 5af6fd8b04b..d39be3d8e20 100644
--- a/source/blender/editors/space_view3d/view3d_gizmo_navigate.c
+++ b/source/blender/editors/space_view3d/view3d_gizmo_navigate.c
@@ -131,7 +131,7 @@ static bool WIDGETGROUP_navigate_poll(const bContext *C, wmGizmoGroupType *UNUSE
return true;
}
-static void WIDGETGROUP_navigate_setup(const bContext *UNUSED(C), wmGizmoGroup *gzgroup)
+static void WIDGETGROUP_navigate_setup(const bContext *C, wmGizmoGroup *gzgroup)
{
struct NavigateWidgetGroup *navgroup = MEM_callocN(sizeof(struct NavigateWidgetGroup), __func__);
@@ -227,6 +227,9 @@ static void WIDGETGROUP_navigate_setup(const bContext *UNUSED(C), wmGizmoGroup *
}
/* When dragging an axis, use this instead. */
+ wmWindowManager *wm = CTX_wm_manager(C);
+ gz->keymap = WM_keymap_ensure(
+ wm->defaultconf, "Generic Gizmo Click Drag", SPACE_EMPTY, RGN_TYPE_WINDOW);
gz->drag_part = 0;
}
diff --git a/source/blender/editors/space_view3d/view3d_select.c b/source/blender/editors/space_view3d/view3d_select.c
index 419ec87eec8..b3b4910c525 100644
--- a/source/blender/editors/space_view3d/view3d_select.c
+++ b/source/blender/editors/space_view3d/view3d_select.c
@@ -41,6 +41,7 @@
#include "MEM_guardedalloc.h"
#include "BLI_array.h"
+#include "BLI_bitmap.h"
#include "BLI_math.h"
#include "BLI_lasso_2d.h"
#include "BLI_rect.h"
@@ -88,6 +89,7 @@
#include "ED_mesh.h"
#include "ED_object.h"
#include "ED_screen.h"
+#include "ED_select_buffer_utils.h"
#include "ED_select_utils.h"
#include "ED_sculpt.h"
#include "ED_mball.h"
@@ -179,20 +181,96 @@ static bool object_deselect_all_except(ViewLayer *view_layer, Base *b)
/** \} */
/* -------------------------------------------------------------------- */
+/** \name Internal Edit-Mesh Select Buffer Wrapper
+ *
+ * Avoid duplicate code when using edit-mode selection,
+ * actual logic is handled outside of this function.
+ *
+ * \note Currently this #EDBMSelectID_Context which is mesh specific
+ * however the logic could also be used for non-meshes too.
+ *
+ * \{ */
+
+struct EditSelectBuf_Cache {
+ Base **bases;
+ uint bases_len;
+ struct EDBMSelectID_Context *sel_id_ctx;
+ BLI_bitmap *select_bitmap;
+};
+
+static void editselect_buf_cache_init(struct EditSelectBuf_Cache *esel, ViewContext *vc)
+{
+ if (vc->obedit) {
+ esel->bases = BKE_view_layer_array_from_bases_in_edit_mode(
+ vc->view_layer, vc->v3d, &esel->bases_len);
+ }
+ else {
+ /* Use for paint modes, currently only a single object at a time. */
+ if (vc->obact) {
+ esel->bases = MEM_mallocN(sizeof(esel->bases), __func__);
+ esel->bases[0] = BKE_view_layer_base_find(vc->view_layer, vc->obact);
+ esel->bases_len = 1;
+ }
+ else {
+ esel->bases = NULL;
+ esel->bases_len = 0;
+ }
+ }
+ esel->sel_id_ctx = EDBM_select_id_context_create(
+ vc, esel->bases, esel->bases_len, vc->scene->toolsettings->selectmode);
+ for (int i = 0; i < esel->bases_len; i++) {
+ esel->bases[i]->object->runtime.select_id = i;
+ }
+}
+
+static void editselect_buf_cache_free(struct EditSelectBuf_Cache *esel)
+{
+ if (esel->sel_id_ctx) {
+ EDBM_select_id_context_destroy(esel->sel_id_ctx);
+ }
+ MEM_SAFE_FREE(esel->select_bitmap);
+ MEM_SAFE_FREE(esel->bases);
+}
+
+static void editselect_buf_cache_free_voidp(void *esel_voidp)
+{
+ editselect_buf_cache_free(esel_voidp);
+ MEM_freeN(esel_voidp);
+}
+
+static void editselect_buf_cache_init_with_generic_userdata(wmGenericUserData *wm_userdata,
+ ViewContext *vc)
+{
+ struct EditSelectBuf_Cache *esel = MEM_callocN(sizeof(*esel), __func__);
+ wm_userdata->data = esel;
+ wm_userdata->free_fn = editselect_buf_cache_free_voidp;
+ wm_userdata->use_free = true;
+ editselect_buf_cache_init(esel, vc);
+}
+
+/** \} */
+
+/* -------------------------------------------------------------------- */
/** \name Internal Edit-Mesh Utilities
* \{ */
-static bool edbm_backbuf_check_and_select_verts(BMEditMesh *em, const eSelectOp sel_op)
+static bool edbm_backbuf_check_and_select_verts(struct EditSelectBuf_Cache *esel,
+ Object *ob,
+ BMEditMesh *em,
+ const eSelectOp sel_op)
{
BMVert *eve;
BMIter iter;
- uint index = bm_wireoffs;
bool changed = false;
+ const BLI_bitmap *select_bitmap = esel->select_bitmap;
+ uint index = EDBM_select_id_context_offset_for_object_elem(
+ esel->sel_id_ctx, ob->runtime.select_id, BM_VERT);
+
BM_ITER_MESH (eve, &iter, em->bm, BM_VERTS_OF_MESH) {
if (!BM_elem_flag_test(eve, BM_ELEM_HIDDEN)) {
const bool is_select = BM_elem_flag_test(eve, BM_ELEM_SELECT);
- const bool is_inside = EDBM_backbuf_check(index);
+ const bool is_inside = BLI_BITMAP_TEST_BOOL(select_bitmap, index);
const int sel_op_result = ED_select_op_action_deselected(sel_op, is_select, is_inside);
if (sel_op_result != -1) {
BM_vert_select_set(em->bm, eve, sel_op_result);
@@ -204,17 +282,23 @@ static bool edbm_backbuf_check_and_select_verts(BMEditMesh *em, const eSelectOp
return changed;
}
-static bool edbm_backbuf_check_and_select_edges(BMEditMesh *em, const eSelectOp sel_op)
+static bool edbm_backbuf_check_and_select_edges(struct EditSelectBuf_Cache *esel,
+ Object *ob,
+ BMEditMesh *em,
+ const eSelectOp sel_op)
{
BMEdge *eed;
BMIter iter;
- uint index = bm_solidoffs;
bool changed = false;
+ const BLI_bitmap *select_bitmap = esel->select_bitmap;
+ uint index = EDBM_select_id_context_offset_for_object_elem(
+ esel->sel_id_ctx, ob->runtime.select_id, BM_EDGE);
+
BM_ITER_MESH (eed, &iter, em->bm, BM_EDGES_OF_MESH) {
if (!BM_elem_flag_test(eed, BM_ELEM_HIDDEN)) {
const bool is_select = BM_elem_flag_test(eed, BM_ELEM_SELECT);
- const bool is_inside = EDBM_backbuf_check(index);
+ const bool is_inside = BLI_BITMAP_TEST_BOOL(select_bitmap, index);
const int sel_op_result = ED_select_op_action_deselected(sel_op, is_select, is_inside);
if (sel_op_result != -1) {
BM_edge_select_set(em->bm, eed, sel_op_result);
@@ -226,17 +310,23 @@ static bool edbm_backbuf_check_and_select_edges(BMEditMesh *em, const eSelectOp
return changed;
}
-static bool edbm_backbuf_check_and_select_faces(BMEditMesh *em, const eSelectOp sel_op)
+static bool edbm_backbuf_check_and_select_faces(struct EditSelectBuf_Cache *esel,
+ Object *ob,
+ BMEditMesh *em,
+ const eSelectOp sel_op)
{
BMFace *efa;
BMIter iter;
- uint index = 1;
bool changed = false;
+ const BLI_bitmap *select_bitmap = esel->select_bitmap;
+ uint index = EDBM_select_id_context_offset_for_object_elem(
+ esel->sel_id_ctx, ob->runtime.select_id, BM_FACE);
+
BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) {
if (!BM_elem_flag_test(efa, BM_ELEM_HIDDEN)) {
const bool is_select = BM_elem_flag_test(efa, BM_ELEM_SELECT);
- const bool is_inside = EDBM_backbuf_check(index);
+ const bool is_inside = BLI_BITMAP_TEST_BOOL(select_bitmap, index);
const int sel_op_result = ED_select_op_action_deselected(sel_op, is_select, is_inside);
if (sel_op_result != -1) {
BM_face_select_set(em->bm, efa, sel_op_result);
@@ -249,17 +339,21 @@ static bool edbm_backbuf_check_and_select_faces(BMEditMesh *em, const eSelectOp
}
/* object mode, edbm_ prefix is confusing here, rename? */
-static bool edbm_backbuf_check_and_select_verts_obmode(Mesh *me, const eSelectOp sel_op)
+static bool edbm_backbuf_check_and_select_verts_obmode(Mesh *me,
+ struct EditSelectBuf_Cache *esel,
+ const eSelectOp sel_op)
{
MVert *mv = me->mvert;
uint index;
bool changed = false;
+ const BLI_bitmap *select_bitmap = esel->select_bitmap;
+
if (mv) {
- for (index = 1; index <= me->totvert; index++, mv++) {
+ for (index = 0; index < me->totvert; index++, mv++) {
if (!(mv->flag & ME_HIDE)) {
const bool is_select = mv->flag & SELECT;
- const bool is_inside = EDBM_backbuf_check(index);
+ const bool is_inside = BLI_BITMAP_TEST_BOOL(select_bitmap, index);
const int sel_op_result = ED_select_op_action_deselected(sel_op, is_select, is_inside);
if (sel_op_result != -1) {
SET_FLAG_FROM_TEST(mv->flag, sel_op_result, SELECT);
@@ -272,17 +366,21 @@ static bool edbm_backbuf_check_and_select_verts_obmode(Mesh *me, const eSelectOp
}
/* object mode, edbm_ prefix is confusing here, rename? */
-static bool edbm_backbuf_check_and_select_tfaces(Mesh *me, const eSelectOp sel_op)
+static bool edbm_backbuf_check_and_select_faces_obmode(Mesh *me,
+ struct EditSelectBuf_Cache *esel,
+ const eSelectOp sel_op)
{
MPoly *mpoly = me->mpoly;
uint index;
bool changed = false;
+ const BLI_bitmap *select_bitmap = esel->select_bitmap;
+
if (mpoly) {
- for (index = 1; index <= me->totpoly; index++, mpoly++) {
+ for (index = 0; index < me->totpoly; index++, mpoly++) {
if (!(mpoly->flag & ME_HIDE)) {
const bool is_select = mpoly->flag & ME_FACE_SEL;
- const bool is_inside = EDBM_backbuf_check(index);
+ const bool is_inside = BLI_BITMAP_TEST_BOOL(select_bitmap, index);
const int sel_op_result = ED_select_op_action_deselected(sel_op, is_select, is_inside);
if (sel_op_result != -1) {
SET_FLAG_FROM_TEST(mpoly->flag, sel_op_result, ME_FACE_SEL);
@@ -621,14 +719,26 @@ static void do_lasso_select_mesh__doSelectVert(void *userData,
data->is_changed = true;
}
}
-static void do_lasso_select_mesh__doSelectEdge_pass0(
- void *userData, BMEdge *eed, const float screen_co_a[2], const float screen_co_b[2], int index)
-{
- LassoSelectUserData *data = userData;
+struct LassoSelectUserData_ForMeshEdge {
+ LassoSelectUserData *data;
+ struct EditSelectBuf_Cache *esel;
+ uint backbuf_offset;
+};
+static void do_lasso_select_mesh__doSelectEdge_pass0(void *user_data,
+ BMEdge *eed,
+ const float screen_co_a[2],
+ const float screen_co_b[2],
+ int index)
+{
+ struct LassoSelectUserData_ForMeshEdge *data_for_edge = user_data;
+ LassoSelectUserData *data = data_for_edge->data;
+ const bool is_visible = (data_for_edge->esel ?
+ BLI_BITMAP_TEST_BOOL(data_for_edge->esel->select_bitmap,
+ data_for_edge->backbuf_offset + index) :
+ true);
const bool is_select = BM_elem_flag_test(eed, BM_ELEM_SELECT);
const bool is_inside =
- (EDBM_backbuf_check(bm_solidoffs + index) &&
- edge_fully_inside_rect(data->rect_fl, screen_co_a, screen_co_b) &&
+ (is_visible && edge_fully_inside_rect(data->rect_fl, screen_co_a, screen_co_b) &&
BLI_lasso_is_point_inside(data->mcords, data->moves, UNPACK2(screen_co_a), IS_CLIPPED) &&
BLI_lasso_is_point_inside(data->mcords, data->moves, UNPACK2(screen_co_b), IS_CLIPPED));
const int sel_op_result = ED_select_op_action_deselected(data->sel_op, is_select, is_inside);
@@ -638,15 +748,24 @@ static void do_lasso_select_mesh__doSelectEdge_pass0(
data->is_changed = true;
}
}
-static void do_lasso_select_mesh__doSelectEdge_pass1(
- void *userData, BMEdge *eed, const float screen_co_a[2], const float screen_co_b[2], int index)
+static void do_lasso_select_mesh__doSelectEdge_pass1(void *user_data,
+ BMEdge *eed,
+ const float screen_co_a[2],
+ const float screen_co_b[2],
+ int index)
{
- LassoSelectUserData *data = userData;
+ struct LassoSelectUserData_ForMeshEdge *data_for_edge = user_data;
+ LassoSelectUserData *data = data_for_edge->data;
+ const bool is_visible = (data_for_edge->esel ?
+ BLI_BITMAP_TEST_BOOL(data_for_edge->esel->select_bitmap,
+ data_for_edge->backbuf_offset + index) :
+ true);
const bool is_select = BM_elem_flag_test(eed, BM_ELEM_SELECT);
- const bool is_inside =
- (EDBM_backbuf_check(bm_solidoffs + index) &&
- BLI_lasso_is_edge_inside(
- data->mcords, data->moves, UNPACK2(screen_co_a), UNPACK2(screen_co_b), IS_CLIPPED));
+ const bool is_inside = (is_visible && BLI_lasso_is_edge_inside(data->mcords,
+ data->moves,
+ UNPACK2(screen_co_a),
+ UNPACK2(screen_co_b),
+ IS_CLIPPED));
const int sel_op_result = ED_select_op_action_deselected(data->sel_op, is_select, is_inside);
if (sel_op_result != -1) {
BM_edge_select_set(data->vc->em->bm, eed, sel_op_result);
@@ -672,6 +791,7 @@ static void do_lasso_select_mesh__doSelectFace(void *userData,
}
static bool do_lasso_select_mesh(ViewContext *vc,
+ wmGenericUserData *wm_userdata,
const int mcords[][2],
short moves,
const eSelectOp sel_op)
@@ -679,7 +799,6 @@ static bool do_lasso_select_mesh(ViewContext *vc,
LassoSelectUserData data;
ToolSettings *ts = vc->scene->toolsettings;
rcti rect;
- int bbsel;
/* set editmesh */
vc->em = BKE_editmesh_from_object(vc->obedit);
@@ -699,12 +818,22 @@ static bool do_lasso_select_mesh(ViewContext *vc,
ED_view3d_init_mats_rv3d(vc->obedit, vc->rv3d);
GPU_matrix_set(vc->rv3d->viewmat);
- bbsel = EDBM_backbuf_border_mask_init(
- vc, mcords, moves, rect.xmin, rect.ymin, rect.xmax, rect.ymax);
+
+ const bool use_zbuf = !XRAY_FLAG_ENABLED(vc->v3d);
+
+ struct EditSelectBuf_Cache *esel = wm_userdata->data;
+ if (use_zbuf) {
+ if (wm_userdata->data == NULL) {
+ editselect_buf_cache_init_with_generic_userdata(wm_userdata, vc);
+ esel = wm_userdata->data;
+ const uint buffer_len = EDBM_select_id_context_elem_len(esel->sel_id_ctx);
+ esel->select_bitmap = ED_select_buffer_bitmap_from_poly(buffer_len, mcords, moves, &rect);
+ }
+ }
if (ts->selectmode & SCE_SELECT_VERTEX) {
- if (bbsel) {
- data.is_changed |= edbm_backbuf_check_and_select_verts(vc->em, sel_op);
+ if (use_zbuf) {
+ data.is_changed |= edbm_backbuf_check_and_select_verts(esel, vc->obedit, vc->em, sel_op);
}
else {
mesh_foreachScreenVert(
@@ -712,18 +841,26 @@ static bool do_lasso_select_mesh(ViewContext *vc,
}
}
if (ts->selectmode & SCE_SELECT_EDGE) {
- /* Does both bbsel and non-bbsel versions (need screen cos for both) */
+ /* Does both use_zbuf and non-use_zbuf versions (need screen cos for both) */
+ struct LassoSelectUserData_ForMeshEdge data_for_edge = {
+ .data = &data,
+ .esel = use_zbuf ? esel : NULL,
+ .backbuf_offset = use_zbuf ?
+ EDBM_select_id_context_offset_for_object_elem(
+ esel->sel_id_ctx, vc->obedit->runtime.select_id, BM_EDGE) :
+ 0,
+ };
mesh_foreachScreenEdge(
- vc, do_lasso_select_mesh__doSelectEdge_pass0, &data, V3D_PROJ_TEST_CLIP_NEAR);
+ vc, do_lasso_select_mesh__doSelectEdge_pass0, &data_for_edge, V3D_PROJ_TEST_CLIP_NEAR);
if (data.is_done == false) {
mesh_foreachScreenEdge(
- vc, do_lasso_select_mesh__doSelectEdge_pass1, &data, V3D_PROJ_TEST_CLIP_NEAR);
+ vc, do_lasso_select_mesh__doSelectEdge_pass1, &data_for_edge, V3D_PROJ_TEST_CLIP_NEAR);
}
}
if (ts->selectmode & SCE_SELECT_FACE) {
- if (bbsel) {
- data.is_changed |= edbm_backbuf_check_and_select_faces(vc->em, sel_op);
+ if (use_zbuf) {
+ data.is_changed |= edbm_backbuf_check_and_select_faces(esel, vc->obedit, vc->em, sel_op);
}
else {
mesh_foreachScreenFace(
@@ -731,8 +868,6 @@ static bool do_lasso_select_mesh(ViewContext *vc,
}
}
- EDBM_backbuf_free();
-
if (data.is_changed) {
EDBM_selectmode_flush(vc->em);
}
@@ -973,6 +1108,7 @@ static void do_lasso_select_meshobject__doSelectVert(void *userData,
}
}
static bool do_lasso_select_paintvert(ViewContext *vc,
+ wmGenericUserData *wm_userdata,
const int mcords[][2],
short moves,
const eSelectOp sel_op)
@@ -994,14 +1130,20 @@ static bool do_lasso_select_paintvert(ViewContext *vc,
BLI_lasso_boundbox(&rect, mcords, moves);
+ struct EditSelectBuf_Cache *esel = wm_userdata->data;
if (use_zbuf) {
- bm_vertoffs = me->totvert + 1; /* max index array */
-
- EDBM_backbuf_border_mask_init(vc, mcords, moves, rect.xmin, rect.ymin, rect.xmax, rect.ymax);
-
- changed |= edbm_backbuf_check_and_select_verts_obmode(me, sel_op);
+ if (wm_userdata->data == NULL) {
+ editselect_buf_cache_init_with_generic_userdata(wm_userdata, vc);
+ esel = wm_userdata->data;
+ const uint buffer_len = EDBM_select_id_context_elem_len(esel->sel_id_ctx);
+ esel->select_bitmap = ED_select_buffer_bitmap_from_poly(buffer_len, mcords, moves, &rect);
+ }
+ }
- EDBM_backbuf_free();
+ if (use_zbuf) {
+ if (esel->select_bitmap != NULL) {
+ changed |= edbm_backbuf_check_and_select_verts_obmode(me, esel, sel_op);
+ }
}
else {
LassoSelectUserData data;
@@ -1023,9 +1165,11 @@ static bool do_lasso_select_paintvert(ViewContext *vc,
paintvert_flush_flags(ob);
paintvert_tag_select_update(vc->C, ob);
}
+
return changed;
}
static bool do_lasso_select_paintface(ViewContext *vc,
+ wmGenericUserData *wm_userdata,
const int mcords[][2],
short moves,
const eSelectOp sel_op)
@@ -1038,19 +1182,25 @@ static bool do_lasso_select_paintface(ViewContext *vc,
return false;
}
- bm_vertoffs = me->totpoly + 1; /* max index array */
-
- BLI_lasso_boundbox(&rect, mcords, moves);
- EDBM_backbuf_border_mask_init(vc, mcords, moves, rect.xmin, rect.ymin, rect.xmax, rect.ymax);
-
bool changed = false;
if (SEL_OP_USE_PRE_DESELECT(sel_op)) {
/* flush selection at the end */
changed |= paintface_deselect_all_visible(vc->C, ob, SEL_DESELECT, false);
}
- changed |= edbm_backbuf_check_and_select_tfaces(me, sel_op);
- EDBM_backbuf_free();
+ BLI_lasso_boundbox(&rect, mcords, moves);
+
+ struct EditSelectBuf_Cache *esel = wm_userdata->data;
+ if (esel == NULL) {
+ editselect_buf_cache_init_with_generic_userdata(wm_userdata, vc);
+ esel = wm_userdata->data;
+ const uint buffer_len = EDBM_select_id_context_elem_len(esel->sel_id_ctx);
+ esel->select_bitmap = ED_select_buffer_bitmap_from_poly(buffer_len, mcords, moves, &rect);
+ }
+
+ if (esel->select_bitmap) {
+ changed |= edbm_backbuf_check_and_select_faces_obmode(me, esel, sel_op);
+ }
if (changed) {
paintface_flush_flags(vc->C, ob, SELECT);
@@ -1098,12 +1248,15 @@ static bool view3d_lasso_select(
Object *ob = CTX_data_active_object(C);
bool changed_multi = false;
+ wmGenericUserData wm_userdata_buf = {0};
+ wmGenericUserData *wm_userdata = &wm_userdata_buf;
+
if (vc->obedit == NULL) { /* Object Mode */
if (BKE_paint_select_face_test(ob)) {
- changed_multi |= do_lasso_select_paintface(vc, mcords, moves, sel_op);
+ changed_multi |= do_lasso_select_paintface(vc, wm_userdata, mcords, moves, sel_op);
}
else if (BKE_paint_select_vert_test(ob)) {
- changed_multi |= do_lasso_select_paintvert(vc, mcords, moves, sel_op);
+ changed_multi |= do_lasso_select_paintvert(vc, wm_userdata, mcords, moves, sel_op);
}
else if (ob &&
(ob->mode & (OB_MODE_VERTEX_PAINT | OB_MODE_WEIGHT_PAINT | OB_MODE_TEXTURE_PAINT))) {
@@ -1120,14 +1273,13 @@ static bool view3d_lasso_select(
}
}
else { /* Edit Mode */
-
FOREACH_OBJECT_IN_MODE_BEGIN (vc->view_layer, vc->v3d, ob->type, ob->mode, ob_iter) {
ED_view3d_viewcontext_init_object(vc, ob_iter);
bool changed = false;
switch (vc->obedit->type) {
case OB_MESH:
- changed = do_lasso_select_mesh(vc, mcords, moves, sel_op);
+ changed = do_lasso_select_mesh(vc, wm_userdata, mcords, moves, sel_op);
break;
case OB_CURVE:
case OB_SURF:
@@ -1155,6 +1307,9 @@ static bool view3d_lasso_select(
}
FOREACH_OBJECT_IN_MODE_END;
}
+
+ WM_generic_user_data_free(wm_userdata);
+
return changed_multi;
}
@@ -2336,9 +2491,13 @@ static void do_paintvert_box_select__doSelectVert(void *userData,
data->is_changed = true;
}
}
-static bool do_paintvert_box_select(ViewContext *vc, const rcti *rect, const eSelectOp sel_op)
+static bool do_paintvert_box_select(ViewContext *vc,
+ wmGenericUserData *wm_userdata,
+ const rcti *rect,
+ const eSelectOp sel_op)
{
const bool use_zbuf = !XRAY_ENABLED(vc->v3d);
+
Mesh *me;
me = vc->obact->data;
@@ -2355,48 +2514,16 @@ static bool do_paintvert_box_select(ViewContext *vc, const rcti *rect, const eSe
/* pass */
}
else if (use_zbuf) {
- MVert *mvert;
- uint *rt, *buf, buf_len;
- int a, index;
- char *selar;
-
- selar = MEM_callocN(me->totvert + 1, "selar");
-
- ED_view3d_select_id_validate(vc);
- buf = ED_view3d_select_id_read_rect(vc, rect, &buf_len);
-
- rt = buf;
-
- a = buf_len;
- while (a--) {
- if (*rt) {
- index = *rt;
- if (index <= me->totvert) {
- selar[index] = 1;
- }
- }
- rt++;
+ struct EditSelectBuf_Cache *esel = wm_userdata->data;
+ if (wm_userdata->data == NULL) {
+ editselect_buf_cache_init_with_generic_userdata(wm_userdata, vc);
+ esel = wm_userdata->data;
+ const uint buffer_len = EDBM_select_id_context_elem_len(esel->sel_id_ctx);
+ esel->select_bitmap = ED_select_buffer_bitmap_from_rect(buffer_len, rect);
}
-
- mvert = me->mvert;
- for (a = 1; a <= me->totvert; a++, mvert++) {
- if ((mvert->flag & ME_HIDE) == 0) {
- const bool is_select = mvert->flag & SELECT;
- const bool is_inside = (selar[a] != 0);
- const int sel_op_result = ED_select_op_action_deselected(sel_op, is_select, is_inside);
- if (sel_op_result != -1) {
- SET_FLAG_FROM_TEST(mvert->flag, sel_op_result, SELECT);
- changed = true;
- }
- }
+ if (esel->select_bitmap != NULL) {
+ changed |= edbm_backbuf_check_and_select_verts_obmode(me, esel, sel_op);
}
-
- MEM_freeN(buf);
- MEM_freeN(selar);
-
-#ifdef __APPLE__
- glReadBuffer(GL_BACK);
-#endif
}
else {
BoxSelectUserData data;
@@ -2420,6 +2547,46 @@ static bool do_paintvert_box_select(ViewContext *vc, const rcti *rect, const eSe
return changed;
}
+static bool do_paintface_box_select(ViewContext *vc,
+ wmGenericUserData *wm_userdata,
+ const rcti *rect,
+ int sel_op)
+{
+ Object *ob = vc->obact;
+ Mesh *me;
+
+ me = BKE_mesh_from_object(ob);
+ if ((me == NULL) || (me->totpoly == 0)) {
+ return false;
+ }
+
+ bool changed = false;
+ if (SEL_OP_USE_PRE_DESELECT(sel_op)) {
+ changed |= paintface_deselect_all_visible(vc->C, vc->obact, SEL_DESELECT, false);
+ }
+
+ if (BLI_rcti_is_empty(rect)) {
+ /* pass */
+ }
+ else {
+ struct EditSelectBuf_Cache *esel = wm_userdata->data;
+ if (wm_userdata->data == NULL) {
+ editselect_buf_cache_init_with_generic_userdata(wm_userdata, vc);
+ esel = wm_userdata->data;
+ const uint buffer_len = EDBM_select_id_context_elem_len(esel->sel_id_ctx);
+ esel->select_bitmap = ED_select_buffer_bitmap_from_rect(buffer_len, rect);
+ }
+ if (esel->select_bitmap != NULL) {
+ changed |= edbm_backbuf_check_and_select_faces_obmode(me, esel, sel_op);
+ }
+ }
+
+ if (changed) {
+ paintface_flush_flags(vc->C, vc->obact, SELECT);
+ }
+ return changed;
+}
+
static void do_nurbs_box_select__doSelect(void *userData,
Nurb *UNUSED(nu),
BPoint *bp,
@@ -2520,12 +2687,22 @@ static void do_mesh_box_select__doSelectVert(void *userData,
data->is_changed = true;
}
}
+struct BoxSelectUserData_ForMeshEdge {
+ BoxSelectUserData *data;
+ struct EditSelectBuf_Cache *esel;
+ uint backbuf_offset;
+};
static void do_mesh_box_select__doSelectEdge_pass0(
void *userData, BMEdge *eed, const float screen_co_a[2], const float screen_co_b[2], int index)
{
- BoxSelectUserData *data = userData;
+ struct BoxSelectUserData_ForMeshEdge *data_for_edge = userData;
+ BoxSelectUserData *data = data_for_edge->data;
+ const bool is_visible = (data_for_edge->esel ?
+ BLI_BITMAP_TEST_BOOL(data_for_edge->esel->select_bitmap,
+ data_for_edge->backbuf_offset + index) :
+ true);
const bool is_select = BM_elem_flag_test(eed, BM_ELEM_SELECT);
- const bool is_inside = (EDBM_backbuf_check(bm_solidoffs + index) &&
+ const bool is_inside = (is_visible &&
edge_fully_inside_rect(data->rect_fl, screen_co_a, screen_co_b));
const int sel_op_result = ED_select_op_action_deselected(data->sel_op, is_select, is_inside);
if (sel_op_result != -1) {
@@ -2537,10 +2714,14 @@ static void do_mesh_box_select__doSelectEdge_pass0(
static void do_mesh_box_select__doSelectEdge_pass1(
void *userData, BMEdge *eed, const float screen_co_a[2], const float screen_co_b[2], int index)
{
- BoxSelectUserData *data = userData;
+ struct BoxSelectUserData_ForMeshEdge *data_for_edge = userData;
+ BoxSelectUserData *data = data_for_edge->data;
+ const bool is_visible = (data_for_edge->esel ?
+ BLI_BITMAP_TEST_BOOL(data_for_edge->esel->select_bitmap,
+ data_for_edge->backbuf_offset + index) :
+ true);
const bool is_select = BM_elem_flag_test(eed, BM_ELEM_SELECT);
- const bool is_inside = (EDBM_backbuf_check(bm_solidoffs + index) &&
- edge_inside_rect(data->rect_fl, screen_co_a, screen_co_b));
+ const bool is_inside = (is_visible && edge_inside_rect(data->rect_fl, screen_co_a, screen_co_b));
const int sel_op_result = ED_select_op_action_deselected(data->sel_op, is_select, is_inside);
if (sel_op_result != -1) {
BM_edge_select_set(data->vc->em->bm, eed, sel_op_result);
@@ -2561,11 +2742,13 @@ static void do_mesh_box_select__doSelectFace(void *userData,
data->is_changed = true;
}
}
-static bool do_mesh_box_select(ViewContext *vc, rcti *rect, const eSelectOp sel_op)
+static bool do_mesh_box_select(ViewContext *vc,
+ wmGenericUserData *wm_userdata,
+ const rcti *rect,
+ const eSelectOp sel_op)
{
BoxSelectUserData data;
ToolSettings *ts = vc->scene->toolsettings;
- int bbsel;
view3d_userdata_boxselect_init(&data, vc, rect, sel_op);
@@ -2580,11 +2763,22 @@ static bool do_mesh_box_select(ViewContext *vc, rcti *rect, const eSelectOp sel_
ED_view3d_init_mats_rv3d(vc->obedit, vc->rv3d);
GPU_matrix_set(vc->rv3d->viewmat);
- bbsel = EDBM_backbuf_border_init(vc, rect->xmin, rect->ymin, rect->xmax, rect->ymax);
+
+ const bool use_zbuf = !XRAY_FLAG_ENABLED(vc->v3d);
+
+ struct EditSelectBuf_Cache *esel = wm_userdata->data;
+ if (use_zbuf) {
+ if (wm_userdata->data == NULL) {
+ editselect_buf_cache_init_with_generic_userdata(wm_userdata, vc);
+ esel = wm_userdata->data;
+ const uint buffer_len = EDBM_select_id_context_elem_len(esel->sel_id_ctx);
+ esel->select_bitmap = ED_select_buffer_bitmap_from_rect(buffer_len, rect);
+ }
+ }
if (ts->selectmode & SCE_SELECT_VERTEX) {
- if (bbsel) {
- data.is_changed |= edbm_backbuf_check_and_select_verts(vc->em, sel_op);
+ if (use_zbuf) {
+ data.is_changed |= edbm_backbuf_check_and_select_verts(esel, vc->obedit, vc->em, sel_op);
}
else {
mesh_foreachScreenVert(
@@ -2592,18 +2786,26 @@ static bool do_mesh_box_select(ViewContext *vc, rcti *rect, const eSelectOp sel_
}
}
if (ts->selectmode & SCE_SELECT_EDGE) {
- /* Does both bbsel and non-bbsel versions (need screen cos for both) */
+ /* Does both use_zbuf and non-use_zbuf versions (need screen cos for both) */
+ struct BoxSelectUserData_ForMeshEdge cb_data = {
+ .data = &data,
+ .esel = use_zbuf ? esel : NULL,
+ .backbuf_offset = use_zbuf ?
+ EDBM_select_id_context_offset_for_object_elem(
+ esel->sel_id_ctx, vc->obedit->runtime.select_id, BM_EDGE) :
+ 0,
+ };
mesh_foreachScreenEdge(
- vc, do_mesh_box_select__doSelectEdge_pass0, &data, V3D_PROJ_TEST_CLIP_NEAR);
+ vc, do_mesh_box_select__doSelectEdge_pass0, &cb_data, V3D_PROJ_TEST_CLIP_NEAR);
if (data.is_done == false) {
mesh_foreachScreenEdge(
- vc, do_mesh_box_select__doSelectEdge_pass1, &data, V3D_PROJ_TEST_CLIP_NEAR);
+ vc, do_mesh_box_select__doSelectEdge_pass1, &cb_data, V3D_PROJ_TEST_CLIP_NEAR);
}
}
if (ts->selectmode & SCE_SELECT_FACE) {
- if (bbsel) {
- data.is_changed |= edbm_backbuf_check_and_select_faces(vc->em, sel_op);
+ if (use_zbuf) {
+ data.is_changed |= edbm_backbuf_check_and_select_faces(esel, vc->obedit, vc->em, sel_op);
}
else {
mesh_foreachScreenFace(
@@ -2611,8 +2813,6 @@ static bool do_mesh_box_select(ViewContext *vc, rcti *rect, const eSelectOp sel_
}
}
- EDBM_backbuf_free();
-
if (data.is_changed) {
EDBM_selectmode_flush(vc->em);
}
@@ -2930,6 +3130,9 @@ static int view3d_box_select_exec(bContext *C, wmOperator *op)
rcti rect;
bool changed_multi = false;
+ wmGenericUserData wm_userdata_buf = {0};
+ wmGenericUserData *wm_userdata = &wm_userdata_buf;
+
view3d_operator_needs_opengl(C);
BKE_object_update_select_id(CTX_data_main(C));
@@ -2940,7 +3143,6 @@ static int view3d_box_select_exec(bContext *C, wmOperator *op)
WM_operator_properties_border_to_rcti(op, &rect);
if (vc.obedit) {
-
FOREACH_OBJECT_IN_MODE_BEGIN (
vc.view_layer, vc.v3d, vc.obedit->type, vc.obedit->mode, ob_iter) {
ED_view3d_viewcontext_init_object(&vc, ob_iter);
@@ -2949,7 +3151,7 @@ static int view3d_box_select_exec(bContext *C, wmOperator *op)
switch (vc.obedit->type) {
case OB_MESH:
vc.em = BKE_editmesh_from_object(vc.obedit);
- changed = do_mesh_box_select(&vc, &rect, sel_op);
+ changed = do_mesh_box_select(&vc, wm_userdata, &rect, sel_op);
if (changed) {
DEG_id_tag_update(vc.obedit->data, ID_RECALC_SELECT);
WM_event_add_notifier(C, NC_GEOM | ND_SELECT, vc.obedit->data);
@@ -2999,10 +3201,10 @@ static int view3d_box_select_exec(bContext *C, wmOperator *op)
C, &vc, &rect, sel_op == SEL_OP_ADD ? true : false);
}
else if (vc.obact && BKE_paint_select_face_test(vc.obact)) {
- changed_multi = do_paintface_box_select(&vc, &rect, sel_op);
+ changed_multi = do_paintface_box_select(&vc, wm_userdata, &rect, sel_op);
}
else if (vc.obact && BKE_paint_select_vert_test(vc.obact)) {
- changed_multi = do_paintvert_box_select(&vc, &rect, sel_op);
+ changed_multi = do_paintvert_box_select(&vc, wm_userdata, &rect, sel_op);
}
else if (vc.obact && vc.obact->mode & OB_MODE_PARTICLE_EDIT) {
changed_multi = PE_box_select(C, &rect, sel_op);
@@ -3015,6 +3217,8 @@ static int view3d_box_select_exec(bContext *C, wmOperator *op)
}
}
+ WM_generic_user_data_free(wm_userdata);
+
if (changed_multi) {
return OPERATOR_FINISHED;
}
@@ -3120,10 +3324,13 @@ static void mesh_circle_doSelectFace(void *userData,
}
}
-static bool mesh_circle_select(ViewContext *vc, eSelectOp sel_op, const int mval[2], float rad)
+static bool mesh_circle_select(ViewContext *vc,
+ wmGenericUserData *wm_userdata,
+ eSelectOp sel_op,
+ const int mval[2],
+ float rad)
{
ToolSettings *ts = vc->scene->toolsettings;
- int bbsel;
CircleSelectUserData data;
vc->em = BKE_editmesh_from_object(vc->obedit);
@@ -3136,14 +3343,30 @@ static bool mesh_circle_select(ViewContext *vc, eSelectOp sel_op, const int mval
}
const bool select = (sel_op != SEL_OP_SUB);
- bbsel = EDBM_backbuf_circle_init(vc, mval[0], mval[1], (short)(rad + 1.0f));
ED_view3d_init_mats_rv3d(vc->obedit, vc->rv3d); /* for foreach's screen/vert projection */
view3d_userdata_circleselect_init(&data, vc, select, mval, rad);
+ const bool use_zbuf = !XRAY_FLAG_ENABLED(vc->v3d);
+
+ if (use_zbuf) {
+ if (wm_userdata->data == NULL) {
+ editselect_buf_cache_init_with_generic_userdata(wm_userdata, vc);
+ }
+ }
+ struct EditSelectBuf_Cache *esel = wm_userdata->data;
+
+ if (use_zbuf) {
+ const uint buffer_len = EDBM_select_id_context_elem_len(esel->sel_id_ctx);
+ esel->select_bitmap = ED_select_buffer_bitmap_from_circle(buffer_len, mval, (int)(rad + 1.0f));
+ }
+
if (ts->selectmode & SCE_SELECT_VERTEX) {
- if (bbsel) {
- changed |= edbm_backbuf_check_and_select_verts(vc->em, select ? SEL_OP_ADD : SEL_OP_SUB);
+ if (use_zbuf) {
+ if (esel->select_bitmap != NULL) {
+ changed |= edbm_backbuf_check_and_select_verts(
+ esel, vc->obedit, vc->em, select ? SEL_OP_ADD : SEL_OP_SUB);
+ }
}
else {
mesh_foreachScreenVert(vc, mesh_circle_doSelectVert, &data, V3D_PROJ_TEST_CLIP_DEFAULT);
@@ -3151,8 +3374,11 @@ static bool mesh_circle_select(ViewContext *vc, eSelectOp sel_op, const int mval
}
if (ts->selectmode & SCE_SELECT_EDGE) {
- if (bbsel) {
- changed |= edbm_backbuf_check_and_select_edges(vc->em, select ? SEL_OP_ADD : SEL_OP_SUB);
+ if (use_zbuf) {
+ if (esel->select_bitmap != NULL) {
+ changed |= edbm_backbuf_check_and_select_edges(
+ esel, vc->obedit, vc->em, select ? SEL_OP_ADD : SEL_OP_SUB);
+ }
}
else {
mesh_foreachScreenEdge(vc, mesh_circle_doSelectEdge, &data, V3D_PROJ_TEST_CLIP_NEAR);
@@ -3160,17 +3386,25 @@ static bool mesh_circle_select(ViewContext *vc, eSelectOp sel_op, const int mval
}
if (ts->selectmode & SCE_SELECT_FACE) {
- if (bbsel) {
- changed |= edbm_backbuf_check_and_select_faces(vc->em, select ? SEL_OP_ADD : SEL_OP_SUB);
+ if (use_zbuf) {
+ if (esel->select_bitmap != NULL) {
+ changed |= edbm_backbuf_check_and_select_faces(
+ esel, vc->obedit, vc->em, select ? SEL_OP_ADD : SEL_OP_SUB);
+ }
}
else {
mesh_foreachScreenFace(vc, mesh_circle_doSelectFace, &data, V3D_PROJ_TEST_CLIP_DEFAULT);
}
}
- changed |= data.is_changed;
+ if (use_zbuf) {
+ if (esel->select_bitmap != NULL) {
+ MEM_freeN(esel->select_bitmap);
+ esel->select_bitmap = NULL;
+ }
+ }
- EDBM_backbuf_free();
+ changed |= data.is_changed;
if (changed) {
EDBM_selectmode_flush(vc->em);
@@ -3179,6 +3413,7 @@ static bool mesh_circle_select(ViewContext *vc, eSelectOp sel_op, const int mval
}
static bool paint_facesel_circle_select(ViewContext *vc,
+ wmGenericUserData *wm_userdata,
const eSelectOp sel_op,
const int mval[2],
float rad)
@@ -3186,7 +3421,6 @@ static bool paint_facesel_circle_select(ViewContext *vc,
BLI_assert(ELEM(sel_op, SEL_OP_SET, SEL_OP_ADD, SEL_OP_SUB));
Object *ob = vc->obact;
Mesh *me = ob->data;
- bool bbsel;
bool changed = false;
if (SEL_OP_USE_PRE_DESELECT(sel_op)) {
@@ -3194,13 +3428,21 @@ static bool paint_facesel_circle_select(ViewContext *vc,
changed |= paintface_deselect_all_visible(vc->C, ob, SEL_DESELECT, false);
}
- bm_vertoffs = me->totpoly + 1; /* max index array */
+ if (wm_userdata->data == NULL) {
+ editselect_buf_cache_init_with_generic_userdata(wm_userdata, vc);
+ }
- bbsel = EDBM_backbuf_circle_init(vc, mval[0], mval[1], (short)(rad + 1.0f));
- if (bbsel) {
- changed |= edbm_backbuf_check_and_select_tfaces(me, sel_op);
- EDBM_backbuf_free();
+ {
+ struct EditSelectBuf_Cache *esel = wm_userdata->data;
+ const uint buffer_len = EDBM_select_id_context_elem_len(esel->sel_id_ctx);
+ esel->select_bitmap = ED_select_buffer_bitmap_from_circle(buffer_len, mval, (int)(rad + 1.0f));
+ if (esel->select_bitmap != NULL) {
+ changed |= edbm_backbuf_check_and_select_faces_obmode(me, esel, sel_op);
+ MEM_freeN(esel->select_bitmap);
+ esel->select_bitmap = NULL;
+ }
}
+
if (changed) {
paintface_flush_flags(vc->C, ob, SELECT);
}
@@ -3220,6 +3462,7 @@ static void paint_vertsel_circle_select_doSelectVert(void *userData,
}
}
static bool paint_vertsel_circle_select(ViewContext *vc,
+ wmGenericUserData *wm_userdata,
const eSelectOp sel_op,
const int mval[2],
float rad)
@@ -3228,7 +3471,6 @@ static bool paint_vertsel_circle_select(ViewContext *vc,
const bool use_zbuf = !XRAY_ENABLED(vc->v3d);
Object *ob = vc->obact;
Mesh *me = ob->data;
- bool bbsel;
/* CircleSelectUserData data = {NULL}; */ /* UNUSED */
bool changed = false;
@@ -3240,12 +3482,19 @@ static bool paint_vertsel_circle_select(ViewContext *vc,
const bool select = (sel_op != SEL_OP_SUB);
if (use_zbuf) {
- bm_vertoffs = me->totvert + 1; /* max index array */
+ if (wm_userdata->data == NULL) {
+ editselect_buf_cache_init_with_generic_userdata(wm_userdata, vc);
+ }
+ }
- bbsel = EDBM_backbuf_circle_init(vc, mval[0], mval[1], (short)(rad + 1.0f));
- if (bbsel) {
- changed |= edbm_backbuf_check_and_select_verts_obmode(me, sel_op);
- EDBM_backbuf_free();
+ if (use_zbuf) {
+ struct EditSelectBuf_Cache *esel = wm_userdata->data;
+ const uint buffer_len = EDBM_select_id_context_elem_len(esel->sel_id_ctx);
+ esel->select_bitmap = ED_select_buffer_bitmap_from_circle(buffer_len, mval, (int)(rad + 1.0f));
+ if (esel->select_bitmap != NULL) {
+ changed |= edbm_backbuf_check_and_select_verts_obmode(me, esel, sel_op);
+ MEM_freeN(esel->select_bitmap);
+ esel->select_bitmap = NULL;
}
}
else {
@@ -3593,27 +3842,40 @@ static bool mball_circle_select(ViewContext *vc,
/** Callbacks for circle selection in Editmode */
static bool obedit_circle_select(ViewContext *vc,
+ wmGenericUserData *wm_userdata,
const eSelectOp sel_op,
const int mval[2],
float rad)
{
+ bool changed = false;
BLI_assert(ELEM(sel_op, SEL_OP_SET, SEL_OP_ADD, SEL_OP_SUB));
switch (vc->obedit->type) {
case OB_MESH:
- return mesh_circle_select(vc, sel_op, mval, rad);
+ changed = mesh_circle_select(vc, wm_userdata, sel_op, mval, rad);
+ break;
case OB_CURVE:
case OB_SURF:
- return nurbscurve_circle_select(vc, sel_op, mval, rad);
+ changed = nurbscurve_circle_select(vc, sel_op, mval, rad);
+ break;
case OB_LATTICE:
- return lattice_circle_select(vc, sel_op, mval, rad);
+ changed = lattice_circle_select(vc, sel_op, mval, rad);
+ break;
case OB_ARMATURE:
- return armature_circle_select(vc, sel_op, mval, rad);
+ changed = armature_circle_select(vc, sel_op, mval, rad);
+ break;
case OB_MBALL:
- return mball_circle_select(vc, sel_op, mval, rad);
+ changed = mball_circle_select(vc, sel_op, mval, rad);
+ break;
default:
BLI_assert(0);
- return false;
+ break;
}
+
+ if (changed) {
+ DEG_id_tag_update(vc->obact->data, ID_RECALC_SELECT);
+ WM_main_add_notifier(NC_GEOM | ND_SELECT, vc->obact->data);
+ }
+ return changed;
}
static bool object_circle_select(ViewContext *vc,
@@ -3662,8 +3924,13 @@ static int view3d_circle_select_exec(bContext *C, wmOperator *op)
const int radius = RNA_int_get(op->ptr, "radius");
const int mval[2] = {RNA_int_get(op->ptr, "x"), RNA_int_get(op->ptr, "y")};
+ /* Allow each selection type to allocate their own data thats used between executions. */
+ wmGesture *gesture = op->customdata; /* NULL when non-modal. */
+ wmGenericUserData wm_userdata_buf = {0};
+ wmGenericUserData *wm_userdata = gesture ? &gesture->user_data : &wm_userdata_buf;
+
const eSelectOp sel_op = ED_select_op_modal(RNA_enum_get(op->ptr, "mode"),
- WM_gesture_is_modal_first(op->customdata));
+ WM_gesture_is_modal_first(gesture));
ED_view3d_viewcontext_init(C, &vc);
@@ -3672,7 +3939,9 @@ static int view3d_circle_select_exec(bContext *C, wmOperator *op)
if (obedit || BKE_paint_select_elem_test(obact) || (obact && (obact->mode & OB_MODE_POSE))) {
view3d_operator_needs_opengl(C);
- BKE_object_update_select_id(CTX_data_main(C));
+ if (obedit == NULL) {
+ BKE_object_update_select_id(CTX_data_main(C));
+ }
FOREACH_OBJECT_IN_MODE_BEGIN (vc.view_layer, vc.v3d, obact->type, obact->mode, ob_iter) {
ED_view3d_viewcontext_init_object(&vc, ob_iter);
@@ -3681,16 +3950,13 @@ static int view3d_circle_select_exec(bContext *C, wmOperator *op)
obedit = vc.obedit;
if (obedit) {
- if (obedit_circle_select(&vc, sel_op, mval, (float)radius)) {
- DEG_id_tag_update(obact->data, ID_RECALC_SELECT);
- WM_event_add_notifier(C, NC_GEOM | ND_SELECT, obact->data);
- }
+ obedit_circle_select(&vc, wm_userdata, sel_op, mval, (float)radius);
}
else if (BKE_paint_select_face_test(obact)) {
- paint_facesel_circle_select(&vc, sel_op, mval, (float)radius);
+ paint_facesel_circle_select(&vc, wm_userdata, sel_op, mval, (float)radius);
}
else if (BKE_paint_select_vert_test(obact)) {
- paint_vertsel_circle_select(&vc, sel_op, mval, (float)radius);
+ paint_vertsel_circle_select(&vc, wm_userdata, sel_op, mval, (float)radius);
}
else if (obact->mode & OB_MODE_POSE) {
pose_circle_select(&vc, sel_op, mval, (float)radius);
@@ -3717,6 +3983,11 @@ static int view3d_circle_select_exec(bContext *C, wmOperator *op)
}
}
+ /* Otherwise this is freed by the gesture. */
+ if (wm_userdata == &wm_userdata_buf) {
+ WM_generic_user_data_free(wm_userdata);
+ }
+
return OPERATOR_FINISHED;
}
diff --git a/source/blender/editors/space_view3d/view3d_view.c b/source/blender/editors/space_view3d/view3d_view.c
index 2454358b687..5865efa0ffa 100644
--- a/source/blender/editors/space_view3d/view3d_view.c
+++ b/source/blender/editors/space_view3d/view3d_view.c
@@ -428,7 +428,7 @@ void ED_view3d_smooth_view_force_finish(bContext *C, View3D *v3d, ARegion *ar)
* can use them without redrawing first */
Depsgraph *depsgraph = CTX_data_depsgraph(C);
Scene *scene = CTX_data_scene(C);
- ED_view3d_update_viewmat(depsgraph, scene, v3d, ar, NULL, NULL, NULL);
+ ED_view3d_update_viewmat(depsgraph, scene, v3d, ar, NULL, NULL, NULL, false);
}
}
diff --git a/source/blender/editors/transform/transform.c b/source/blender/editors/transform/transform.c
index 09f198ff14c..c3acd604ee1 100644
--- a/source/blender/editors/transform/transform.c
+++ b/source/blender/editors/transform/transform.c
@@ -4835,6 +4835,7 @@ static void initNormalRotation(TransInfo *t)
BMEditMesh *em = BKE_editmesh_from_object(tc->obedit);
BMesh *bm = em->bm;
+ BKE_editmesh_ensure_autosmooth(em);
BKE_editmesh_lnorspace_update(em);
storeCustomLNorValue(tc, bm);
diff --git a/source/blender/editors/transform/transform_generics.c b/source/blender/editors/transform/transform_generics.c
index 758551be0b5..6a9c6856a03 100644
--- a/source/blender/editors/transform/transform_generics.c
+++ b/source/blender/editors/transform/transform_generics.c
@@ -1177,12 +1177,7 @@ static void recalcData_sequencer(TransInfo *t)
Sequence *seq = tdsq->seq;
if (seq != seq_prev) {
- if (BKE_sequence_tx_fullupdate_test(seq)) {
- BKE_sequence_invalidate_cache(t->scene, seq);
- }
- else {
- BKE_sequence_invalidate_cache(t->scene, seq);
- }
+ BKE_sequence_invalidate_cache_composite(t->scene, seq);
}
seq_prev = seq;
diff --git a/source/blender/editors/transform/transform_gizmo_3d.c b/source/blender/editors/transform/transform_gizmo_3d.c
index e43379dc358..68885a72092 100644
--- a/source/blender/editors/transform/transform_gizmo_3d.c
+++ b/source/blender/editors/transform/transform_gizmo_3d.c
@@ -1661,7 +1661,12 @@ static void WIDGETGROUP_gizmo_setup(const bContext *C, wmGizmoGroup *gzgroup)
else if (tref && STREQ(tref->idname, "builtin.scale")) {
ggd->twtype |= V3D_GIZMO_SHOW_OBJECT_SCALE;
}
+ else if (tref && STREQ(tref->idname, "builtin.transform")) {
+ ggd->twtype = V3D_GIZMO_SHOW_OBJECT_TRANSLATE | V3D_GIZMO_SHOW_OBJECT_ROTATE |
+ V3D_GIZMO_SHOW_OBJECT_SCALE;
+ }
else {
+ /* This is also correct logic for 'builtin.transform', no special check needed. */
/* Setup all gizmos, they can be toggled via 'ToolSettings.gizmo_flag' */
ggd->twtype = V3D_GIZMO_SHOW_OBJECT_TRANSLATE | V3D_GIZMO_SHOW_OBJECT_ROTATE |
V3D_GIZMO_SHOW_OBJECT_SCALE;
@@ -1852,7 +1857,10 @@ static void WIDGETGROUP_gizmo_draw_prepare(const bContext *C, wmGizmoGroup *gzgr
}
}
-static void WIDGETGROUP_gizmo_invoke_prepare(const bContext *C, wmGizmoGroup *gzgroup, wmGizmo *gz)
+static void WIDGETGROUP_gizmo_invoke_prepare(const bContext *C,
+ wmGizmoGroup *gzgroup,
+ wmGizmo *gz,
+ const wmEvent *UNUSED(event))
{
GizmoGroup *ggd = gzgroup->customdata;
@@ -1971,12 +1979,12 @@ static bool WIDGETGROUP_gizmo_poll_tool(const struct bContext *C, struct wmGizmo
return true;
}
-/* Expose as multiple gizmos so tools use one, persistant context another.
+/* Expose as multiple gizmos so tools use one, persistent context another.
* Needed because they use different options which isn't so simple to dynamically update. */
void VIEW3D_GGT_xform_gizmo(wmGizmoGroupType *gzgt)
{
- gzgt->name = "Transform Gizmo";
+ gzgt->name = "3D View: Transform Gizmo";
gzgt->idname = "VIEW3D_GGT_xform_gizmo";
gzgt->flag = WM_GIZMOGROUPTYPE_3D;
@@ -1990,12 +1998,26 @@ void VIEW3D_GGT_xform_gizmo(wmGizmoGroupType *gzgt)
gzgt->message_subscribe = WIDGETGROUP_gizmo_message_subscribe;
gzgt->draw_prepare = WIDGETGROUP_gizmo_draw_prepare;
gzgt->invoke_prepare = WIDGETGROUP_gizmo_invoke_prepare;
+
+ static const EnumPropertyItem rna_enum_gizmo_items[] = {
+ {V3D_GIZMO_SHOW_OBJECT_TRANSLATE, "TRANSLATE", 0, "Move", ""},
+ {V3D_GIZMO_SHOW_OBJECT_ROTATE, "ROTATE", 0, "Rotate", ""},
+ {V3D_GIZMO_SHOW_OBJECT_SCALE, "SCALE", 0, "Scale", ""},
+ {0, "NONE", 0, "None", ""},
+ {0, NULL, 0, NULL, NULL},
+ };
+ RNA_def_enum(gzgt->srna,
+ "drag_action",
+ rna_enum_gizmo_items,
+ V3D_GIZMO_SHOW_OBJECT_TRANSLATE,
+ "Drag Action",
+ "");
}
/** Only poll, flag & gzmap_params differ. */
void VIEW3D_GGT_xform_gizmo_context(wmGizmoGroupType *gzgt)
{
- gzgt->name = "Transform Gizmo Context";
+ gzgt->name = "3D View: Transform Gizmo Context";
gzgt->idname = "VIEW3D_GGT_xform_gizmo_context";
gzgt->flag = WM_GIZMOGROUPTYPE_3D | WM_GIZMOGROUPTYPE_PERSISTENT;
diff --git a/source/blender/editors/transform/transform_gizmo_extrude_3d.c b/source/blender/editors/transform/transform_gizmo_extrude_3d.c
index 47a584561f9..24ef92b3153 100644
--- a/source/blender/editors/transform/transform_gizmo_extrude_3d.c
+++ b/source/blender/editors/transform/transform_gizmo_extrude_3d.c
@@ -385,7 +385,8 @@ static void gizmo_mesh_extrude_draw_prepare(const bContext *C, wmGizmoGroup *gzg
static void gizmo_mesh_extrude_invoke_prepare(const bContext *UNUSED(C),
wmGizmoGroup *gzgroup,
- wmGizmo *gz)
+ wmGizmo *gz,
+ const wmEvent *UNUSED(event))
{
GizmoExtrudeGroup *ggd = gzgroup->customdata;
if (ELEM(gz, ggd->adjust[0], ggd->adjust[1])) {
diff --git a/source/blender/editors/transform/transform_ops.c b/source/blender/editors/transform/transform_ops.c
index 8606cd19c96..f028f2dc506 100644
--- a/source/blender/editors/transform/transform_ops.c
+++ b/source/blender/editors/transform/transform_ops.c
@@ -1170,7 +1170,7 @@ static void TRANSFORM_OT_rotate_normal(struct wmOperatorType *ot)
ot->exec = transform_exec;
ot->modal = transform_modal;
ot->cancel = transform_cancel;
- ot->poll = ED_operator_editmesh_auto_smooth;
+ ot->poll = ED_operator_editmesh;
RNA_def_float_rotation(
ot->srna, "value", 0, NULL, -FLT_MAX, FLT_MAX, "Angle", "", -M_PI * 2, M_PI * 2);
@@ -1210,6 +1210,60 @@ static void TRANSFORM_OT_transform(struct wmOperatorType *ot)
P_ALIGN_SNAP | P_GPENCIL_EDIT | P_CENTER);
}
+static int transform_from_gizmo_invoke(bContext *C,
+ wmOperator *UNUSED(op),
+ const wmEvent *UNUSED(event))
+{
+ bToolRef *tref = WM_toolsystem_ref_from_context(C);
+ if (tref) {
+ ARegion *ar = CTX_wm_region(C);
+ wmGizmoMap *gzmap = ar->gizmo_map;
+ wmGizmoGroup *gzgroup = gzmap ? WM_gizmomap_group_find(gzmap, "VIEW3D_GGT_xform_gizmo") : NULL;
+ if (gzgroup != NULL) {
+ PointerRNA gzg_ptr;
+ WM_toolsystem_ref_properties_ensure_from_gizmo_group(tref, gzgroup->type, &gzg_ptr);
+ const int drag_action = RNA_enum_get(&gzg_ptr, "drag_action");
+ const char *op_id = NULL;
+ switch (drag_action) {
+ case V3D_GIZMO_SHOW_OBJECT_TRANSLATE:
+ op_id = "TRANSFORM_OT_translate";
+ break;
+ case V3D_GIZMO_SHOW_OBJECT_ROTATE:
+ op_id = "TRANSFORM_OT_rotate";
+ break;
+ case V3D_GIZMO_SHOW_OBJECT_SCALE:
+ op_id = "TRANSFORM_OT_resize";
+ break;
+ default:
+ break;
+ }
+ if (op_id) {
+ wmOperatorType *ot = WM_operatortype_find(op_id, true);
+ PointerRNA op_ptr;
+ WM_operator_properties_create_ptr(&op_ptr, ot);
+ RNA_boolean_set(&op_ptr, "release_confirm", true);
+ WM_operator_name_call_ptr(C, ot, WM_OP_INVOKE_DEFAULT, &op_ptr);
+ WM_operator_properties_free(&op_ptr);
+ return OPERATOR_FINISHED;
+ }
+ }
+ }
+ return OPERATOR_PASS_THROUGH;
+}
+
+/* Use with 'TRANSFORM_GGT_gizmo'. */
+static void TRANSFORM_OT_from_gizmo(struct wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name = "Transform From Gizmo";
+ ot->description = "Transform selected items by mode type";
+ ot->idname = "TRANSFORM_OT_from_gizmo";
+ ot->flag = 0;
+
+ /* api callbacks */
+ ot->invoke = transform_from_gizmo_invoke;
+}
+
void transform_operatortypes(void)
{
TransformModeItem *tmode;
@@ -1223,6 +1277,8 @@ void transform_operatortypes(void)
WM_operatortype_append(TRANSFORM_OT_select_orientation);
WM_operatortype_append(TRANSFORM_OT_create_orientation);
WM_operatortype_append(TRANSFORM_OT_delete_orientation);
+
+ WM_operatortype_append(TRANSFORM_OT_from_gizmo);
}
void ED_keymap_transform(wmKeyConfig *keyconf)
diff --git a/source/blender/editors/undo/ed_undo.c b/source/blender/editors/undo/ed_undo.c
index 49b5cada04a..ccbe12b4a93 100644
--- a/source/blender/editors/undo/ed_undo.c
+++ b/source/blender/editors/undo/ed_undo.c
@@ -569,7 +569,7 @@ static const EnumPropertyItem *rna_undo_itemf(bContext *C, int *totitem)
item_tmp.identifier = us->name;
item_tmp.name = IFACE_(us->name);
if (us == wm->undo_stack->step_active) {
- item_tmp.icon = ICON_HIDE_OFF;
+ item_tmp.icon = ICON_LAYER_ACTIVE;
}
else {
item_tmp.icon = ICON_NONE;
diff --git a/source/blender/editors/util/CMakeLists.txt b/source/blender/editors/util/CMakeLists.txt
index 0564cb07897..c09237d825d 100644
--- a/source/blender/editors/util/CMakeLists.txt
+++ b/source/blender/editors/util/CMakeLists.txt
@@ -41,6 +41,7 @@ set(SRC
ed_util.c
gizmo_utils.c
numinput.c
+ select_buffer_utils.c
select_utils.c
# general includes
@@ -79,6 +80,7 @@ set(SRC
../include/ED_screen.h
../include/ED_screen_types.h
../include/ED_sculpt.h
+ ../include/ED_select_buffer_utils.h
../include/ED_select_utils.h
../include/ED_sequencer.h
../include/ED_sound.h
diff --git a/source/blender/editors/util/select_buffer_utils.c b/source/blender/editors/util/select_buffer_utils.c
new file mode 100644
index 00000000000..130f6819e34
--- /dev/null
+++ b/source/blender/editors/util/select_buffer_utils.c
@@ -0,0 +1,303 @@
+/*
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * The Original Code is Copyright (C) 2008 Blender Foundation.
+ * All rights reserved.
+ */
+
+/** \file
+ * \ingroup edutil
+ *
+ * Generic utilities for handling buffer selection where selection ID's are drawn onto
+ * an off screen buffer.
+ *
+ * All coordinates are relative to the current region.
+ */
+
+#include "MEM_guardedalloc.h"
+
+#include "BLI_bitmap.h"
+#include "BLI_bitmap_draw_2d.h"
+#include "BLI_rect.h"
+#include "BLI_utildefines.h"
+
+#include "ED_select_buffer_utils.h"
+
+/* Only for #ED_view3d_select_id_read,
+ * note that this file shouldn't have 3D view specific logic in it, we could have a more general
+ * way to read from selection buffers that doesn't depend on the view3d API. */
+#include "ED_view3d.h"
+
+/* -------------------------------------------------------------------- */
+/** \name Select Bitmap from ID's
+ *
+ * Given a buffer of select ID's, fill in a booleans (true/false) per index.
+ * #BLI_bitmap is used for memory effeciency.
+ *
+ * \{ */
+
+/**
+ * \param bitmap_len: Number of indices in the selection id buffer.
+ * \param rect: The rectangle to sample indices from (min/max inclusive).
+ * \returns a #BLI_bitmap the length of \a bitmap_len or NULL on failure.
+ */
+uint *ED_select_buffer_bitmap_from_rect(const uint bitmap_len, const rcti *rect)
+{
+ uint buf_len;
+ const uint *buf = ED_view3d_select_id_read(
+ rect->xmin, rect->ymin, rect->xmax, rect->ymax, &buf_len);
+ if (buf == NULL) {
+ return NULL;
+ }
+
+ const uint *buf_iter = buf;
+
+ BLI_bitmap *bitmap_buf = BLI_BITMAP_NEW(bitmap_len, __func__);
+
+ while (buf_len--) {
+ const uint index = *buf_iter - 1;
+ if (index < bitmap_len) {
+ BLI_BITMAP_ENABLE(bitmap_buf, index);
+ }
+ buf_iter++;
+ }
+ MEM_freeN((void *)buf);
+ return bitmap_buf;
+}
+
+/**
+ * \param bitmap_len: Number of indices in the selection id buffer.
+ * \param center: Circle center.
+ * \param radius: Circle radius.
+ * \returns a #BLI_bitmap the length of \a bitmap_len or NULL on failure.
+ */
+uint *ED_select_buffer_bitmap_from_circle(const uint bitmap_len,
+ const int center[2],
+ const int radius)
+{
+ if (bitmap_len == 0) {
+ return NULL;
+ }
+
+ const int xmin = center[0] - radius;
+ const int xmax = center[0] + radius;
+ const int ymin = center[1] - radius;
+ const int ymax = center[1] + radius;
+
+ const uint *buf = ED_view3d_select_id_read(xmin, ymin, xmax, ymax, NULL);
+ if (buf == NULL) {
+ return NULL;
+ }
+
+ const uint *buf_iter = buf;
+
+ BLI_bitmap *bitmap_buf = BLI_BITMAP_NEW(bitmap_len, __func__);
+ const int radius_sq = radius * radius;
+ for (int yc = -radius; yc <= radius; yc++) {
+ for (int xc = -radius; xc <= radius; xc++, buf_iter++) {
+ if (xc * xc + yc * yc < radius_sq) {
+ /* Intentionally wrap to max value if this is zero. */
+ const uint index = *buf_iter - 1;
+ if (index < bitmap_len) {
+ BLI_BITMAP_ENABLE(bitmap_buf, index);
+ }
+ }
+ }
+ }
+ MEM_freeN((void *)buf);
+ return bitmap_buf;
+}
+
+struct PolyMaskData {
+ BLI_bitmap *px;
+ int width;
+};
+
+static void ed_select_buffer_mask_px_cb(int x, int x_end, int y, void *user_data)
+{
+ struct PolyMaskData *data = user_data;
+ BLI_bitmap *px = data->px;
+ int i = (y * data->width) + x;
+ do {
+ BLI_BITMAP_ENABLE(px, i);
+ i++;
+ } while (++x != x_end);
+}
+
+/**
+ * \param bitmap_len: Number of indices in the selection id buffer.
+ * \param center: Circle center.
+ * \param radius: Circle radius.
+ * \returns a #BLI_bitmap the length of \a bitmap_len or NULL on failure.
+ */
+uint *ED_select_buffer_bitmap_from_poly(const uint bitmap_len,
+ const int poly[][2],
+ const int poly_len,
+ const rcti *rect)
+
+{
+ if (bitmap_len == 0) {
+ return NULL;
+ }
+
+ struct PolyMaskData poly_mask_data;
+ uint buf_len;
+ const uint *buf = ED_view3d_select_id_read(
+ rect->xmin, rect->ymin, rect->xmax, rect->ymax, &buf_len);
+ if (buf == NULL) {
+ return NULL;
+ }
+
+ BLI_bitmap *buf_mask = BLI_BITMAP_NEW(buf_len, __func__);
+ poly_mask_data.px = buf_mask;
+ poly_mask_data.width = (rect->xmax - rect->xmin) + 1;
+
+ BLI_bitmap_draw_2d_poly_v2i_n(rect->xmin,
+ rect->ymin,
+ rect->xmax + 1,
+ rect->ymax + 1,
+ poly,
+ poly_len,
+ ed_select_buffer_mask_px_cb,
+ &poly_mask_data);
+
+ /* Build selection lookup. */
+ const uint *buf_iter = buf;
+ BLI_bitmap *bitmap_buf = BLI_BITMAP_NEW(bitmap_len, __func__);
+ int i = 0;
+ while (buf_len--) {
+ const uint index = *buf_iter - 1;
+ if (index < bitmap_len && BLI_BITMAP_TEST(buf_mask, i)) {
+ BLI_BITMAP_ENABLE(bitmap_buf, index);
+ }
+ buf_iter++;
+ i++;
+ }
+ MEM_freeN((void *)buf);
+ MEM_freeN(buf_mask);
+
+ return bitmap_buf;
+}
+
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Find Single Select ID's
+ *
+ * Given a buffer of select ID's, find the a single select id.
+ *
+ * \{ */
+
+/**
+ * Samples a single pixel.
+ */
+uint ED_select_buffer_sample_point(const int center[2])
+{
+ uint buf_len;
+ uint *buf = ED_view3d_select_id_read(center[0], center[1], center[0], center[1], &buf_len);
+ BLI_assert(0 != buf_len);
+ uint ret = buf[0];
+ MEM_freeN(buf);
+ return ret;
+}
+
+/**
+ * Find the selection id closest to \a center.
+ * \param dist[in,out]: Use to initalize the distance,
+ * when found, this value is set to the distance of the selection thats returned.
+ */
+uint ED_select_buffer_find_nearest_to_point(const int center[2],
+ const uint id_min,
+ const uint id_max,
+ uint *dist)
+{
+ /* Smart function to sample a rect spiralling outside, nice for selection ID. */
+
+ /* Create region around center (typically the mouse cursor).
+ * This must be square and have an odd width,
+ * the spiraling algorithm does not work with arbitrary rectangles. */
+ rcti rect;
+ BLI_rcti_init_pt_radius(&rect, center, *dist);
+ rect.xmax += 1;
+ rect.ymax += 1;
+
+ int width = BLI_rcti_size_x(&rect);
+ int height = width;
+ BLI_assert(width == height);
+
+ /* Read from selection framebuffer. */
+
+ uint buf_len;
+ const uint *buf = ED_view3d_select_id_read_rect(&rect, &buf_len);
+ BLI_assert(width * height == buf_len);
+
+ /* Spiral, starting from center of buffer. */
+ int spiral_offset = height * (int)(width / 2) + (height / 2);
+ int spiral_direction = 0;
+
+ uint index = 0;
+
+ for (int nr = 1; nr <= height; nr++) {
+ for (int a = 0; a < 2; a++) {
+ for (int b = 0; b < nr; b++) {
+ /* Find hit within the specified range. */
+ uint hit_id = buf[spiral_offset];
+
+ if (hit_id && hit_id >= id_min && hit_id < id_max) {
+ /* Get x/y from spiral offset. */
+ int hit_x = spiral_offset % width;
+ int hit_y = spiral_offset / width;
+
+ int center_x = width / 2;
+ int center_y = height / 2;
+
+ /* Manhatten distance in keeping with other screen-based selection. */
+ *dist = (uint)(abs(hit_x - center_x) + abs(hit_y - center_y));
+
+ /* Indices start at 1 here. */
+ index = (hit_id - id_min) + 1;
+ goto exit;
+ }
+
+ /* Next spiral step. */
+ if (spiral_direction == 0) {
+ spiral_offset += 1; /* right */
+ }
+ else if (spiral_direction == 1) {
+ spiral_offset -= width; /* down */
+ }
+ else if (spiral_direction == 2) {
+ spiral_offset -= 1; /* left */
+ }
+ else {
+ spiral_offset += width; /* up */
+ }
+
+ /* Stop if we are outside the buffer. */
+ if (spiral_offset < 0 || spiral_offset >= buf_len) {
+ goto exit;
+ }
+ }
+
+ spiral_direction = (spiral_direction + 1) % 4;
+ }
+ }
+
+exit:
+ MEM_freeN((void *)buf);
+ return index;
+}
+
+/** \} */
diff --git a/source/blender/editors/uvedit/uvedit_draw.c b/source/blender/editors/uvedit/uvedit_draw.c
index 3a5aead3d44..7f9b90f4496 100644
--- a/source/blender/editors/uvedit/uvedit_draw.c
+++ b/source/blender/editors/uvedit/uvedit_draw.c
@@ -246,6 +246,7 @@ static void draw_uvs_texpaint(Scene *scene, Object *ob, Depsgraph *depsgraph)
bool prev_ma_match = (mpoly->mat_nr == (eval_ob->actcol - 1));
GPU_matrix_bind(geom->interface);
+ GPU_batch_bind(geom);
/* TODO(fclem): If drawcall count becomes a problem in the future
* we can use multi draw indirect drawcalls for this.
@@ -254,7 +255,7 @@ static void draw_uvs_texpaint(Scene *scene, Object *ob, Depsgraph *depsgraph)
bool ma_match = (mpoly->mat_nr == (eval_ob->actcol - 1));
if (ma_match != prev_ma_match) {
if (ma_match == false) {
- GPU_batch_draw_range_ex(geom, draw_start, idx - draw_start, false);
+ GPU_batch_draw_advanced(geom, draw_start, idx - draw_start, 0, 0);
}
else {
draw_start = idx;
@@ -264,7 +265,7 @@ static void draw_uvs_texpaint(Scene *scene, Object *ob, Depsgraph *depsgraph)
prev_ma_match = ma_match;
}
if (prev_ma_match == true) {
- GPU_batch_draw_range_ex(geom, draw_start, idx - draw_start, false);
+ GPU_batch_draw_advanced(geom, draw_start, idx - draw_start, 0, 0);
}
GPU_batch_program_use_end(geom);
diff --git a/source/blender/freestyle/intern/blender_interface/BlenderFileLoader.cpp b/source/blender/freestyle/intern/blender_interface/BlenderFileLoader.cpp
index ee13583e67a..e9d81ef479b 100644
--- a/source/blender/freestyle/intern/blender_interface/BlenderFileLoader.cpp
+++ b/source/blender/freestyle/intern/blender_interface/BlenderFileLoader.cpp
@@ -99,7 +99,7 @@ NodeGroup *BlenderFileLoader::Load()
continue;
}
- Mesh *mesh = BKE_object_to_mesh(ob);
+ Mesh *mesh = BKE_object_to_mesh(NULL, ob, false);
if (mesh) {
insertShapeNode(ob, mesh, ++id);
diff --git a/source/blender/freestyle/intern/blender_interface/BlenderStrokeRenderer.cpp b/source/blender/freestyle/intern/blender_interface/BlenderStrokeRenderer.cpp
index dbd770eb5e8..8a3cdd575fe 100644
--- a/source/blender/freestyle/intern/blender_interface/BlenderStrokeRenderer.cpp
+++ b/source/blender/freestyle/intern/blender_interface/BlenderStrokeRenderer.cpp
@@ -263,6 +263,7 @@ Material *BlenderStrokeRenderer::GetStrokeShader(Main *bmain,
}
ma->nodetree = ntree;
ma->use_nodes = 1;
+ ma->blend_method = MA_BM_HASHED;
bNode *input_attr_color = nodeAddStaticNode(NULL, ntree, SH_NODE_ATTRIBUTE);
input_attr_color->locx = 0.0f;
diff --git a/source/blender/gpu/GPU_batch.h b/source/blender/gpu/GPU_batch.h
index 783bfb0b1f0..5b0cab220c0 100644
--- a/source/blender/gpu/GPU_batch.h
+++ b/source/blender/gpu/GPU_batch.h
@@ -132,7 +132,7 @@ void GPU_batch_program_set_builtin_with_config(GPUBatch *batch,
void GPU_batch_program_use_begin(GPUBatch *); /* call before Batch_Uniform (temp hack?) */
void GPU_batch_program_use_end(GPUBatch *);
-void GPU_batch_uniform_1ui(GPUBatch *, const char *name, int value);
+void GPU_batch_uniform_1ui(GPUBatch *, const char *name, uint value);
void GPU_batch_uniform_1i(GPUBatch *, const char *name, int value);
void GPU_batch_uniform_1b(GPUBatch *, const char *name, bool value);
void GPU_batch_uniform_1f(GPUBatch *, const char *name, float value);
@@ -142,14 +142,16 @@ void GPU_batch_uniform_4f(GPUBatch *, const char *name, float x, float y, float
void GPU_batch_uniform_2fv(GPUBatch *, const char *name, const float data[2]);
void GPU_batch_uniform_3fv(GPUBatch *, const char *name, const float data[3]);
void GPU_batch_uniform_4fv(GPUBatch *, const char *name, const float data[4]);
-void GPU_batch_uniform_2fv_array(GPUBatch *, const char *name, int len, const float *data);
-void GPU_batch_uniform_4fv_array(GPUBatch *, const char *name, int len, const float *data);
+void GPU_batch_uniform_2fv_array(GPUBatch *, const char *name, const int len, const float *data);
+void GPU_batch_uniform_4fv_array(GPUBatch *, const char *name, const int len, const float *data);
void GPU_batch_uniform_mat4(GPUBatch *, const char *name, const float data[4][4]);
void GPU_batch_draw(GPUBatch *);
+/* Needs to be called before GPU_batch_draw_advanced. */
+void GPU_batch_bind(GPUBatch *);
/* This does not bind/unbind shader and does not call GPU_matrix_bind() */
-void GPU_batch_draw_range_ex(GPUBatch *, int v_first, int v_count, bool force_instance);
+void GPU_batch_draw_advanced(GPUBatch *, int v_first, int v_count, int i_first, int i_count);
/* Does not even need batch */
void GPU_draw_primitive(GPUPrimType, int v_count);
diff --git a/source/blender/gpu/GPU_shader_interface.h b/source/blender/gpu/GPU_shader_interface.h
index fc7d9e22ea3..d3a9a18b392 100644
--- a/source/blender/gpu/GPU_shader_interface.h
+++ b/source/blender/gpu/GPU_shader_interface.h
@@ -44,9 +44,9 @@ typedef enum {
GPU_UNIFORM_PROJECTION_INV, /* mat4 ProjectionMatrixInverse */
GPU_UNIFORM_VIEWPROJECTION_INV, /* mat4 ViewProjectionMatrixInverse */
- GPU_UNIFORM_NORMAL, /* mat3 NormalMatrix */
- GPU_UNIFORM_CAMERATEXCO, /* vec4 CameraTexCoFactors */
- GPU_UNIFORM_ORCO, /* vec3 OrcoTexCoFactors[] */
+ GPU_UNIFORM_NORMAL, /* mat3 NormalMatrix */
+ GPU_UNIFORM_ORCO, /* vec3 OrcoTexCoFactors[] */
+ GPU_UNIFORM_CLIPPLANES, /* vec4 WorldClipPlanes[] */
GPU_UNIFORM_COLOR, /* vec4 color */
GPU_UNIFORM_CALLID, /* int callId */
diff --git a/source/blender/gpu/GPU_viewport.h b/source/blender/gpu/GPU_viewport.h
index e61cfe363df..e7600279d6f 100644
--- a/source/blender/gpu/GPU_viewport.h
+++ b/source/blender/gpu/GPU_viewport.h
@@ -39,8 +39,10 @@ typedef struct GPUViewport GPUViewport;
typedef struct ViewportMemoryPool {
struct BLI_memblock *calls;
struct BLI_memblock *states;
+ struct BLI_memblock *cullstates;
struct BLI_memblock *shgroups;
struct BLI_memblock *uniforms;
+ struct BLI_memblock *views;
struct BLI_memblock *passes;
struct BLI_memblock *images;
} ViewportMemoryPool;
diff --git a/source/blender/gpu/intern/gpu_batch.c b/source/blender/gpu/intern/gpu_batch.c
index 45697befe50..d1cfd5c337d 100644
--- a/source/blender/gpu/intern/gpu_batch.c
+++ b/source/blender/gpu/intern/gpu_batch.c
@@ -56,7 +56,7 @@ void GPU_batch_vao_cache_clear(GPUBatch *batch)
(GPUShaderInterface *)batch->dynamic_vaos.interfaces[i], batch);
}
}
- MEM_freeN(batch->dynamic_vaos.interfaces);
+ MEM_freeN((void *)batch->dynamic_vaos.interfaces);
MEM_freeN(batch->dynamic_vaos.vao_ids);
}
else {
@@ -285,7 +285,7 @@ static GLuint batch_vao_get(GPUBatch *batch)
/* Not enough place, realloc the array. */
i = batch->dynamic_vaos.count;
batch->dynamic_vaos.count += GPU_BATCH_VAO_DYN_ALLOC_COUNT;
- batch->dynamic_vaos.interfaces = MEM_recallocN(batch->dynamic_vaos.interfaces,
+ batch->dynamic_vaos.interfaces = MEM_recallocN((void *)batch->dynamic_vaos.interfaces,
sizeof(GPUShaderInterface *) *
batch->dynamic_vaos.count);
batch->dynamic_vaos.vao_ids = MEM_recallocN(batch->dynamic_vaos.vao_ids,
@@ -461,7 +461,7 @@ void GPU_batch_program_use_end(GPUBatch *batch)
const GPUShaderInput *uniform = GPU_shaderinterface_uniform_ensure(batch->interface, name);
#endif
-void GPU_batch_uniform_1ui(GPUBatch *batch, const char *name, int value)
+void GPU_batch_uniform_1ui(GPUBatch *batch, const char *name, uint value)
{
GET_UNIFORM
glUniform1ui(uniform->location, value);
@@ -577,10 +577,14 @@ static void *elem_offset(const GPUIndexBuf *el, int v_first)
else if (el->index_type == GPU_INDEX_U16) {
return (GLushort *)0 + v_first;
}
- else {
#endif
- return (GLuint *)0 + v_first;
- }
+ return (GLuint *)0 + v_first;
+}
+
+/* Use when drawing with GPU_batch_draw_advanced */
+void GPU_batch_bind(GPUBatch *batch)
+{
+ glBindVertexArray(batch->vao_id);
}
void GPU_batch_draw(GPUBatch *batch)
@@ -592,103 +596,76 @@ void GPU_batch_draw(GPUBatch *batch)
GPU_batch_program_use_begin(batch);
GPU_matrix_bind(batch->interface); // external call.
- GPU_batch_draw_range_ex(batch, 0, 0, false);
+ GPU_batch_bind(batch);
+ GPU_batch_draw_advanced(batch, 0, 0, 0, 0);
GPU_batch_program_use_end(batch);
}
-void GPU_batch_draw_range_ex(GPUBatch *batch, int v_first, int v_count, bool force_instance)
+void GPU_batch_draw_advanced(GPUBatch *batch, int v_first, int v_count, int i_first, int i_count)
{
#if TRUST_NO_ONE
- assert(!(force_instance && (batch->inst == NULL)) ||
- v_count > 0); // we cannot infer length if force_instance
+ BLI_assert(batch->program_in_use);
+ /* TODO could assert that VAO is bound. */
#endif
- const bool do_instance = (force_instance || batch->inst);
-
- // If using offset drawing, use the default VAO and redo bindings.
- if (v_first != 0 && do_instance) {
- glBindVertexArray(GPU_vao_default());
- batch_update_program_bindings(batch, v_first);
+ if (v_count == 0) {
+ v_count = (batch->elem) ? batch->elem->index_len : batch->verts[0]->vertex_len;
}
- else {
- glBindVertexArray(batch->vao_id);
+ if (i_count == 0) {
+ i_count = (batch->inst) ? batch->inst->vertex_len : 1;
}
- if (do_instance) {
- /* Infer length if vertex count is not given */
- if (v_count == 0) {
- v_count = batch->inst->vertex_len;
+ if (!GLEW_ARB_base_instance) {
+ if (i_first > 0 && i_count > 0) {
+ /* If using offset drawing with instancing, we must
+ * use the default VAO and redo bindings. */
+ glBindVertexArray(GPU_vao_default());
+ batch_update_program_bindings(batch, i_first);
}
+ else {
+ /* Previous call could have bind the default vao
+ * see above. */
+ glBindVertexArray(batch->vao_id);
+ }
+ }
- if (batch->elem) {
- const GPUIndexBuf *el = batch->elem;
-
- if (el->use_prim_restart) {
- primitive_restart_enable(el);
- }
+ if (batch->elem) {
+ const GPUIndexBuf *el = batch->elem;
#if GPU_TRACK_INDEX_RANGE
- glDrawElementsInstancedBaseVertex(
- batch->gl_prim_type, el->index_len, el->gl_index_type, 0, v_count, el->base_index);
+ GLenum index_type = el->gl_index_type;
+ GLint base_index = el->base_index;
#else
- glDrawElementsInstanced(batch->gl_prim_type, el->index_len, GL_UNSIGNED_INT, 0, v_count);
+ GLenum index_type = GL_UNSIGNED_INT;
+ GLint base_index = 0;
#endif
- if (el->use_prim_restart) {
- primitive_restart_disable();
- }
+ void *v_first_ofs = elem_offset(el, v_first);
+
+ if (el->use_prim_restart) {
+ primitive_restart_enable(el);
+ }
+
+ if (GLEW_ARB_base_instance) {
+ glDrawElementsInstancedBaseVertexBaseInstance(
+ batch->gl_prim_type, v_count, index_type, v_first_ofs, i_count, base_index, i_first);
}
else {
- glDrawArraysInstanced(batch->gl_prim_type, 0, batch->verts[0]->vertex_len, v_count);
+ glDrawElementsInstancedBaseVertex(
+ batch->gl_prim_type, v_count, index_type, v_first_ofs, i_count, base_index);
+ }
+
+ if (el->use_prim_restart) {
+ primitive_restart_disable();
}
}
else {
- /* Infer length if vertex count is not given */
- if (v_count == 0) {
- v_count = (batch->elem) ? batch->elem->index_len : batch->verts[0]->vertex_len;
- }
-
- if (batch->elem) {
- const GPUIndexBuf *el = batch->elem;
-
- if (el->use_prim_restart) {
- primitive_restart_enable(el);
- }
-
- void *v_first_ofs = elem_offset(el, v_first);
-
-#if GPU_TRACK_INDEX_RANGE
- if (el->base_index) {
- glDrawRangeElementsBaseVertex(batch->gl_prim_type,
- el->min_index,
- el->max_index,
- v_count,
- el->gl_index_type,
- v_first_ofs,
- el->base_index);
- }
- else {
- glDrawRangeElements(batch->gl_prim_type,
- el->min_index,
- el->max_index,
- v_count,
- el->gl_index_type,
- v_first_ofs);
- }
-#else
- glDrawElements(batch->gl_prim_type, v_count, GL_UNSIGNED_INT, v_first_ofs);
-#endif
- if (el->use_prim_restart) {
- primitive_restart_disable();
- }
+ if (GLEW_ARB_base_instance) {
+ glDrawArraysInstancedBaseInstance(batch->gl_prim_type, v_first, v_count, i_count, i_first);
}
else {
- glDrawArrays(batch->gl_prim_type, v_first, v_count);
+ glDrawArraysInstanced(batch->gl_prim_type, v_first, v_count, i_count);
}
}
-
- /* Performance hog if you are drawing with the same vao multiple time.
- * Only activate for debugging. */
- // glBindVertexArray(0);
}
/* just draw some vertices and let shader place them where we want. */
diff --git a/source/blender/gpu/intern/gpu_draw.c b/source/blender/gpu/intern/gpu_draw.c
index 2220eef4034..638729d027c 100644
--- a/source/blender/gpu/intern/gpu_draw.c
+++ b/source/blender/gpu/intern/gpu_draw.c
@@ -757,7 +757,7 @@ void GPU_create_gl_tex_compressed(unsigned int *bind, int textarget, Image *ima,
if (textarget == GL_TEXTURE_2D && GPU_upload_dxt_texture(ibuf, use_srgb) == 0) {
glDeleteTextures(1, (GLuint *)bind);
- GPU_create_gl_tex(bind, ibuf->rect, NULL, ibuf->x, ibuf->x, textarget, mipmap, use_srgb, ima);
+ GPU_create_gl_tex(bind, ibuf->rect, NULL, ibuf->x, ibuf->y, textarget, mipmap, use_srgb, ima);
}
glBindTexture(textarget, 0);
diff --git a/source/blender/gpu/intern/gpu_material.c b/source/blender/gpu/intern/gpu_material.c
index fde60fd387d..007a13a06ef 100644
--- a/source/blender/gpu/intern/gpu_material.c
+++ b/source/blender/gpu/intern/gpu_material.c
@@ -620,7 +620,7 @@ void GPU_material_flag_set(GPUMaterial *mat, eGPUMatFlag flag)
bool GPU_material_flag_get(GPUMaterial *mat, eGPUMatFlag flag)
{
- return (mat->flag & flag);
+ return (mat->flag & flag) != 0;
}
GPUMaterial *GPU_material_from_nodetree_find(ListBase *gpumaterials,
@@ -684,7 +684,10 @@ GPUMaterial *GPU_material_from_nodetree(Scene *scene,
if (mat->outlink) {
/* HACK: this is only for eevee. We add the define here after the nodetree evaluation. */
if (GPU_material_flag_get(mat, GPU_MATFLAG_SSS)) {
- defines = BLI_string_joinN(defines, "#define USE_SSS\n");
+ defines = BLI_string_joinN(defines,
+ "#ifndef USE_ALPHA_BLEND\n"
+ "# define USE_SSS\n"
+ "#endif\n");
}
/* Prune the unused nodes and extract attributes before compiling so the
* generated VBOs are ready to accept the future shader. */
diff --git a/source/blender/gpu/intern/gpu_select.c b/source/blender/gpu/intern/gpu_select.c
index 010087e5536..119aed2f5ed 100644
--- a/source/blender/gpu/intern/gpu_select.c
+++ b/source/blender/gpu/intern/gpu_select.c
@@ -229,12 +229,18 @@ void GPU_select_buffer_stride_realign(const rcti *src, const rcti *dst, uint *r_
const int dst_x = BLI_rcti_size_x(dst);
const int dst_y = BLI_rcti_size_y(dst);
- int last_px_written = dst_x * dst_y - 1;
int last_px_id = src_x * (y + dst_y - 1) + (x + dst_x - 1);
- const int skip = src_x - dst_x;
-
memset(&r_buf[last_px_id + 1], 0, (src_x * src_y - (last_px_id + 1)) * sizeof(*r_buf));
+ if (last_px_id < 0) {
+ /* Nothing to write. */
+ BLI_assert(last_px_id == -1);
+ return;
+ }
+
+ int last_px_written = dst_x * dst_y - 1;
+ const int skip = src_x - dst_x;
+
while (true) {
for (int i = dst_x; i--;) {
r_buf[last_px_id--] = r_buf[last_px_written--];
diff --git a/source/blender/gpu/intern/gpu_shader_interface.c b/source/blender/gpu/intern/gpu_shader_interface.c
index 97dbb80d736..e7483e45312 100644
--- a/source/blender/gpu/intern/gpu_shader_interface.c
+++ b/source/blender/gpu/intern/gpu_shader_interface.c
@@ -61,8 +61,8 @@ static const char *BuiltinUniform_name(GPUUniformBuiltin u)
[GPU_UNIFORM_VIEWPROJECTION_INV] = "ViewProjectionMatrixInverse",
[GPU_UNIFORM_NORMAL] = "NormalMatrix",
- [GPU_UNIFORM_CAMERATEXCO] = "CameraTexCoFactors",
[GPU_UNIFORM_ORCO] = "OrcoTexCoFactors",
+ [GPU_UNIFORM_CLIPPLANES] = "WorldClipPlanes",
[GPU_UNIFORM_COLOR] = "color",
[GPU_UNIFORM_CALLID] = "callId",
diff --git a/source/blender/gpu/intern/gpu_viewport.c b/source/blender/gpu/intern/gpu_viewport.c
index b825819ceb4..4fd439f4203 100644
--- a/source/blender/gpu/intern/gpu_viewport.c
+++ b/source/blender/gpu/intern/gpu_viewport.c
@@ -625,12 +625,18 @@ void GPU_viewport_free(GPUViewport *viewport)
if (viewport->vmempool.states != NULL) {
BLI_memblock_destroy(viewport->vmempool.states, NULL);
}
+ if (viewport->vmempool.cullstates != NULL) {
+ BLI_memblock_destroy(viewport->vmempool.cullstates, NULL);
+ }
if (viewport->vmempool.shgroups != NULL) {
BLI_memblock_destroy(viewport->vmempool.shgroups, NULL);
}
if (viewport->vmempool.uniforms != NULL) {
BLI_memblock_destroy(viewport->vmempool.uniforms, NULL);
}
+ if (viewport->vmempool.views != NULL) {
+ BLI_memblock_destroy(viewport->vmempool.views, NULL);
+ }
if (viewport->vmempool.passes != NULL) {
BLI_memblock_destroy(viewport->vmempool.passes, NULL);
}
diff --git a/source/blender/gpu/shaders/gpu_shader_cfg_world_clip_lib.glsl b/source/blender/gpu/shaders/gpu_shader_cfg_world_clip_lib.glsl
index e34b86ac1ce..46cf2fe09a2 100644
--- a/source/blender/gpu/shaders/gpu_shader_cfg_world_clip_lib.glsl
+++ b/source/blender/gpu/shaders/gpu_shader_cfg_world_clip_lib.glsl
@@ -1,15 +1,24 @@
#ifdef USE_WORLD_CLIP_PLANES
# if defined(GPU_VERTEX_SHADER) || defined(GPU_GEOMETRY_SHADER)
+
uniform vec4 WorldClipPlanes[6];
-void world_clip_planes_calc_clip_distance(vec3 wpos)
-{
- gl_ClipDistance[0] = dot(WorldClipPlanes[0].xyz, wpos) + WorldClipPlanes[0].w;
- gl_ClipDistance[1] = dot(WorldClipPlanes[1].xyz, wpos) + WorldClipPlanes[1].w;
- gl_ClipDistance[2] = dot(WorldClipPlanes[2].xyz, wpos) + WorldClipPlanes[2].w;
- gl_ClipDistance[3] = dot(WorldClipPlanes[3].xyz, wpos) + WorldClipPlanes[3].w;
- gl_ClipDistance[4] = dot(WorldClipPlanes[4].xyz, wpos) + WorldClipPlanes[4].w;
- gl_ClipDistance[5] = dot(WorldClipPlanes[5].xyz, wpos) + WorldClipPlanes[5].w;
-}
+
+# define _world_clip_planes_calc_clip_distance(wpos, _clipplanes) \
+ { \
+ vec4 pos = vec4(wpos, 1.0); \
+ gl_ClipDistance[0] = dot(_clipplanes[0], pos); \
+ gl_ClipDistance[1] = dot(_clipplanes[1], pos); \
+ gl_ClipDistance[2] = dot(_clipplanes[2], pos); \
+ gl_ClipDistance[3] = dot(_clipplanes[3], pos); \
+ gl_ClipDistance[4] = dot(_clipplanes[4], pos); \
+ gl_ClipDistance[5] = dot(_clipplanes[5], pos); \
+ }
+
+/* HACK Dirty hack to be able to override the definition in common_view_lib.glsl.
+ * Not doing this would require changing the include order in every shaders. */
+# define world_clip_planes_calc_clip_distance(wpos) \
+ _world_clip_planes_calc_clip_distance(wpos, WorldClipPlanes)
+
# endif
# define world_clip_planes_set_clip_distance(c) \
diff --git a/source/blender/imbuf/IMB_imbuf.h b/source/blender/imbuf/IMB_imbuf.h
index f8df14cf317..8574f33bce6 100644
--- a/source/blender/imbuf/IMB_imbuf.h
+++ b/source/blender/imbuf/IMB_imbuf.h
@@ -476,13 +476,11 @@ int imb_get_anim_type(const char *name);
*/
bool IMB_isfloat(struct ImBuf *ibuf);
+/* Do byte/float and colorspace conversions need to take alpha into account? */
+bool IMB_alpha_affects_rgb(const struct ImBuf *ibuf);
+
/* create char buffer, color corrected if necessary, for ImBufs that lack one */
void IMB_rect_from_float(struct ImBuf *ibuf);
-/* Create char buffer for part of the image, color corrected if necessary,
- * Changed part will be stored in buffer.
- * This is expected to be used for texture painting updates */
-void IMB_partial_rect_from_float(
- struct ImBuf *ibuf, float *buffer, int x, int y, int w, int h, bool is_data);
void IMB_float_from_rect(struct ImBuf *ibuf);
void IMB_color_to_bw(struct ImBuf *ibuf);
void IMB_saturation(struct ImBuf *ibuf, float sat);
@@ -555,7 +553,6 @@ void IMB_buffer_byte_from_byte(unsigned char *rect_to,
int height,
int stride_to,
int stride_from);
-void IMB_buffer_float_clamp(float *buf, int width, int height);
void IMB_buffer_float_unpremultiply(float *buf, int width, int height);
void IMB_buffer_float_premultiply(float *buf, int width, int height);
diff --git a/source/blender/imbuf/IMB_imbuf_types.h b/source/blender/imbuf/IMB_imbuf_types.h
index 0f2529e261a..61aa1f401a0 100644
--- a/source/blender/imbuf/IMB_imbuf_types.h
+++ b/source/blender/imbuf/IMB_imbuf_types.h
@@ -285,10 +285,12 @@ enum {
IB_alphamode_premul = 1 << 12,
/** if this flag is set, alpha mode would be guessed from file */
IB_alphamode_detect = 1 << 13,
+ /* alpha channel is unrelated to RGB and should not affect it */
+ IB_alphamode_channel_packed = 1 << 14,
/** ignore alpha on load and substitute it with 1.0f */
- IB_ignore_alpha = 1 << 14,
- IB_thumbnail = 1 << 15,
- IB_multiview = 1 << 16,
+ IB_alphamode_ignore = 1 << 15,
+ IB_thumbnail = 1 << 16,
+ IB_multiview = 1 << 17,
};
/** \} */
diff --git a/source/blender/imbuf/intern/colormanagement.c b/source/blender/imbuf/intern/colormanagement.c
index ba0f10446a1..583a3be8168 100644
--- a/source/blender/imbuf/intern/colormanagement.c
+++ b/source/blender/imbuf/intern/colormanagement.c
@@ -747,6 +747,16 @@ void colormanagement_exit(void)
/*********************** Internal functions *************************/
+static bool colormanage_compatible_look(ColorManagedLook *look, const char *view_name)
+{
+ if (look->is_noop) {
+ return true;
+ }
+
+ /* Skip looks only relevant to specific view transforms. */
+ return (look->view[0] == 0 || (view_name && STREQ(look->view, view_name)));
+}
+
void colormanage_cache_free(ImBuf *ibuf)
{
if (ibuf->display_buffer_flags) {
@@ -840,7 +850,7 @@ static OCIO_ConstProcessorRcPtr *create_display_buffer_processor(const char *loo
OCIO_displayTransformSetView(dt, view_transform);
OCIO_displayTransformSetDisplay(dt, display);
- if (look_descr->is_noop == false) {
+ if (look_descr->is_noop == false && colormanage_compatible_look(look_descr, view_transform)) {
OCIO_displayTransformSetLooksOverrideEnabled(dt, true);
OCIO_displayTransformSetLooksOverride(dt, look);
}
@@ -989,9 +999,9 @@ static OCIO_ConstProcessorRcPtr *display_to_scene_linear_processor(ColorManagedD
void IMB_colormanagement_init_default_view_settings(
ColorManagedViewSettings *view_settings, const ColorManagedDisplaySettings *display_settings)
{
- /* First, try use "Default" view transform of the requested device. */
+ /* First, try use "Standard" view transform of the requested device. */
ColorManagedView *default_view = colormanage_view_get_named_for_display(
- display_settings->display_device, "Default");
+ display_settings->display_device, "Standard");
/* If that fails, we fall back to the default view transform of the display
* as per OCIO configuration. */
if (default_view == NULL) {
@@ -1057,13 +1067,19 @@ void colormanage_imbuf_make_linear(ImBuf *ibuf, const char *from_colorspace)
if (ibuf->rect_float) {
const char *to_colorspace = global_role_scene_linear;
+ const bool predivide = IMB_alpha_affects_rgb(ibuf);
if (ibuf->rect) {
imb_freerectImBuf(ibuf);
}
- IMB_colormanagement_transform(
- ibuf->rect_float, ibuf->x, ibuf->y, ibuf->channels, from_colorspace, to_colorspace, true);
+ IMB_colormanagement_transform(ibuf->rect_float,
+ ibuf->x,
+ ibuf->y,
+ ibuf->channels,
+ from_colorspace,
+ to_colorspace,
+ predivide);
}
}
@@ -1405,6 +1421,7 @@ typedef struct DisplayBufferThread {
int channels;
float dither;
bool is_data;
+ bool predivide;
const char *byte_colorspace;
const char *float_colorspace;
@@ -1469,6 +1486,7 @@ static void display_buffer_init_handle(void *handle_v,
handle->channels = channels;
handle->dither = dither;
handle->is_data = is_data;
+ handle->predivide = IMB_alpha_affects_rgb(ibuf);
handle->byte_colorspace = init_data->byte_colorspace;
handle->float_colorspace = init_data->float_colorspace;
@@ -1486,6 +1504,7 @@ static void display_buffer_apply_get_linear_buffer(DisplayBufferThread *handle,
bool is_data = handle->is_data;
bool is_data_display = handle->cm_processor->is_data_result;
+ bool predivide = handle->predivide;
if (!handle->buffer) {
unsigned char *byte_buffer = handle->byte_buffer;
@@ -1534,7 +1553,7 @@ static void display_buffer_apply_get_linear_buffer(DisplayBufferThread *handle,
if (!is_data && !is_data_display) {
IMB_colormanagement_transform(
- linear_buffer, width, height, channels, from_colorspace, to_colorspace, true);
+ linear_buffer, width, height, channels, from_colorspace, to_colorspace, predivide);
}
*is_straight_alpha = false;
@@ -1590,13 +1609,13 @@ static void *do_display_buffer_apply_thread(void *handle_v)
}
}
else {
- bool is_straight_alpha, predivide;
+ bool is_straight_alpha;
float *linear_buffer = MEM_mallocN(((size_t)channels) * width * height * sizeof(float),
"color conversion linear buffer");
display_buffer_apply_get_linear_buffer(handle, height, linear_buffer, &is_straight_alpha);
- predivide = is_straight_alpha == false;
+ bool predivide = handle->predivide && (is_straight_alpha == false);
if (is_data) {
/* special case for data buffers - no color space conversions,
@@ -2178,6 +2197,7 @@ void IMB_colormanagement_imbuf_to_srgb_texture(unsigned char *out_buffer,
/* TODO(brecht): make this multithreaded, or at least process in batches. */
const unsigned char *in_buffer = (unsigned char *)ibuf->rect;
+ const bool use_premultiply = IMB_alpha_affects_rgb(ibuf);
for (int y = 0; y < height; y++) {
const size_t in_offset = (offset_y + y) * ibuf->x + offset_x;
@@ -2192,11 +2212,13 @@ void IMB_colormanagement_imbuf_to_srgb_texture(unsigned char *out_buffer,
rgba_uchar_to_float(pixel, in);
OCIO_processorApplyRGB(processor, pixel);
linearrgb_to_srgb_v3_v3(pixel, pixel);
- mul_v3_fl(pixel, pixel[3]);
+ if (use_premultiply) {
+ mul_v3_fl(pixel, pixel[3]);
+ }
rgba_float_to_uchar(out, pixel);
}
}
- else {
+ else if (use_premultiply) {
/* Premultiply only. */
for (int x = 0; x < width; x++, in += 4, out += 4) {
out[0] = (in[0] * in[3]) >> 8;
@@ -2205,6 +2227,15 @@ void IMB_colormanagement_imbuf_to_srgb_texture(unsigned char *out_buffer,
out[3] = in[3];
}
}
+ else {
+ /* Copy only. */
+ for (int x = 0; x < width; x++, in += 4, out += 4) {
+ out[0] = in[0];
+ out[1] = in[1];
+ out[2] = in[2];
+ out[3] = in[3];
+ }
+ }
}
}
@@ -3194,17 +3225,9 @@ void IMB_colormanagement_look_items_add(struct EnumPropertyItem **items,
const char *view_name)
{
ColorManagedLook *look;
- const char *view_filter = NULL;
-
- /* Test if this view transform is limited to specific looks. */
- for (look = global_looks.first; look; look = look->next) {
- if (STREQ(look->view, view_name)) {
- view_filter = view_name;
- }
- }
for (look = global_looks.first; look; look = look->next) {
- if (!look->is_noop && view_filter && !STREQ(look->view, view_filter)) {
+ if (!colormanage_compatible_look(look, view_name)) {
continue;
}
diff --git a/source/blender/imbuf/intern/divers.c b/source/blender/imbuf/intern/divers.c
index e4845e56c46..aa49453d68c 100644
--- a/source/blender/imbuf/intern/divers.c
+++ b/source/blender/imbuf/intern/divers.c
@@ -96,6 +96,12 @@ MINLINE void float_to_byte_dither_v4(
b[3] = unit_float_to_uchar_clamp(f[3]);
}
+/* Test if colorspace conversions of pixels in buffer need to take into account alpha. */
+bool IMB_alpha_affects_rgb(const ImBuf *ibuf)
+{
+ return (ibuf->flags & IB_alphamode_channel_packed) == 0;
+}
+
/* float to byte pixels, output 4-channel RGBA */
void IMB_buffer_byte_from_float(uchar *rect_to,
const float *rect_from,
@@ -728,16 +734,19 @@ void IMB_rect_from_float(ImBuf *ibuf)
buffer = MEM_dupallocN(ibuf->rect_float);
/* first make float buffer in byte space */
+ const bool predivide = IMB_alpha_affects_rgb(ibuf);
IMB_colormanagement_transform(buffer,
ibuf->x,
ibuf->y,
ibuf->channels,
from_colorspace,
ibuf->rect_colorspace->name,
- true);
+ predivide);
/* convert from float's premul alpha to byte's straight alpha */
- IMB_unpremultiply_rect_float(buffer, ibuf->channels, ibuf->x, ibuf->y);
+ if (IMB_alpha_affects_rgb(ibuf)) {
+ IMB_unpremultiply_rect_float(buffer, ibuf->channels, ibuf->x, ibuf->y);
+ }
/* convert float to byte */
IMB_buffer_byte_from_float((unsigned char *)ibuf->rect,
@@ -758,118 +767,6 @@ void IMB_rect_from_float(ImBuf *ibuf)
ibuf->userflags &= ~IB_RECT_INVALID;
}
-typedef struct PartialThreadData {
- ImBuf *ibuf;
- float *buffer;
- uchar *rect_byte;
- const float *rect_float;
- int width;
- bool is_data;
-} PartialThreadData;
-
-static void partial_rect_from_float_slice(float *buffer,
- uchar *rect_byte,
- ImBuf *ibuf,
- const float *rect_float,
- const int w,
- const int h,
- const bool is_data)
-{
- const int profile_from = IB_PROFILE_LINEAR_RGB;
- if (is_data) {
- /* exception for non-color data, just copy float */
- IMB_buffer_float_from_float(buffer,
- rect_float,
- ibuf->channels,
- IB_PROFILE_LINEAR_RGB,
- IB_PROFILE_LINEAR_RGB,
- 0,
- w,
- h,
- w,
- ibuf->x);
-
- /* and do color space conversion to byte */
- IMB_buffer_byte_from_float(rect_byte,
- rect_float,
- 4,
- ibuf->dither,
- IB_PROFILE_SRGB,
- profile_from,
- true,
- w,
- h,
- ibuf->x,
- w);
- }
- else {
- IMB_buffer_float_from_float(
- buffer, rect_float, ibuf->channels, IB_PROFILE_SRGB, profile_from, true, w, h, w, ibuf->x);
-
- IMB_buffer_float_unpremultiply(buffer, w, h);
- /* XXX: need to convert to image buffer's rect space */
- IMB_buffer_byte_from_float(
- rect_byte, buffer, 4, ibuf->dither, IB_PROFILE_SRGB, IB_PROFILE_SRGB, 0, w, h, ibuf->x, w);
- }
-}
-
-static void partial_rect_from_float_thread_do(void *data_v, int start_scanline, int num_scanlines)
-{
- PartialThreadData *data = (PartialThreadData *)data_v;
- ImBuf *ibuf = data->ibuf;
- size_t global_offset = ((size_t)ibuf->x) * start_scanline;
- size_t local_offset = ((size_t)data->width) * start_scanline;
- partial_rect_from_float_slice(data->buffer + local_offset * ibuf->channels,
- data->rect_byte + global_offset * 4,
- ibuf,
- data->rect_float + global_offset * ibuf->channels,
- data->width,
- num_scanlines,
- data->is_data);
-}
-
-/**
- * Converts from linear float to sRGB byte for part of the texture,
- * buffer will hold the changed part.
- */
-void IMB_partial_rect_from_float(
- ImBuf *ibuf, float *buffer, int x, int y, int w, int h, bool is_data)
-{
- const float *rect_float;
- uchar *rect_byte;
-
- /* verify we have a float buffer */
- if (ibuf->rect_float == NULL || buffer == NULL) {
- return;
- }
-
- /* create byte rect if it didn't exist yet */
- if (ibuf->rect == NULL) {
- imb_addrectImBuf(ibuf);
- }
-
- /* do conversion */
- rect_float = ibuf->rect_float + (x + ((size_t)y) * ibuf->x) * ibuf->channels;
- rect_byte = (uchar *)ibuf->rect + (x + ((size_t)y) * ibuf->x) * 4;
-
- if (((size_t)w) * h < 64 * 64) {
- partial_rect_from_float_slice(buffer, rect_byte, ibuf, rect_float, w, h, is_data);
- }
- else {
- PartialThreadData data;
- data.ibuf = ibuf;
- data.buffer = buffer;
- data.rect_byte = rect_byte;
- data.rect_float = rect_float;
- data.width = w;
- data.is_data = is_data;
- IMB_processor_apply_threaded_scanlines(h, partial_rect_from_float_thread_do, &data);
- }
-
- /* ensure user flag is reset */
- ibuf->userflags &= ~IB_RECT_INVALID;
-}
-
void IMB_float_from_rect(ImBuf *ibuf)
{
float *rect_float;
@@ -914,7 +811,9 @@ void IMB_float_from_rect(ImBuf *ibuf)
rect_float, ibuf->x, ibuf->y, ibuf->channels, ibuf->rect_colorspace, false);
/* byte buffer is straight alpha, float should always be premul */
- IMB_premultiply_rect_float(rect_float, ibuf->channels, ibuf->x, ibuf->y);
+ if (IMB_alpha_affects_rgb(ibuf)) {
+ IMB_premultiply_rect_float(rect_float, ibuf->channels, ibuf->x, ibuf->y);
+ }
if (ibuf->rect_float == NULL) {
ibuf->rect_float = rect_float;
@@ -945,14 +844,6 @@ void IMB_color_to_bw(ImBuf *ibuf)
}
}
-void IMB_buffer_float_clamp(float *buf, int width, int height)
-{
- size_t i, total = ((size_t)width) * height * 4;
- for (i = 0; i < total; i++) {
- buf[i] = min_ff(1.0, buf[i]);
- }
-}
-
void IMB_buffer_float_unpremultiply(float *buf, int width, int height)
{
size_t total = ((size_t)width) * height;
diff --git a/source/blender/imbuf/intern/oiio/openimageio_api.cpp b/source/blender/imbuf/intern/oiio/openimageio_api.cpp
index 32079e4f290..7a47d0f7787 100644
--- a/source/blender/imbuf/intern/oiio/openimageio_api.cpp
+++ b/source/blender/imbuf/intern/oiio/openimageio_api.cpp
@@ -25,6 +25,7 @@
#if defined(WIN32)
# include "utfconv.h"
+# define _USE_MATH_DEFINES
#endif
// NOTE: Keep first, BLI_path_util conflicts with OIIO's format.
diff --git a/source/blender/imbuf/intern/readimage.c b/source/blender/imbuf/intern/readimage.c
index e1df5c63093..d9f3c7ec6bb 100644
--- a/source/blender/imbuf/intern/readimage.c
+++ b/source/blender/imbuf/intern/readimage.c
@@ -49,8 +49,6 @@ static void imb_handle_alpha(ImBuf *ibuf,
char colorspace[IM_MAX_SPACE],
char effective_colorspace[IM_MAX_SPACE])
{
- int alpha_flags;
-
if (colorspace) {
if (ibuf->rect != NULL && ibuf->rect_float == NULL) {
/* byte buffer is never internally converted to some standard space,
@@ -62,15 +60,17 @@ static void imb_handle_alpha(ImBuf *ibuf,
BLI_strncpy(colorspace, effective_colorspace, IM_MAX_SPACE);
}
- if (flags & IB_alphamode_detect) {
- alpha_flags = ibuf->flags & IB_alphamode_premul;
- }
- else {
- alpha_flags = flags & IB_alphamode_premul;
- }
+ bool is_data = (colorspace && IMB_colormanagement_space_name_is_data(colorspace));
+ int alpha_flags = (flags & IB_alphamode_detect) ? ibuf->flags : flags;
- if (flags & IB_ignore_alpha) {
+ if (is_data || (flags & IB_alphamode_channel_packed)) {
+ /* Don't touch alpha. */
+ ibuf->flags |= IB_alphamode_channel_packed;
+ }
+ else if (flags & IB_alphamode_ignore) {
+ /* Make opaque. */
IMB_rectfill_alpha(ibuf, 1.0f);
+ ibuf->flags |= IB_alphamode_ignore;
}
else {
if (alpha_flags & IB_alphamode_premul) {
diff --git a/source/blender/makesdna/DNA_genfile.h b/source/blender/makesdna/DNA_genfile.h
index 6a9d50ecc2d..dc4f5512b1a 100644
--- a/source/blender/makesdna/DNA_genfile.h
+++ b/source/blender/makesdna/DNA_genfile.h
@@ -121,4 +121,15 @@ bool DNA_sdna_patch_struct_member(struct SDNA *sdna,
void DNA_sdna_alias_data_ensure(struct SDNA *sdna);
+/* Alias lookups (using runtime struct member names). */
+int DNA_struct_alias_find_nr_ex(const struct SDNA *sdna,
+ const char *str,
+ unsigned int *index_last);
+int DNA_struct_alias_find_nr(const struct SDNA *sdna, const char *str);
+bool DNA_struct_alias_elem_find(const struct SDNA *sdna,
+ const char *stype,
+ const char *vartype,
+ const char *name);
+void DNA_sdna_alias_data_ensure_structs_map(struct SDNA *sdna);
+
#endif /* __DNA_GENFILE_H__ */
diff --git a/source/blender/makesdna/DNA_image_types.h b/source/blender/makesdna/DNA_image_types.h
index 3e42aa17492..6141472125f 100644
--- a/source/blender/makesdna/DNA_image_types.h
+++ b/source/blender/makesdna/DNA_image_types.h
@@ -178,7 +178,7 @@ enum {
/** For image user, but these flags are mixed. */
IMA_USER_FRAME_IN_RANGE = (1 << 10),
IMA_VIEW_AS_RENDER = (1 << 11),
- IMA_IGNORE_ALPHA = (1 << 12),
+ IMA_FLAG_UNUSED_12 = (1 << 12), /* cleared */
IMA_DEINTERLACE = (1 << 13),
IMA_USE_VIEWS = (1 << 14),
IMA_FLAG_UNUSED_15 = (1 << 15), /* cleared */
@@ -233,6 +233,8 @@ enum {
enum {
IMA_ALPHA_STRAIGHT = 0,
IMA_ALPHA_PREMUL = 1,
+ IMA_ALPHA_CHANNEL_PACKED = 2,
+ IMA_ALPHA_IGNORE = 3,
};
#endif
diff --git a/source/blender/makesdna/DNA_node_types.h b/source/blender/makesdna/DNA_node_types.h
index 3890fc63f3f..342641f00ac 100644
--- a/source/blender/makesdna/DNA_node_types.h
+++ b/source/blender/makesdna/DNA_node_types.h
@@ -161,8 +161,8 @@ typedef enum eNodeSocketDrawShape {
/* socket side (input/output) */
typedef enum eNodeSocketInOut {
- SOCK_IN = 1,
- SOCK_OUT = 2,
+ SOCK_IN = 1 << 0,
+ SOCK_OUT = 1 << 1,
} eNodeSocketInOut;
/* sock->flag, first bit is select */
diff --git a/source/blender/makesdna/DNA_object_types.h b/source/blender/makesdna/DNA_object_types.h
index 4287017543b..9bbb6f1656c 100644
--- a/source/blender/makesdna/DNA_object_types.h
+++ b/source/blender/makesdna/DNA_object_types.h
@@ -43,8 +43,8 @@ struct DerivedMesh;
struct FluidsimSettings;
struct GpencilBatchCache;
struct Ipo;
-struct Mesh;
struct Material;
+struct Mesh;
struct Object;
struct PartDeflect;
struct ParticleSystem;
diff --git a/source/blender/makesdna/DNA_scene_types.h b/source/blender/makesdna/DNA_scene_types.h
index 61fcb0c87d3..6813bc0e3aa 100644
--- a/source/blender/makesdna/DNA_scene_types.h
+++ b/source/blender/makesdna/DNA_scene_types.h
@@ -1443,8 +1443,9 @@ typedef struct ToolSettings {
/* Multires */
char multires_subdiv_type;
- /* Alt+RMB option */
+ /* Edge tagging, store operator settings (no UI access). */
char edge_mode;
+
char edge_mode_live_unwrap;
char _pad1[1];
@@ -1499,7 +1500,7 @@ typedef struct ToolSettings {
/* Normal Editing */
float normal_vector[3];
- int face_strength;
+ char _pad6[4];
} ToolSettings;
/* *************************************************************** */
@@ -2158,13 +2159,6 @@ enum {
OB_DRAW_GROUPUSER_ALL = 2,
};
-/* toolsettings->face_strength */
-enum {
- FACE_STRENGTH_WEAK = -16384,
- FACE_STRENGTH_MEDIUM = 0,
- FACE_STRENGTH_STRONG = 16384,
-};
-
/* object_vgroup.c */
/* ToolSettings.vgroupsubset */
typedef enum eVGroupSelect {
@@ -2316,14 +2310,6 @@ enum {
#define UV_SELECT_FACE 4
#define UV_SELECT_ISLAND 8
-/* ToolSettings.edge_mode */
-#define EDGE_MODE_SELECT 0
-#define EDGE_MODE_TAG_SEAM 1
-#define EDGE_MODE_TAG_SHARP 2
-#define EDGE_MODE_TAG_CREASE 3
-#define EDGE_MODE_TAG_BEVEL 4
-#define EDGE_MODE_TAG_FREESTYLE 5
-
/* ToolSettings.gpencil_flags */
typedef enum eGPencil_Flags {
/* When creating new frames, the last frame gets used as the basis for the new one */
diff --git a/source/blender/makesdna/DNA_sdna_types.h b/source/blender/makesdna/DNA_sdna_types.h
index 01e74da4e3b..efa7a308f88 100644
--- a/source/blender/makesdna/DNA_sdna_types.h
+++ b/source/blender/makesdna/DNA_sdna_types.h
@@ -35,7 +35,7 @@ typedef struct SDNA {
bool data_alloc;
/** Total number of struct members. */
- int nr_names, nr_names_alloc;
+ int names_len, names_len_alloc;
/** Struct member names. */
const char **names;
/** Result of #DNA_elem_array_size (aligned with #names). */
@@ -44,15 +44,14 @@ typedef struct SDNA {
/** Size of a pointer in bytes. */
int pointer_size;
- /** Number of basic types + struct types. */
- int nr_types;
/** Type names. */
const char **types;
+ /** Number of basic types + struct types. */
+ int types_len;
+
/** Type lengths. */
short *types_size;
- /** Number of struct types. */
- int nr_structs;
/**
* sp = structs[a] is the address of a struct definition
* sp[0] is struct type number, sp[1] amount of members
@@ -61,6 +60,8 @@ typedef struct SDNA {
* type and name numbers respectively.
*/
short **structs;
+ /** Number of struct types. */
+ int structs_len;
/** #GHash for faster lookups, requires WITH_DNA_GHASH to be used for now. */
struct GHash *structs_map;
@@ -74,6 +75,8 @@ typedef struct SDNA {
const char **names;
/** Aligned with #SDNA.types, same pointers when unchanged. */
const char **types;
+ /** A version of #SDNA.structs_map that uses #SDNA.alias.types for it's keys. */
+ struct GHash *structs_map;
} alias;
} SDNA;
diff --git a/source/blender/makesdna/DNA_userdef_types.h b/source/blender/makesdna/DNA_userdef_types.h
index 9cab63dbfeb..fa12de56364 100644
--- a/source/blender/makesdna/DNA_userdef_types.h
+++ b/source/blender/makesdna/DNA_userdef_types.h
@@ -283,7 +283,7 @@ typedef struct ThemeSpace {
char cframe[4];
char time_keyframe[4], time_gp_keyframe[4];
char freestyle_edge_mark[4], freestyle_face_mark[4];
- char scrubbing_background[4];
+ char time_scrub_background[4];
char _pad5[4];
char nurb_uline[4], nurb_vline[4];
diff --git a/source/blender/makesdna/DNA_view3d_types.h b/source/blender/makesdna/DNA_view3d_types.h
index d5ac8cc197b..0170b27e15f 100644
--- a/source/blender/makesdna/DNA_view3d_types.h
+++ b/source/blender/makesdna/DNA_view3d_types.h
@@ -584,9 +584,8 @@ enum {
/** Settings for offscreen rendering */
enum {
V3D_OFSDRAW_NONE = (0),
- V3D_OFSDRAW_USE_FULL_SAMPLE = (1 << 0),
- V3D_OFSDRAW_SHOW_ANNOTATION = (1 << 1),
- V3D_OFSDRAW_OVERRIDE_SCENE_SETTINGS = (1 << 2),
+ V3D_OFSDRAW_SHOW_ANNOTATION = (1 << 0),
+ V3D_OFSDRAW_OVERRIDE_SCENE_SETTINGS = (1 << 1),
};
#define RV3D_CAMZOOM_MIN -30
diff --git a/source/blender/makesdna/intern/dna_genfile.c b/source/blender/makesdna/intern/dna_genfile.c
index ad0765a58de..3cc005535b6 100644
--- a/source/blender/makesdna/intern/dna_genfile.c
+++ b/source/blender/makesdna/intern/dna_genfile.c
@@ -39,9 +39,7 @@
#include "BLI_memarena.h"
#include "BLI_string.h"
-#ifdef WITH_DNA_GHASH
-# include "BLI_ghash.h"
-#endif
+#include "BLI_ghash.h"
#include "DNA_genfile.h"
#include "DNA_sdna_types.h" // for SDNA ;-)
@@ -161,6 +159,11 @@ void DNA_sdna_free(SDNA *sdna)
MEM_SAFE_FREE(sdna->alias.names);
MEM_SAFE_FREE(sdna->alias.types);
+#ifdef WITH_DNA_GHASH
+ if (sdna->alias.structs_map) {
+ BLI_ghash_free(sdna->alias.structs_map, NULL, NULL);
+ }
+#endif
MEM_freeN(sdna);
}
@@ -222,49 +225,86 @@ static void printstruct(SDNA *sdna, short strnr)
/**
* Returns the index of the struct info for the struct with the specified name.
*/
-int DNA_struct_find_nr_ex(const SDNA *sdna, const char *str, unsigned int *index_last)
+static int dna_struct_find_nr_ex_impl(
+ /* From SDNA struct. */
+ const char **types,
+ const int UNUSED(types_len),
+ short **const structs,
+ const int structs_len,
+#ifdef WITH_DNA_GHASH
+ GHash *structs_map,
+#endif
+ /* Regular args. */
+ const char *str,
+ unsigned int *index_last)
{
- const short *sp = NULL;
-
- if (*index_last < sdna->nr_structs) {
- sp = sdna->structs[*index_last];
- if (strcmp(sdna->types[sp[0]], str) == 0) {
+ if (*index_last < structs_len) {
+ const short *sp = structs[*index_last];
+ if (STREQ(types[sp[0]], str)) {
return *index_last;
}
}
#ifdef WITH_DNA_GHASH
{
- void **index_p;
- int a;
-
- index_p = BLI_ghash_lookup_p(sdna->structs_map, str);
-
+ void **index_p = BLI_ghash_lookup_p(structs_map, str);
if (index_p) {
- a = POINTER_AS_INT(*index_p);
- *index_last = a;
- }
- else {
- a = -1;
+ const int index = POINTER_AS_INT(*index_p);
+ *index_last = index;
+ return index;
}
- return a;
}
#else
{
- int a;
-
- for (a = 0; a < sdna->nr_structs; a++) {
-
- sp = sdna->structs[a];
-
- if (strcmp(sdna->types[sp[0]], str) == 0) {
- *index_last = a;
- return a;
+ for (int index = 0; index < structs_len; index++) {
+ const short *sp = structs[index];
+ if (STREQ(types[sp[0]], str)) {
+ *index_last = index;
+ return index;
}
}
}
+#endif
return -1;
+}
+
+/**
+ * Returns the index of the struct info for the struct with the specified name.
+ */
+int DNA_struct_find_nr_ex(const SDNA *sdna, const char *str, unsigned int *index_last)
+{
+ return dna_struct_find_nr_ex_impl(
+ /* Expand SDNA. */
+ sdna->types,
+ sdna->types_len,
+ sdna->structs,
+ sdna->structs_len,
+#ifdef WITH_DNA_GHASH
+ sdna->structs_map,
#endif
+ /* Regular args. */
+ str,
+ index_last);
+}
+
+/** \note requires #DNA_sdna_alias_data_ensure_structs_map to be called. */
+int DNA_struct_alias_find_nr_ex(const SDNA *sdna, const char *str, unsigned int *index_last)
+{
+#ifdef WITH_DNA_GHASH
+ BLI_assert(sdna->alias.structs_map != NULL);
+#endif
+ return dna_struct_find_nr_ex_impl(
+ /* Expand SDNA. */
+ sdna->alias.types,
+ sdna->types_len,
+ sdna->structs,
+ sdna->structs_len,
+#ifdef WITH_DNA_GHASH
+ sdna->alias.structs_map,
+#endif
+ /* Regular args. */
+ str,
+ index_last);
}
int DNA_struct_find_nr(const SDNA *sdna, const char *str)
@@ -273,6 +313,13 @@ int DNA_struct_find_nr(const SDNA *sdna, const char *str)
return DNA_struct_find_nr_ex(sdna, str, &index_last_dummy);
}
+/** \note requires #DNA_sdna_alias_data_ensure_structs_map to be called. */
+int DNA_struct_alias_find_nr(const SDNA *sdna, const char *str)
+{
+ unsigned int index_last_dummy = UINT_MAX;
+ return DNA_struct_alias_find_nr_ex(sdna, str, &index_last_dummy);
+}
+
/* ************************* END DIV ********************** */
/* ************************* READ DNA ********************** */
@@ -317,14 +364,14 @@ static bool init_structDNA(SDNA *sdna, bool do_endian_swap, const char **r_error
if (*data == MAKE_ID('N', 'A', 'M', 'E')) {
data++;
- sdna->nr_names = *data;
+ sdna->names_len = *data;
if (do_endian_swap) {
- BLI_endian_switch_int32(&sdna->nr_names);
+ BLI_endian_switch_int32(&sdna->names_len);
}
- sdna->nr_names_alloc = sdna->nr_names;
+ sdna->names_len_alloc = sdna->names_len;
data++;
- sdna->names = MEM_callocN(sizeof(void *) * sdna->nr_names, "sdnanames");
+ sdna->names = MEM_callocN(sizeof(void *) * sdna->names_len, "sdnanames");
}
else {
*r_error_message = "NAME error in SDNA file";
@@ -332,7 +379,7 @@ static bool init_structDNA(SDNA *sdna, bool do_endian_swap, const char **r_error
}
cp = (char *)data;
- for (int nr = 0; nr < sdna->nr_names; nr++) {
+ for (int nr = 0; nr < sdna->names_len; nr++) {
sdna->names[nr] = cp;
/* "float gravity [3]" was parsed wrong giving both "gravity" and
@@ -357,13 +404,13 @@ static bool init_structDNA(SDNA *sdna, bool do_endian_swap, const char **r_error
if (*data == MAKE_ID('T', 'Y', 'P', 'E')) {
data++;
- sdna->nr_types = *data;
+ sdna->types_len = *data;
if (do_endian_swap) {
- BLI_endian_switch_int32(&sdna->nr_types);
+ BLI_endian_switch_int32(&sdna->types_len);
}
data++;
- sdna->types = MEM_callocN(sizeof(void *) * sdna->nr_types, "sdnatypes");
+ sdna->types = MEM_callocN(sizeof(void *) * sdna->types_len, "sdnatypes");
}
else {
*r_error_message = "TYPE error in SDNA file";
@@ -371,7 +418,7 @@ static bool init_structDNA(SDNA *sdna, bool do_endian_swap, const char **r_error
}
cp = (char *)data;
- for (int nr = 0; nr < sdna->nr_types; nr++) {
+ for (int nr = 0; nr < sdna->types_len; nr++) {
/* WARNING! See: DNA_struct_rename_legacy_hack_static_from_alias docs. */
sdna->types[nr] = DNA_struct_rename_legacy_hack_static_from_alias(cp);
while (*cp) {
@@ -390,17 +437,17 @@ static bool init_structDNA(SDNA *sdna, bool do_endian_swap, const char **r_error
sdna->types_size = sp;
if (do_endian_swap) {
- BLI_endian_switch_int16_array(sp, sdna->nr_types);
+ BLI_endian_switch_int16_array(sp, sdna->types_len);
}
- sp += sdna->nr_types;
+ sp += sdna->types_len;
}
else {
*r_error_message = "TLEN error in SDNA file";
return false;
}
/* prevent BUS error */
- if (sdna->nr_types & 1) {
+ if (sdna->types_len & 1) {
sp++;
}
@@ -409,13 +456,13 @@ static bool init_structDNA(SDNA *sdna, bool do_endian_swap, const char **r_error
if (*data == MAKE_ID('S', 'T', 'R', 'C')) {
data++;
- sdna->nr_structs = *data;
+ sdna->structs_len = *data;
if (do_endian_swap) {
- BLI_endian_switch_int32(&sdna->nr_structs);
+ BLI_endian_switch_int32(&sdna->structs_len);
}
data++;
- sdna->structs = MEM_callocN(sizeof(void *) * sdna->nr_structs, "sdnastrcs");
+ sdna->structs = MEM_callocN(sizeof(void *) * sdna->structs_len, "sdnastrcs");
}
else {
*r_error_message = "STRC error in SDNA file";
@@ -423,7 +470,7 @@ static bool init_structDNA(SDNA *sdna, bool do_endian_swap, const char **r_error
}
sp = (short *)data;
- for (int nr = 0; nr < sdna->nr_structs; nr++) {
+ for (int nr = 0; nr < sdna->structs_len; nr++) {
sdna->structs[nr] = sp;
if (do_endian_swap) {
@@ -449,7 +496,7 @@ static bool init_structDNA(SDNA *sdna, bool do_endian_swap, const char **r_error
{
/* second part of gravity problem, setting "gravity" type to void */
if (gravity_fix > -1) {
- for (int nr = 0; nr < sdna->nr_structs; nr++) {
+ for (int nr = 0; nr < sdna->structs_len; nr++) {
sp = sdna->structs[nr];
if (strcmp(sdna->types[sp[0]], "ClothSimSettings") == 0) {
sp[10] = SDNA_TYPE_VOID;
@@ -461,9 +508,9 @@ static bool init_structDNA(SDNA *sdna, bool do_endian_swap, const char **r_error
#ifdef WITH_DNA_GHASH
{
/* create a ghash lookup to speed up */
- sdna->structs_map = BLI_ghash_str_new_ex("init_structDNA gh", sdna->nr_structs);
+ sdna->structs_map = BLI_ghash_str_new_ex("init_structDNA gh", sdna->structs_len);
- for (intptr_t nr = 0; nr < sdna->nr_structs; nr++) {
+ for (intptr_t nr = 0; nr < sdna->structs_len; nr++) {
sp = sdna->structs[nr];
BLI_ghash_insert(sdna->structs_map, (void *)sdna->types[sp[0]], POINTER_FROM_INT(nr));
}
@@ -495,8 +542,8 @@ static bool init_structDNA(SDNA *sdna, bool do_endian_swap, const char **r_error
/* Cache name size. */
{
- short *names_array_len = MEM_mallocN(sizeof(*names_array_len) * sdna->nr_names, __func__);
- for (int i = 0; i < sdna->nr_names; i++) {
+ short *names_array_len = MEM_mallocN(sizeof(*names_array_len) * sdna->names_len, __func__);
+ for (int i = 0; i < sdna->names_len; i++) {
names_array_len[i] = DNA_elem_array_size(sdna->names[i]);
}
sdna->names_array_len = names_array_len;
@@ -586,7 +633,7 @@ static void recurs_test_compflags(const SDNA *sdna, char *compflags, int structn
sp = sdna->structs[structnr];
typenr = sp[0];
- for (a = 0; a < sdna->nr_structs; a++) {
+ for (a = 0; a < sdna->structs_len; a++) {
if ((a != structnr) && (compflags[a] == SDNA_CMP_EQUAL)) {
sp = sdna->structs[a];
elems = sp[1];
@@ -615,19 +662,19 @@ const char *DNA_struct_get_compareflags(const SDNA *oldsdna, const SDNA *newsdna
const char *str1, *str2;
char *compflags;
- if (oldsdna->nr_structs == 0) {
+ if (oldsdna->structs_len == 0) {
printf("error: file without SDNA\n");
return NULL;
}
- compflags = MEM_callocN(oldsdna->nr_structs, "compflags");
+ compflags = MEM_callocN(oldsdna->structs_len, "compflags");
/* we check all structs in 'oldsdna' and compare them with
* the structs in 'newsdna'
*/
unsigned int newsdna_index_last = 0;
- for (a = 0; a < oldsdna->nr_structs; a++) {
+ for (a = 0; a < oldsdna->structs_len; a++) {
sp_old = oldsdna->structs[a];
/* search for type in cur */
@@ -691,14 +738,14 @@ const char *DNA_struct_get_compareflags(const SDNA *oldsdna, const SDNA *newsdna
/* Because structs can be inside structs, we recursively
* set flags when a struct is altered
*/
- for (a = 0; a < oldsdna->nr_structs; a++) {
+ for (a = 0; a < oldsdna->structs_len; a++) {
if (compflags[a] == SDNA_CMP_NOT_EQUAL) {
recurs_test_compflags(oldsdna, compflags, a);
}
}
#if 0
- for (a = 0; a < oldsdna->nr_structs; a++) {
+ for (a = 0; a < oldsdna->structs_len; a++) {
if (compflags[a] == SDNA_CMP_NOT_EQUAL) {
spold = oldsdna->structs[a];
printf("changed: %s\n", oldsdna->types[spold[0]]);
@@ -922,7 +969,14 @@ static int elem_strcmp(const char *name, const char *oname)
* \param old: Pointer to struct information in sdna
* \return true when existing, false otherwise.
*/
-static bool elem_exists(const SDNA *sdna, const char *type, const char *name, const short *old)
+static bool elem_exists_impl(
+ /* Expand SDNA. */
+ const char **types,
+ const char **names,
+ /* Regular args. */
+ const char *type,
+ const char *name,
+ const short *old)
{
int a, elemcount;
const char *otype, *oname;
@@ -931,8 +985,8 @@ static bool elem_exists(const SDNA *sdna, const char *type, const char *name, co
elemcount = old[1];
old += 2;
for (a = 0; a < elemcount; a++, old += 2) {
- otype = sdna->types[old[0]];
- oname = sdna->names[old[1]];
+ otype = types[old[0]];
+ oname = names[old[1]];
if (elem_strcmp(name, oname) == 0) { /* name equal */
return strcmp(type, otype) == 0; /* type equal */
@@ -941,6 +995,33 @@ static bool elem_exists(const SDNA *sdna, const char *type, const char *name, co
return false;
}
+static bool elem_exists(const SDNA *sdna, const char *type, const char *name, const short *old)
+{
+ return elem_exists_impl(
+ /* Expand SDNA. */
+ sdna->types,
+ sdna->names,
+ /* Regular args. */
+ type,
+ name,
+ old);
+}
+
+static bool elem_exists_alias(const SDNA *sdna,
+ const char *type,
+ const char *name,
+ const short *old)
+{
+ return elem_exists_impl(
+ /* Expand SDNA. */
+ sdna->alias.types,
+ sdna->alias.names,
+ /* Regular args. */
+ type,
+ name,
+ old);
+}
+
/**
* Returns the address of the data for the specified field within olddata
* according to the struct format pointed to by old, or NULL if no such
@@ -1397,6 +1478,25 @@ bool DNA_struct_elem_find(const SDNA *sdna,
return false;
}
+/** \note requires #DNA_sdna_alias_data_ensure_structs_map to be called. */
+bool DNA_struct_alias_elem_find(const SDNA *sdna,
+ const char *stype,
+ const char *vartype,
+ const char *name)
+{
+ const int SDNAnr = DNA_struct_alias_find_nr(sdna, stype);
+
+ if (SDNAnr != -1) {
+ const short *const spo = sdna->structs[SDNAnr];
+ const bool found = elem_exists_alias(sdna, vartype, name, spo);
+
+ if (found) {
+ return true;
+ }
+ }
+ return false;
+}
+
/**
* Returns the size in bytes of a primitive type.
*/
@@ -1483,14 +1583,15 @@ static bool DNA_sdna_patch_struct_member_nr(SDNA *sdna,
strlen(elem_old_full),
elem_old_full_offset_start);
- if (sdna->nr_names == sdna->nr_names_alloc) {
- sdna->nr_names_alloc += 64;
- sdna->names = MEM_recallocN(sdna->names, sizeof(*sdna->names) * sdna->nr_names_alloc);
+ if (sdna->names_len == sdna->names_len_alloc) {
+ sdna->names_len_alloc += 64;
+ sdna->names = MEM_recallocN((void *)sdna->names,
+ sizeof(*sdna->names) * sdna->names_len_alloc);
sdna->names_array_len = MEM_recallocN(
- (void *)sdna->names_array_len, sizeof(*sdna->names_array_len) * sdna->nr_names_alloc);
+ (void *)sdna->names_array_len, sizeof(*sdna->names_array_len) * sdna->names_len_alloc);
}
const short name_nr_prev = sp[1];
- sp[1] = sdna->nr_names++;
+ sp[1] = sdna->names_len++;
sdna->names[sp[1]] = elem_new_full;
sdna->names_array_len[sp[1]] = sdna->names_array_len[name_nr_prev];
@@ -1533,14 +1634,14 @@ bool DNA_sdna_patch_struct_member(SDNA *sdna,
static void sdna_expand_names(SDNA *sdna)
{
int names_expand_len = 0;
- for (int struct_nr = 0; struct_nr < sdna->nr_structs; struct_nr++) {
+ for (int struct_nr = 0; struct_nr < sdna->structs_len; struct_nr++) {
const short *sp = sdna->structs[struct_nr];
names_expand_len += sp[1];
}
const char **names_expand = MEM_mallocN(sizeof(*names_expand) * names_expand_len, __func__);
int names_expand_index = 0;
- for (int struct_nr = 0; struct_nr < sdna->nr_structs; struct_nr++) {
+ for (int struct_nr = 0; struct_nr < sdna->structs_len; struct_nr++) {
/* We can't edit this memory 'sdna->structs' points to (readonly datatoc file). */
const short *sp = sdna->structs[struct_nr];
short *sp_expand = BLI_memarena_alloc(sdna->mem_arena, sizeof(short[2]) * (1 + sp[1]));
@@ -1558,13 +1659,13 @@ static void sdna_expand_names(SDNA *sdna)
}
MEM_freeN((void *)sdna->names);
sdna->names = names_expand;
- sdna->nr_names = names_expand_len;
+ sdna->names_len = names_expand_len;
}
-static const char *dna_sdna_alias_alias_from_static_elem_full(SDNA *sdna,
- GHash *elem_map_alias_from_static,
- const char *struct_name_static,
- const char *elem_static_full)
+static const char *dna_sdna_alias_from_static_elem_full(SDNA *sdna,
+ GHash *elem_map_alias_from_static,
+ const char *struct_name_static,
+ const char *elem_static_full)
{
const int elem_static_full_len = strlen(elem_static_full);
char *elem_static = alloca(elem_static_full_len + 1);
@@ -1600,8 +1701,8 @@ void DNA_sdna_alias_data_ensure(SDNA *sdna)
DNA_RENAME_ALIAS_FROM_STATIC, &struct_map_alias_from_static, &elem_map_alias_from_static);
if (sdna->alias.types == NULL) {
- sdna->alias.types = MEM_mallocN(sizeof(*sdna->alias.types) * sdna->nr_types, __func__);
- for (int type_nr = 0; type_nr < sdna->nr_types; type_nr++) {
+ sdna->alias.types = MEM_mallocN(sizeof(*sdna->alias.types) * sdna->types_len, __func__);
+ for (int type_nr = 0; type_nr < sdna->types_len; type_nr++) {
const char *struct_name_static = sdna->types[type_nr];
if (use_legacy_hack) {
@@ -1615,8 +1716,8 @@ void DNA_sdna_alias_data_ensure(SDNA *sdna)
if (sdna->alias.names == NULL) {
sdna_expand_names(sdna);
- sdna->alias.names = MEM_mallocN(sizeof(*sdna->alias.names) * sdna->nr_names, __func__);
- for (int struct_nr = 0; struct_nr < sdna->nr_structs; struct_nr++) {
+ sdna->alias.names = MEM_mallocN(sizeof(*sdna->alias.names) * sdna->names_len, __func__);
+ for (int struct_nr = 0; struct_nr < sdna->structs_len; struct_nr++) {
const short *sp = sdna->structs[struct_nr];
const char *struct_name_static = sdna->types[sp[0]];
@@ -1627,7 +1728,7 @@ void DNA_sdna_alias_data_ensure(SDNA *sdna)
const int dna_struct_names_len = sp[1];
sp += 2;
for (int a = 0; a < dna_struct_names_len; a++, sp += 2) {
- const char *elem_alias_full = dna_sdna_alias_alias_from_static_elem_full(
+ const char *elem_alias_full = dna_sdna_alias_from_static_elem_full(
sdna, elem_map_alias_from_static, struct_name_static, sdna->names[sp[1]]);
if (elem_alias_full != NULL) {
sdna->alias.names[sp[1]] = elem_alias_full;
@@ -1642,4 +1743,24 @@ void DNA_sdna_alias_data_ensure(SDNA *sdna)
BLI_ghash_free(elem_map_alias_from_static, MEM_freeN, NULL);
}
+/**
+ * Separated from #DNA_sdna_alias_data_ensure because it's not needed
+ * unless we want to lookup aliased struct names (#DNA_struct_alias_find_nr and friends).
+ */
+void DNA_sdna_alias_data_ensure_structs_map(SDNA *sdna)
+{
+ DNA_sdna_alias_data_ensure(sdna);
+#ifdef WITH_DNA_GHASH
+ /* create a ghash lookup to speed up */
+ struct GHash *structs_map = BLI_ghash_str_new_ex(__func__, sdna->structs_len);
+ for (intptr_t nr = 0; nr < sdna->structs_len; nr++) {
+ const short *sp = sdna->structs[nr];
+ BLI_ghash_insert(structs_map, (void *)sdna->alias.types[sp[0]], POINTER_FROM_INT(nr));
+ }
+ sdna->alias.structs_map = structs_map;
+#else
+ UNUSED_VARS(sdna);
+#endif
+}
+
/** \} */
diff --git a/source/blender/makesdna/intern/dna_rename_defs.h b/source/blender/makesdna/intern/dna_rename_defs.h
index 3aa0ff4b28a..0bc35c15e35 100644
--- a/source/blender/makesdna/intern/dna_rename_defs.h
+++ b/source/blender/makesdna/intern/dna_rename_defs.h
@@ -75,6 +75,7 @@ DNA_STRUCT_RENAME_ELEM(Object, size, scale)
DNA_STRUCT_RENAME_ELEM(ParticleSettings, dup_group, instance_collection)
DNA_STRUCT_RENAME_ELEM(ParticleSettings, dup_ob, instance_object)
DNA_STRUCT_RENAME_ELEM(ParticleSettings, dupliweights, instance_weights)
+DNA_STRUCT_RENAME_ELEM(ThemeSpace, scrubbing_background, time_scrub_background)
DNA_STRUCT_RENAME_ELEM(View3D, far, clip_end)
DNA_STRUCT_RENAME_ELEM(View3D, near, clip_start)
DNA_STRUCT_RENAME_ELEM(bPoseChannel, curveInX, curve_in_x)
diff --git a/source/blender/makesdna/intern/dna_utils.c b/source/blender/makesdna/intern/dna_utils.c
index 425deaf121f..c402b36812b 100644
--- a/source/blender/makesdna/intern/dna_utils.c
+++ b/source/blender/makesdna/intern/dna_utils.c
@@ -265,7 +265,7 @@ void DNA_alias_maps(enum eDNA_RenameDir version_dir, GHash **r_struct_map, GHash
const char **str_pair = MEM_mallocN(sizeof(char *) * 2, __func__);
str_pair[0] = BLI_ghash_lookup_default(struct_map_local, data[i][0], (void *)data[i][0]);
str_pair[1] = data[i][elem_key];
- BLI_ghash_insert(elem_map, str_pair, (void *)data[i][elem_val]);
+ BLI_ghash_insert(elem_map, (void *)str_pair, (void *)data[i][elem_val]);
}
*r_elem_map = elem_map;
}
diff --git a/source/blender/makesdna/intern/makesdna.c b/source/blender/makesdna/intern/makesdna.c
index 2e94c29a825..c0859a7d4ce 100644
--- a/source/blender/makesdna/intern/makesdna.c
+++ b/source/blender/makesdna/intern/makesdna.c
@@ -145,10 +145,10 @@ static const char *includefiles[] = {
static MemArena *mem_arena = NULL;
-static int maxdata = 500000, maxnr = 50000;
-static int nr_names = 0;
-static int nr_types = 0;
-static int nr_structs = 0;
+static int max_data_size = 500000, max_array_len = 50000;
+static int names_len = 0;
+static int types_len = 0;
+static int structs_len = 0;
/** At address `names[a]` is string `a`. */
static char **names;
/** At address `types[a]` is string `a`. */
@@ -162,7 +162,7 @@ static short *types_size_64;
/** At `sp = structs[a]` is the first address of a struct definition:
* - `sp[0]` is type number.
* - `sp[1]` is the length of the element array (next).
- * - `sp[2]` sp[3] is [(type_nr, name_nr), ..] (number of pairs is defined by `sp[1]`),
+ * - `sp[2]` sp[3] is [(type_index, name_index), ..] (number of pairs is defined by `sp[1]`),
*/
static short **structs, *structdata;
@@ -345,7 +345,6 @@ static bool is_name_legal(const char *name)
static int add_type(const char *str, int size)
{
- int nr;
char *cp;
/* first do validity check */
@@ -361,14 +360,14 @@ static int add_type(const char *str, int size)
str = version_struct_static_from_alias(str);
/* search through type array */
- for (nr = 0; nr < nr_types; nr++) {
- if (strcmp(str, types[nr]) == 0) {
+ for (int index = 0; index < types_len; index++) {
+ if (strcmp(str, types[index]) == 0) {
if (size) {
- types_size_native[nr] = size;
- types_size_32[nr] = size;
- types_size_64[nr] = size;
+ types_size_native[index] = size;
+ types_size_32[index] = size;
+ types_size_64[index] = size;
}
- return nr;
+ return index;
}
}
@@ -376,18 +375,18 @@ static int add_type(const char *str, int size)
const int str_size = strlen(str) + 1;
cp = BLI_memarena_alloc(mem_arena, str_size);
memcpy(cp, str, str_size);
- types[nr_types] = cp;
- types_size_native[nr_types] = size;
- types_size_32[nr_types] = size;
- types_size_64[nr_types] = size;
+ types[types_len] = cp;
+ types_size_native[types_len] = size;
+ types_size_32[types_len] = size;
+ types_size_64[types_len] = size;
- if (nr_types >= maxnr) {
+ if (types_len >= max_array_len) {
printf("too many types\n");
- return nr_types - 1;
+ return types_len - 1;
}
- nr_types++;
+ types_len++;
- return nr_types - 1;
+ return types_len - 1;
}
/**
@@ -514,7 +513,7 @@ static int add_name(const char *str)
}
/* search name array */
- for (nr = 0; nr < nr_names; nr++) {
+ for (nr = 0; nr < names_len; nr++) {
if (strcmp(name, names[nr]) == 0) {
return nr;
}
@@ -529,15 +528,15 @@ static int add_name(const char *str)
const int name_size = strlen(name) + 1;
cp = BLI_memarena_alloc(mem_arena, name_size);
memcpy(cp, name, name_size);
- names[nr_names] = cp;
+ names[names_len] = cp;
- if (nr_names >= maxnr) {
+ if (names_len >= max_array_len) {
printf("too many names\n");
- return nr_names - 1;
+ return names_len - 1;
}
- nr_names++;
+ names_len++;
- return nr_names - 1;
+ return names_len - 1;
}
static short *add_struct(int namecode)
@@ -545,23 +544,23 @@ static short *add_struct(int namecode)
int len;
short *sp;
- if (nr_structs == 0) {
+ if (structs_len == 0) {
structs[0] = structdata;
}
else {
- sp = structs[nr_structs - 1];
+ sp = structs[structs_len - 1];
len = sp[1];
- structs[nr_structs] = sp + 2 * len + 2;
+ structs[structs_len] = sp + 2 * len + 2;
}
- sp = structs[nr_structs];
+ sp = structs[structs_len];
sp[0] = namecode;
- if (nr_structs >= maxnr) {
+ if (structs_len >= max_array_len) {
printf("too many structs\n");
return sp;
}
- nr_structs++;
+ structs_len++;
return sp;
}
@@ -897,7 +896,7 @@ static bool check_field_alignment(
static int calculate_struct_sizes(int firststruct, FILE *file_verify, const char *base_directory)
{
- int unknown = nr_structs, lastunknown;
+ int unknown = structs_len, lastunknown;
bool dna_error = false;
/* Write test to verify sizes are accurate. */
@@ -915,7 +914,7 @@ static int calculate_struct_sizes(int firststruct, FILE *file_verify, const char
unknown = 0;
/* check all structs... */
- for (int a = 0; a < nr_structs; a++) {
+ for (int a = 0; a < structs_len; a++) {
const short *structpoin = structs[a];
const int structtype = structpoin[0];
const char *structname = version_struct_alias_from_static(types[structtype]);
@@ -1100,7 +1099,7 @@ static int calculate_struct_sizes(int firststruct, FILE *file_verify, const char
if (debugSDNA) {
fprintf(stderr, "*** Known structs :\n");
- for (int a = 0; a < nr_structs; a++) {
+ for (int a = 0; a < structs_len; a++) {
const short *structpoin = structs[a];
const int structtype = structpoin[0];
@@ -1113,7 +1112,7 @@ static int calculate_struct_sizes(int firststruct, FILE *file_verify, const char
fprintf(stderr, "*** Unknown structs :\n");
- for (int a = 0; a < nr_structs; a++) {
+ for (int a = 0; a < structs_len; a++) {
const short *structpoin = structs[a];
const int structtype = structpoin[0];
@@ -1151,7 +1150,7 @@ static void dna_write(FILE *file, const void *pntr, const int size)
void print_struct_sizes(void)
{
- int a, unknown = nr_structs, structtype;
+ int a, unknown = structs_len, structtype;
/*int lastunknown;*/ /*UNUSED*/
const short *structpoin;
printf("\n\n*** All detected structs:\n");
@@ -1161,7 +1160,7 @@ void print_struct_sizes(void)
unknown = 0;
/* check all structs... */
- for (a = 0; a < nr_structs; a++) {
+ for (a = 0; a < structs_len; a++) {
structpoin = structs[a];
structtype = structpoin[0];
printf("\t%s\t:%d\n", types[structtype], types_size_native[structtype]);
@@ -1191,15 +1190,15 @@ static int make_structDNA(const char *base_directory,
mem_arena = BLI_memarena_new(BLI_MEMARENA_STD_BUFSIZE, __func__);
/* the longest known struct is 50k, so we assume 100k is sufficient! */
- structdata = MEM_callocN(maxdata, "structdata");
+ structdata = MEM_callocN(max_data_size, "structdata");
/* a maximum of 5000 variables, must be sufficient? */
- names = MEM_callocN(sizeof(char *) * maxnr, "names");
- types = MEM_callocN(sizeof(char *) * maxnr, "types");
- types_size_native = MEM_callocN(sizeof(short) * maxnr, "types_size_native");
- types_size_32 = MEM_callocN(sizeof(short) * maxnr, "types_size_32");
- types_size_64 = MEM_callocN(sizeof(short) * maxnr, "types_size_64");
- structs = MEM_callocN(sizeof(short *) * maxnr, "structs");
+ names = MEM_callocN(sizeof(char *) * max_array_len, "names");
+ types = MEM_callocN(sizeof(char *) * max_array_len, "types");
+ types_size_native = MEM_callocN(sizeof(short) * max_array_len, "types_size_native");
+ types_size_32 = MEM_callocN(sizeof(short) * max_array_len, "types_size_32");
+ types_size_64 = MEM_callocN(sizeof(short) * max_array_len, "types_size_64");
+ structs = MEM_callocN(sizeof(short *) * max_array_len, "structs");
/* Build versioning data */
DNA_alias_maps(DNA_RENAME_ALIAS_FROM_STATIC,
@@ -1234,7 +1233,7 @@ static int make_structDNA(const char *base_directory,
add_type("void", 0); /* SDNA_TYPE_VOID */
/* the defines above shouldn't be output in the padding file... */
- firststruct = nr_types;
+ firststruct = types_len;
/* add all include files defined in the global array */
/* Since the internal file+path name buffer has limited length, I do a */
@@ -1261,19 +1260,19 @@ static int make_structDNA(const char *base_directory,
/* short *elem; */
short num_types;
- printf("nr_names %d nr_types %d nr_structs %d\n", nr_names, nr_types, nr_structs);
- for (a = 0; a < nr_names; a++) {
+ printf("names_len %d types_len %d structs_len %d\n", names_len, types_len, structs_len);
+ for (a = 0; a < names_len; a++) {
printf(" %s\n", names[a]);
}
printf("\n");
sp = types_size_native;
- for (a = 0; a < nr_types; a++, sp++) {
+ for (a = 0; a < types_len; a++, sp++) {
printf(" %s %d\n", types[a], *sp);
}
printf("\n");
- for (a = 0; a < nr_structs; a++) {
+ for (a = 0; a < structs_len; a++) {
sp = structs[a];
printf(" struct %s elems: %d size: %d\n", types[sp[0]], sp[1], types_size_native[sp[0]]);
num_types = sp[1];
@@ -1289,7 +1288,7 @@ static int make_structDNA(const char *base_directory,
DEBUG_PRINTF(0, "Writing file ... ");
- if (nr_names == 0 || nr_structs == 0) {
+ if (names_len == 0 || structs_len == 0) {
/* pass */
}
else {
@@ -1300,11 +1299,11 @@ static int make_structDNA(const char *base_directory,
/* write names */
dna_write(file, "NAME", 4);
- len = nr_names;
+ len = names_len;
dna_write(file, &len, 4);
/* write array */
len = 0;
- for (int nr = 0; nr < nr_names; nr++) {
+ for (int nr = 0; nr < names_len; nr++) {
int name_size = strlen(names[nr]) + 1;
dna_write(file, names[nr], name_size);
len += name_size;
@@ -1316,11 +1315,11 @@ static int make_structDNA(const char *base_directory,
/* write TYPES */
dna_write(file, "TYPE", 4);
- len = nr_types;
+ len = types_len;
dna_write(file, &len, 4);
/* write array */
len = 0;
- for (int nr = 0; nr < nr_types; nr++) {
+ for (int nr = 0; nr < types_len; nr++) {
int type_size = strlen(types[nr]) + 1;
dna_write(file, types[nr], type_size);
len += type_size;
@@ -1333,19 +1332,19 @@ static int make_structDNA(const char *base_directory,
/* WRITE TYPELENGTHS */
dna_write(file, "TLEN", 4);
- len = 2 * nr_types;
- if (nr_types & 1) {
+ len = 2 * types_len;
+ if (types_len & 1) {
len += 2;
}
dna_write(file, types_size_native, len);
/* WRITE STRUCTS */
dna_write(file, "STRC", 4);
- len = nr_structs;
+ len = structs_len;
dna_write(file, &len, 4);
/* calc datablock size */
- sp = structs[nr_structs - 1];
+ sp = structs[structs_len - 1];
sp += 2 + 2 * (sp[1]);
len = (intptr_t)((char *)sp - (char *)structs[0]);
len = (len + 3) & ~3;
@@ -1358,7 +1357,7 @@ static int make_structDNA(const char *base_directory,
{
fprintf(file_offsets, "#define SDNA_TYPE_FROM_STRUCT(id) _SDNA_TYPE_##id\n");
fprintf(file_offsets, "enum {\n");
- for (i = 0; i < nr_structs; i++) {
+ for (i = 0; i < structs_len; i++) {
const short *structpoin = structs[i];
const int structtype = structpoin[0];
fprintf(file_offsets,
@@ -1366,7 +1365,7 @@ static int make_structDNA(const char *base_directory,
version_struct_alias_from_static(types[structtype]),
i);
}
- fprintf(file_offsets, "\tSDNA_TYPE_MAX = %d,\n", nr_structs);
+ fprintf(file_offsets, "\tSDNA_TYPE_MAX = %d,\n", structs_len);
fprintf(file_offsets, "};\n\n");
}
@@ -1374,7 +1373,7 @@ static int make_structDNA(const char *base_directory,
* do last because names are stripped. */
{
GSet *names_unique = BLI_gset_str_new_ex(__func__, 512);
- for (int struct_nr = 0; struct_nr < nr_structs; struct_nr++) {
+ for (int struct_nr = 0; struct_nr < structs_len; struct_nr++) {
sp = structs[struct_nr];
const char *struct_name = types[sp[0]];
const int len = sp[1];
diff --git a/source/blender/makesrna/RNA_access.h b/source/blender/makesrna/RNA_access.h
index 40b0b7cc324..47958c2a68e 100644
--- a/source/blender/makesrna/RNA_access.h
+++ b/source/blender/makesrna/RNA_access.h
@@ -728,6 +728,7 @@ extern StructRNA RNA_View3DOverlay;
extern StructRNA RNA_View3DShading;
extern StructRNA RNA_ViewLayer;
extern StructRNA RNA_VoronoiTexture;
+extern StructRNA RNA_WalkNavigation;
extern StructRNA RNA_WarpModifier;
extern StructRNA RNA_WaveModifier;
extern StructRNA RNA_WeightedNormalModifier;
@@ -1033,12 +1034,12 @@ void *RNA_property_enum_py_data_get(PropertyRNA *prop);
int RNA_property_enum_step(
const struct bContext *C, PointerRNA *ptr, PropertyRNA *prop, int from_value, int step);
-PointerRNA RNA_property_pointer_get(PointerRNA *ptr, PropertyRNA *prop);
-void RNA_property_pointer_set(struct ReportList *reports,
- PointerRNA *ptr,
+PointerRNA RNA_property_pointer_get(PointerRNA *ptr, PropertyRNA *prop) ATTR_NONNULL(1, 2);
+void RNA_property_pointer_set(PointerRNA *ptr,
PropertyRNA *prop,
- PointerRNA ptr_value);
-PointerRNA RNA_property_pointer_get_default(PointerRNA *ptr, PropertyRNA *prop);
+ PointerRNA ptr_value,
+ struct ReportList *reports) ATTR_NONNULL(1, 2);
+PointerRNA RNA_property_pointer_get_default(PointerRNA *ptr, PropertyRNA *prop) ATTR_NONNULL(1, 2);
void RNA_property_collection_begin(PointerRNA *ptr,
PropertyRNA *prop,
diff --git a/source/blender/makesrna/RNA_define.h b/source/blender/makesrna/RNA_define.h
index 59c03cf34b3..0beb14614ec 100644
--- a/source/blender/makesrna/RNA_define.h
+++ b/source/blender/makesrna/RNA_define.h
@@ -48,6 +48,7 @@ void RNA_define_free(BlenderRNA *brna);
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_init(void);
void RNA_exit(void);
diff --git a/source/blender/makesrna/intern/makesrna.c b/source/blender/makesrna/intern/makesrna.c
index a3a18be71d1..7768298b2c5 100644
--- a/source/blender/makesrna/intern/makesrna.c
+++ b/source/blender/makesrna/intern/makesrna.c
@@ -567,7 +567,7 @@ static int rna_color_quantize(PropertyRNA *prop, PropertyDefRNA *dp)
(IS_DNATYPE_FLOAT_COMPAT(dp->dnatype) == 0));
}
-static const char *rna_function_string(void *func)
+static const char *rna_function_string(const void *func)
{
return (func) ? (const char *)func : "NULL";
}
@@ -1033,10 +1033,10 @@ static char *rna_def_property_set_func(
break;
}
case PROP_POINTER: {
- fprintf(f, "void %s(struct ReportList *reports, PointerRNA *ptr, PointerRNA value)\n", func);
+ fprintf(f, "void %s(PointerRNA *ptr, PointerRNA value, struct ReportList *reports)\n", func);
fprintf(f, "{\n");
if (manualfunc) {
- fprintf(f, " %s(reports, ptr, value);\n", manualfunc);
+ fprintf(f, " %s(ptr, value, reports);\n", manualfunc);
}
else {
rna_print_data_get(f, dp);
diff --git a/source/blender/makesrna/intern/rna_ID.c b/source/blender/makesrna/intern/rna_ID.c
index 97d3d03468b..7e6a3e70b9d 100644
--- a/source/blender/makesrna/intern/rna_ID.c
+++ b/source/blender/makesrna/intern/rna_ID.c
@@ -463,7 +463,7 @@ static ID *rna_ID_override_create(ID *id, Main *bmain)
return BKE_override_static_create_from_id(bmain, id);
}
-static void rna_ID_update_tag(ID *id, ReportList *reports, int flag)
+static void rna_ID_update_tag(ID *id, Main *bmain, ReportList *reports, int flag)
{
/* XXX, new function for this! */
# if 0
@@ -478,6 +478,8 @@ static void rna_ID_update_tag(ID *id, ReportList *reports, int flag)
/* pass */
}
else {
+ int allow_flag = 0;
+
/* ensure flag us correct for the type */
switch (GS(id->name)) {
case ID_OB:
@@ -485,28 +487,35 @@ static void rna_ID_update_tag(ID *id, ReportList *reports, int flag)
* object types supports different flags. Maybe does not worth checking
* for this at all. Or maybe let dependency graph to return whether
* the tag was valid or not. */
- if (flag & ~(ID_RECALC_ALL)) {
- BKE_report(reports, RPT_ERROR, "'Refresh' incompatible with Object ID type");
- return;
- }
+ allow_flag = ID_RECALC_ALL;
break;
/* Could add particle updates later */
# if 0
case ID_PA:
- if (flag & ~(OB_RECALC_ALL | PSYS_RECALC)) {
- BKE_report(reports, RPT_ERROR, "'Refresh' incompatible with ParticleSettings ID type");
- return;
- }
+ allow_flag = OB_RECALC_ALL | PSYS_RECALC;
break;
# endif
+ case ID_AC:
+ allow_flag = ID_RECALC_ANIMATION;
+ break;
default:
- BKE_report(
- reports, RPT_ERROR, "This ID type is not compatible with any 'refresh' options");
- return;
+ if (id_can_have_animdata(id)) {
+ allow_flag = ID_RECALC_ANIMATION;
+ }
+ }
+
+ if (flag & ~allow_flag) {
+ StructRNA *srna = ID_code_to_RNA_type(GS(id->name));
+ BKE_reportf(reports,
+ RPT_ERROR,
+ "%s is not compatible with %s 'refresh' options",
+ RNA_struct_identifier(srna),
+ allow_flag ? "the specified" : "any");
+ return;
}
}
- DEG_id_tag_update(id, flag);
+ DEG_id_tag_update_ex(bmain, id, flag);
}
static void rna_ID_user_clear(ID *id)
@@ -1531,7 +1540,7 @@ static void rna_def_ID(BlenderRNA *brna)
RNA_def_function_ui_description(func, "Clear animation on this this ID");
func = RNA_def_function(srna, "update_tag", "rna_ID_update_tag");
- RNA_def_function_flag(func, FUNC_USE_REPORTS);
+ RNA_def_function_flag(func, FUNC_USE_MAIN | FUNC_USE_REPORTS);
RNA_def_function_ui_description(func,
"Tag the ID to update its display data, "
"e.g. when calling :class:`bpy.types.Scene.update`");
diff --git a/source/blender/makesrna/intern/rna_access.c b/source/blender/makesrna/intern/rna_access.c
index b56a031f9df..20358ca80fd 100644
--- a/source/blender/makesrna/intern/rna_access.c
+++ b/source/blender/makesrna/intern/rna_access.c
@@ -3733,10 +3733,10 @@ PointerRNA RNA_property_pointer_get(PointerRNA *ptr, PropertyRNA *prop)
}
}
-void RNA_property_pointer_set(ReportList *reports,
- PointerRNA *ptr,
+void RNA_property_pointer_set(PointerRNA *ptr,
PropertyRNA *prop,
- PointerRNA ptr_value)
+ PointerRNA ptr_value,
+ ReportList *reports)
{
PointerPropertyRNA *pprop = (PointerPropertyRNA *)prop;
BLI_assert(RNA_property_type(prop) == PROP_POINTER);
@@ -3755,7 +3755,7 @@ void RNA_property_pointer_set(ReportList *reports,
/* RNA */
if (pprop->set && !((prop->flag & PROP_NEVER_NULL) && ptr_value.data == NULL) &&
!((prop->flag & PROP_ID_SELF_CHECK) && ptr->id.data == ptr_value.id.data)) {
- pprop->set(reports, ptr, ptr_value);
+ pprop->set(ptr, ptr_value, reports);
}
/* IDProperty */
else if (prop->flag & PROP_EDITABLE) {
@@ -6427,7 +6427,7 @@ void RNA_pointer_set(PointerRNA *ptr, const char *name, PointerRNA ptr_value)
PropertyRNA *prop = RNA_struct_find_property(ptr, name);
if (prop) {
- RNA_property_pointer_set(NULL, ptr, prop, ptr_value);
+ RNA_property_pointer_set(ptr, prop, ptr_value, NULL);
}
else {
printf("%s: %s.%s not found.\n", __func__, ptr->type->identifier, name);
@@ -7976,7 +7976,7 @@ bool RNA_property_reset(PointerRNA *ptr, PropertyRNA *prop, int index)
case PROP_POINTER: {
PointerRNA value = RNA_property_pointer_get_default(ptr, prop);
- RNA_property_pointer_set(NULL, ptr, prop, value);
+ RNA_property_pointer_set(ptr, prop, value, NULL);
return true;
}
diff --git a/source/blender/makesrna/intern/rna_action.c b/source/blender/makesrna/intern/rna_action.c
index e99a1ffe2be..4e98db21089 100644
--- a/source/blender/makesrna/intern/rna_action.c
+++ b/source/blender/makesrna/intern/rna_action.c
@@ -214,9 +214,9 @@ static PointerRNA rna_Action_active_pose_marker_get(PointerRNA *ptr)
ptr, &RNA_TimelineMarker, BLI_findlink(&act->markers, act->active_marker - 1));
}
-static void rna_Action_active_pose_marker_set(struct ReportList *UNUSED(reports),
- PointerRNA *ptr,
- PointerRNA value)
+static void rna_Action_active_pose_marker_set(PointerRNA *ptr,
+ PointerRNA value,
+ struct ReportList *UNUSED(reports))
{
bAction *act = (bAction *)ptr->data;
act->active_marker = BLI_findindex(&act->markers, value.data) + 1;
@@ -341,7 +341,7 @@ static void rna_def_dopesheet(BlenderRNA *brna)
RNA_def_property_boolean_sdna(prop, NULL, "filterflag", ADS_FILTER_INCL_HIDDEN);
RNA_def_property_ui_text(
prop, "Display Hidden", "Include channels from objects/bone that are not visible");
- RNA_def_property_ui_icon(prop, ICON_GHOST_ENABLED, 0);
+ RNA_def_property_ui_icon(prop, ICON_OBJECT_HIDDEN, 0);
RNA_def_property_update(prop, NC_ANIMATION | ND_ANIMCHAN | NA_EDITED, NULL);
prop = RNA_def_property(srna, "use_datablock_sort", PROP_BOOLEAN, PROP_NONE);
diff --git a/source/blender/makesrna/intern/rna_animation.c b/source/blender/makesrna/intern/rna_animation.c
index ba7929521f9..6228414e4f4 100644
--- a/source/blender/makesrna/intern/rna_animation.c
+++ b/source/blender/makesrna/intern/rna_animation.c
@@ -151,9 +151,9 @@ static int rna_AnimData_action_editable(PointerRNA *ptr, const char **UNUSED(r_i
return PROP_EDITABLE;
}
-static void rna_AnimData_action_set(struct ReportList *UNUSED(reports),
- PointerRNA *ptr,
- PointerRNA value)
+static void rna_AnimData_action_set(PointerRNA *ptr,
+ PointerRNA value,
+ struct ReportList *UNUSED(reports))
{
ID *ownerId = (ID *)ptr->id.data;
@@ -463,9 +463,9 @@ static PointerRNA rna_KeyingSet_active_ksPath_get(PointerRNA *ptr)
ptr, &RNA_KeyingSetPath, BLI_findlink(&ks->paths, ks->active_path - 1));
}
-static void rna_KeyingSet_active_ksPath_set(struct ReportList *UNUSED(reports),
- PointerRNA *ptr,
- PointerRNA value)
+static void rna_KeyingSet_active_ksPath_set(PointerRNA *ptr,
+ PointerRNA value,
+ struct ReportList *UNUSED(reports))
{
KeyingSet *ks = (KeyingSet *)ptr->data;
KS_Path *ksp = (KS_Path *)value.data;
@@ -616,9 +616,9 @@ static PointerRNA rna_NlaTrack_active_get(PointerRNA *ptr)
return rna_pointer_inherit_refine(ptr, &RNA_NlaTrack, track);
}
-static void rna_NlaTrack_active_set(struct ReportList *UNUSED(reports),
- PointerRNA *ptr,
- PointerRNA value)
+static void rna_NlaTrack_active_set(PointerRNA *ptr,
+ PointerRNA value,
+ struct ReportList *UNUSED(reports))
{
AnimData *adt = (AnimData *)ptr->data;
NlaTrack *track = (NlaTrack *)value.data;
diff --git a/source/blender/makesrna/intern/rna_armature.c b/source/blender/makesrna/intern/rna_armature.c
index 3aef22f5f7f..604be10d5ab 100644
--- a/source/blender/makesrna/intern/rna_armature.c
+++ b/source/blender/makesrna/intern/rna_armature.c
@@ -67,9 +67,9 @@ static void rna_Armature_dependency_update(Main *bmain, Scene *UNUSED(scene), Po
WM_main_add_notifier(NC_GEOM | ND_DATA, id);
}
-static void rna_Armature_act_bone_set(struct ReportList *UNUSED(reports),
- PointerRNA *ptr,
- PointerRNA value)
+static void rna_Armature_act_bone_set(PointerRNA *ptr,
+ PointerRNA value,
+ struct ReportList *UNUSED(reports))
{
bArmature *arm = (bArmature *)ptr->data;
@@ -91,9 +91,9 @@ static void rna_Armature_act_bone_set(struct ReportList *UNUSED(reports),
}
}
-static void rna_Armature_act_edit_bone_set(struct ReportList *UNUSED(reports),
- PointerRNA *ptr,
- PointerRNA value)
+static void rna_Armature_act_edit_bone_set(PointerRNA *ptr,
+ PointerRNA value,
+ struct ReportList *UNUSED(reports))
{
bArmature *arm = (bArmature *)ptr->data;
@@ -399,9 +399,9 @@ static PointerRNA rna_EditBone_parent_get(PointerRNA *ptr)
return rna_pointer_inherit_refine(ptr, &RNA_EditBone, data->parent);
}
-static void rna_EditBone_parent_set(struct ReportList *UNUSED(reports),
- PointerRNA *ptr,
- PointerRNA value)
+static void rna_EditBone_parent_set(PointerRNA *ptr,
+ PointerRNA value,
+ struct ReportList *UNUSED(reports))
{
EditBone *ebone = (EditBone *)(ptr->data);
EditBone *pbone, *parbone = (EditBone *)value.data;
@@ -469,9 +469,9 @@ static PointerRNA rna_EditBone_bbone_prev_get(PointerRNA *ptr)
return rna_pointer_inherit_refine(ptr, &RNA_EditBone, data->bbone_prev);
}
-static void rna_EditBone_bbone_prev_set(struct ReportList *UNUSED(reports),
- PointerRNA *ptr,
- PointerRNA value)
+static void rna_EditBone_bbone_prev_set(PointerRNA *ptr,
+ PointerRNA value,
+ struct ReportList *UNUSED(reports))
{
EditBone *ebone = (EditBone *)(ptr->data);
EditBone *hbone = (EditBone *)value.data;
@@ -482,9 +482,9 @@ static void rna_EditBone_bbone_prev_set(struct ReportList *UNUSED(reports),
}
}
-static void rna_Bone_bbone_prev_set(struct ReportList *UNUSED(reports),
- PointerRNA *ptr,
- PointerRNA value)
+static void rna_Bone_bbone_prev_set(PointerRNA *ptr,
+ PointerRNA value,
+ struct ReportList *UNUSED(reports))
{
Bone *bone = (Bone *)ptr->data;
Bone *hbone = (Bone *)value.data;
@@ -501,9 +501,9 @@ static PointerRNA rna_EditBone_bbone_next_get(PointerRNA *ptr)
return rna_pointer_inherit_refine(ptr, &RNA_EditBone, data->bbone_next);
}
-static void rna_EditBone_bbone_next_set(struct ReportList *UNUSED(reports),
- PointerRNA *ptr,
- PointerRNA value)
+static void rna_EditBone_bbone_next_set(PointerRNA *ptr,
+ PointerRNA value,
+ struct ReportList *UNUSED(reports))
{
EditBone *ebone = (EditBone *)(ptr->data);
EditBone *hbone = (EditBone *)value.data;
@@ -514,9 +514,9 @@ static void rna_EditBone_bbone_next_set(struct ReportList *UNUSED(reports),
}
}
-static void rna_Bone_bbone_next_set(struct ReportList *UNUSED(reports),
- PointerRNA *ptr,
- PointerRNA value)
+static void rna_Bone_bbone_next_set(PointerRNA *ptr,
+ PointerRNA value,
+ struct ReportList *UNUSED(reports))
{
Bone *bone = (Bone *)ptr->data;
Bone *hbone = (Bone *)value.data;
diff --git a/source/blender/makesrna/intern/rna_cloth.c b/source/blender/makesrna/intern/rna_cloth.c
index bab7075b75b..f5cb29b5e69 100644
--- a/source/blender/makesrna/intern/rna_cloth.c
+++ b/source/blender/makesrna/intern/rna_cloth.c
@@ -306,9 +306,9 @@ static PointerRNA rna_ClothSettings_rest_shape_key_get(PointerRNA *ptr)
return rna_object_shapekey_index_get(ob->data, sim->shapekey_rest);
}
-static void rna_ClothSettings_rest_shape_key_set(struct ReportList *UNUSED(reports),
- PointerRNA *ptr,
- PointerRNA value)
+static void rna_ClothSettings_rest_shape_key_set(PointerRNA *ptr,
+ PointerRNA value,
+ struct ReportList *UNUSED(reports))
{
Object *ob = (Object *)ptr->id.data;
ClothSimSettings *sim = (ClothSimSettings *)ptr->data;
diff --git a/source/blender/makesrna/intern/rna_color.c b/source/blender/makesrna/intern/rna_color.c
index 8ba1f5440be..30ab591d3c9 100644
--- a/source/blender/makesrna/intern/rna_color.c
+++ b/source/blender/makesrna/intern/rna_color.c
@@ -623,7 +623,7 @@ static void rna_ColorManagedColorspaceSettings_reload_update(Main *bmain,
seq->strip->proxy->anim = NULL;
}
- BKE_sequence_invalidate_cache(scene, seq);
+ BKE_sequence_invalidate_cache_preprocessed(scene, seq);
}
else {
SEQ_BEGIN (scene->ed, seq) {
@@ -1136,7 +1136,7 @@ static void rna_def_colormanage(BlenderRNA *brna)
PropertyRNA *prop;
static const EnumPropertyItem display_device_items[] = {
- {0, "DEFAULT", 0, "Default", ""},
+ {0, "NONE", 0, "None", ""},
{0, NULL, 0, NULL, NULL},
};
@@ -1249,7 +1249,10 @@ static void rna_def_colormanage(BlenderRNA *brna)
"rna_ColorManagedColorspaceSettings_colorspace_get",
"rna_ColorManagedColorspaceSettings_colorspace_set",
"rna_ColorManagedColorspaceSettings_colorspace_itemf");
- RNA_def_property_ui_text(prop, "Input Color Space", "Color space of the image or movie on disk");
+ RNA_def_property_ui_text(
+ prop,
+ "Input Color Space",
+ "Color space in the image file, to convert to and from when saving and loading the image");
RNA_def_property_update(prop, NC_WINDOW, "rna_ColorManagedColorspaceSettings_reload_update");
prop = RNA_def_property(srna, "is_data", PROP_BOOLEAN, PROP_NONE);
diff --git a/source/blender/makesrna/intern/rna_constraint.c b/source/blender/makesrna/intern/rna_constraint.c
index 252dc40f3f5..ac319a545ac 100644
--- a/source/blender/makesrna/intern/rna_constraint.c
+++ b/source/blender/makesrna/intern/rna_constraint.c
@@ -351,9 +351,9 @@ static StructRNA *rna_ConstraintType_refine(struct PointerRNA *ptr)
}
}
-static void rna_ConstraintTargetBone_target_set(struct ReportList *UNUSED(reports),
- PointerRNA *ptr,
- PointerRNA value)
+static void rna_ConstraintTargetBone_target_set(PointerRNA *ptr,
+ PointerRNA value,
+ struct ReportList *UNUSED(reports))
{
bConstraintTarget *tgt = (bConstraintTarget *)ptr->data;
Object *ob = value.data;
@@ -667,9 +667,9 @@ static bool rna_Constraint_cameraObject_poll(PointerRNA *ptr, PointerRNA value)
return 0;
}
-static void rna_Constraint_followTrack_camera_set(struct ReportList *UNUSED(reports),
- PointerRNA *ptr,
- PointerRNA value)
+static void rna_Constraint_followTrack_camera_set(PointerRNA *ptr,
+ PointerRNA value,
+ struct ReportList *UNUSED(reports))
{
bConstraint *con = (bConstraint *)ptr->data;
bFollowTrackConstraint *data = (bFollowTrackConstraint *)con->data;
@@ -686,9 +686,9 @@ static void rna_Constraint_followTrack_camera_set(struct ReportList *UNUSED(repo
}
}
-static void rna_Constraint_followTrack_depthObject_set(struct ReportList *UNUSED(reports),
- PointerRNA *ptr,
- PointerRNA value)
+static void rna_Constraint_followTrack_depthObject_set(PointerRNA *ptr,
+ PointerRNA value,
+ struct ReportList *UNUSED(reports))
{
bConstraint *con = (bConstraint *)ptr->data;
bFollowTrackConstraint *data = (bFollowTrackConstraint *)con->data;
@@ -718,9 +718,9 @@ static bool rna_Constraint_followTrack_depthObject_poll(PointerRNA *ptr, Pointer
return 0;
}
-static void rna_Constraint_objectSolver_camera_set(struct ReportList *UNUSED(reports),
- PointerRNA *ptr,
- PointerRNA value)
+static void rna_Constraint_objectSolver_camera_set(PointerRNA *ptr,
+ PointerRNA value,
+ struct ReportList *UNUSED(reports))
{
bConstraint *con = (bConstraint *)ptr->data;
bObjectSolverConstraint *data = (bObjectSolverConstraint *)con->data;
diff --git a/source/blender/makesrna/intern/rna_context.c b/source/blender/makesrna/intern/rna_context.c
index a2ac7cb40ba..9986b4c1674 100644
--- a/source/blender/makesrna/intern/rna_context.c
+++ b/source/blender/makesrna/intern/rna_context.c
@@ -57,6 +57,10 @@ const EnumPropertyItem rna_enum_context_mode_items[] = {
#ifdef RNA_RUNTIME
+# ifdef WITH_PYTHON
+# include "BPY_extern.h"
+# endif
+
# include "RE_engine.h"
static PointerRNA rna_Context_manager_get(PointerRNA *ptr)
@@ -200,7 +204,20 @@ static int rna_Context_mode_get(PointerRNA *ptr)
static struct Depsgraph *rna_Context_evaluated_depsgraph_get(bContext *C)
{
- return CTX_data_evaluated_depsgraph(C);
+ struct Depsgraph *depsgraph;
+
+# ifdef WITH_PYTHON
+ /* Allow drivers to be evaluated */
+ BPy_BEGIN_ALLOW_THREADS;
+# endif
+
+ depsgraph = CTX_data_evaluated_depsgraph(C);
+
+# ifdef WITH_PYTHON
+ BPy_END_ALLOW_THREADS;
+# endif
+
+ return depsgraph;
}
#else
diff --git a/source/blender/makesrna/intern/rna_curve.c b/source/blender/makesrna/intern/rna_curve.c
index 111e8956414..89200240b08 100644
--- a/source/blender/makesrna/intern/rna_curve.c
+++ b/source/blender/makesrna/intern/rna_curve.c
@@ -438,9 +438,9 @@ static PointerRNA rna_Curve_bevelObject_get(PointerRNA *ptr)
return rna_pointer_inherit_refine(ptr, NULL, NULL);
}
-static void rna_Curve_bevelObject_set(struct ReportList *UNUSED(reports),
- PointerRNA *ptr,
- PointerRNA value)
+static void rna_Curve_bevelObject_set(PointerRNA *ptr,
+ PointerRNA value,
+ struct ReportList *UNUSED(reports))
{
Curve *cu = (Curve *)ptr->id.data;
Object *ob = (Object *)value.data;
@@ -483,9 +483,9 @@ static PointerRNA rna_Curve_taperObject_get(PointerRNA *ptr)
return rna_pointer_inherit_refine(ptr, NULL, NULL);
}
-static void rna_Curve_taperObject_set(struct ReportList *UNUSED(reports),
- PointerRNA *ptr,
- PointerRNA value)
+static void rna_Curve_taperObject_set(PointerRNA *ptr,
+ PointerRNA value,
+ struct ReportList *UNUSED(reports))
{
Curve *cu = (Curve *)ptr->id.data;
Object *ob = (Object *)value.data;
@@ -734,9 +734,9 @@ static PointerRNA rna_Curve_active_spline_get(PointerRNA *ptr)
return rna_pointer_inherit_refine(ptr, NULL, NULL);
}
-static void rna_Curve_active_spline_set(struct ReportList *UNUSED(reports),
- PointerRNA *ptr,
- PointerRNA value)
+static void rna_Curve_active_spline_set(PointerRNA *ptr,
+ PointerRNA value,
+ struct ReportList *UNUSED(reports))
{
Curve *cu = (Curve *)ptr->data;
Nurb *nu = value.data;
diff --git a/source/blender/makesrna/intern/rna_define.c b/source/blender/makesrna/intern/rna_define.c
index 8e24e9a8364..b1818cae62a 100644
--- a/source/blender/makesrna/intern/rna_define.c
+++ b/source/blender/makesrna/intern/rna_define.c
@@ -709,6 +709,14 @@ void RNA_define_animate_sdna(bool animate)
}
#endif
+#ifndef RNA_RUNTIME
+void RNA_define_fallback_property_update(int noteflag, const char *updatefunc)
+{
+ DefRNA.fallback.property_update.noteflag = noteflag;
+ DefRNA.fallback.property_update.updatefunc = updatefunc;
+}
+#endif
+
void RNA_struct_free_extension(StructRNA *srna, ExtensionRNA *ext)
{
#ifdef RNA_RUNTIME
@@ -1413,6 +1421,12 @@ PropertyRNA *RNA_def_property(StructOrFunctionRNA *cont_,
}
/* TODO: do we want that for runtime-defined stuff too? I’d say no, but... maybe yes :/ */
+#ifndef RNA_RUNTIME
+ /* Both are typically cleared. */
+ RNA_def_property_update(
+ prop, DefRNA.fallback.property_update.noteflag, DefRNA.fallback.property_update.updatefunc);
+#endif
+
rna_addtail(&cont->properties, prop);
return prop;
diff --git a/source/blender/makesrna/intern/rna_depsgraph.c b/source/blender/makesrna/intern/rna_depsgraph.c
index c4a2a64f3f0..df1727ff87c 100644
--- a/source/blender/makesrna/intern/rna_depsgraph.c
+++ b/source/blender/makesrna/intern/rna_depsgraph.c
@@ -622,21 +622,13 @@ static void rna_def_depsgraph(BlenderRNA *brna)
func = RNA_def_function(
srna, "debug_relations_graphviz", "rna_Depsgraph_debug_relations_graphviz");
- parm = RNA_def_string_file_path(func,
- "filename",
- NULL,
- FILE_MAX,
- "File Name",
- "File in which to store graphviz debug output");
+ parm = RNA_def_string_file_path(
+ func, "filename", NULL, FILE_MAX, "File Name", "Output path for the graphviz debug file");
RNA_def_parameter_flags(parm, 0, PARM_REQUIRED);
func = RNA_def_function(srna, "debug_stats_gnuplot", "rna_Depsgraph_debug_stats_gnuplot");
- parm = RNA_def_string_file_path(func,
- "filename",
- NULL,
- FILE_MAX,
- "File Name",
- "File in which to store graphviz debug output");
+ parm = RNA_def_string_file_path(
+ func, "filename", NULL, FILE_MAX, "File Name", "Output path for the gnuplot debug file");
RNA_def_parameter_flags(parm, 0, PARM_REQUIRED);
parm = RNA_def_string_file_path(func,
"output_filename",
diff --git a/source/blender/makesrna/intern/rna_fcurve.c b/source/blender/makesrna/intern/rna_fcurve.c
index 1edcbf0774d..741b73f4250 100644
--- a/source/blender/makesrna/intern/rna_fcurve.c
+++ b/source/blender/makesrna/intern/rna_fcurve.c
@@ -239,9 +239,9 @@ static void rna_DriverTarget_update_name(Main *bmain, Scene *scene, PointerRNA *
/* ----------- */
/* note: this function exists only to avoid id refcounting */
-static void rna_DriverTarget_id_set(struct ReportList *UNUSED(reports),
- PointerRNA *ptr,
- PointerRNA value)
+static void rna_DriverTarget_id_set(PointerRNA *ptr,
+ PointerRNA value,
+ struct ReportList *UNUSED(reports))
{
DriverTarget *dtar = (DriverTarget *)ptr->data;
dtar->id = value.data;
@@ -448,9 +448,9 @@ static void rna_FCurve_RnaPath_set(PointerRNA *ptr, const char *value)
fcu->rna_path = NULL;
}
-static void rna_FCurve_group_set(struct ReportList *UNUSED(reports),
- PointerRNA *ptr,
- PointerRNA value)
+static void rna_FCurve_group_set(PointerRNA *ptr,
+ PointerRNA value,
+ struct ReportList *UNUSED(reports))
{
ID *pid = (ID *)ptr->id.data;
ID *vid = (ID *)value.id.data;
@@ -530,18 +530,35 @@ static bool rna_FCurve_is_empty_get(PointerRNA *ptr)
return BKE_fcurve_is_empty(fcu);
}
+static void rna_tag_animation_update(Main *bmain, ID *id, bool flush)
+{
+ /* Actually recalculate object properties, or just update COW. */
+ int tags = flush ? ID_RECALC_ANIMATION : ID_RECALC_ANIMATION_NO_FLUSH;
+
+ AnimData *adt = BKE_animdata_from_id(id);
+
+ if (adt && adt->action) {
+ /* action is separate datablock, needs separate tag */
+ DEG_id_tag_update_ex(bmain, &adt->action->id, tags);
+ }
+
+ DEG_id_tag_update_ex(bmain, id, tags);
+}
+
/* allow scripts to update curve after editing manually */
-static void rna_FCurve_update_data_ex(FCurve *fcu)
+static void rna_FCurve_update_data_ex(ID *id, FCurve *fcu, Main *bmain)
{
sort_time_fcurve(fcu);
calchandles_fcurve(fcu);
+
+ rna_tag_animation_update(bmain, id, true);
}
/* RNA update callback for F-Curves after curve shape changes */
-static void rna_FCurve_update_data(Main *UNUSED(bmain), Scene *UNUSED(scene), PointerRNA *ptr)
+static void rna_FCurve_update_data(Main *bmain, Scene *UNUSED(scene), PointerRNA *ptr)
{
BLI_assert(ptr->type == &RNA_FCurve);
- rna_FCurve_update_data_ex((FCurve *)ptr->data);
+ rna_FCurve_update_data_ex((ID *)ptr->id.data, (FCurve *)ptr->data, bmain);
}
static void rna_FCurve_update_data_relations(Main *bmain,
@@ -554,13 +571,9 @@ static void rna_FCurve_update_data_relations(Main *bmain,
/* RNA update callback for F-Curves to indicate that there are copy-on-write tagging/flushing
* needed (e.g. for properties that affect how animation gets evaluated).
*/
-static void rna_FCurve_update_eval(Main *UNUSED(bmain), Scene *UNUSED(scene), PointerRNA *ptr)
+static void rna_FCurve_update_eval(Main *bmain, Scene *UNUSED(scene), PointerRNA *ptr)
{
- IdAdtTemplate *iat = (IdAdtTemplate *)ptr->id.data;
- if (iat && iat->adt && iat->adt->action) {
- /* action is separate datablock, needs separate tag */
- DEG_id_tag_update(&iat->adt->action->id, ID_RECALC_ANIMATION);
- }
+ rna_tag_animation_update(bmain, (ID *)ptr->id.data, true);
}
static PointerRNA rna_FCurve_active_modifier_get(PointerRNA *ptr)
@@ -570,9 +583,9 @@ static PointerRNA rna_FCurve_active_modifier_get(PointerRNA *ptr)
return rna_pointer_inherit_refine(ptr, &RNA_FModifier, fcm);
}
-static void rna_FCurve_active_modifier_set(struct ReportList *UNUSED(reports),
- PointerRNA *ptr,
- PointerRNA value)
+static void rna_FCurve_active_modifier_set(PointerRNA *ptr,
+ PointerRNA value,
+ struct ReportList *UNUSED(reports))
{
FCurve *fcu = (FCurve *)ptr->data;
set_active_fmodifier(&fcu->modifiers, (FModifier *)value.data);
@@ -671,28 +684,16 @@ static void rna_FModifier_blending_range(
*max = fcm->efra - fcm->sfra;
}
-static void rna_FModifier_update(Main *UNUSED(bmain), Scene *UNUSED(scene), PointerRNA *ptr)
+static void rna_FModifier_update(Main *bmain, Scene *UNUSED(scene), PointerRNA *ptr)
{
ID *id = ptr->id.data;
FModifier *fcm = (FModifier *)ptr->data;
- AnimData *adt = BKE_animdata_from_id(id);
-
- DEG_id_tag_update(id, ID_RECALC_ANIMATION);
-
- /* tag datablock for time update so that animation is recalculated,
- * as FModifiers affect how animation plays...
- */
- DEG_id_tag_update(id, ID_RECALC_ANIMATION);
- if (adt != NULL) {
- if (adt->action != NULL) {
- /* action is separate datablock, needs separate tag */
- DEG_id_tag_update(&adt->action->id, ID_RECALC_ANIMATION);
- }
- }
if (fcm->curve && fcm->type == FMODIFIER_TYPE_CYCLES) {
calchandles_fcurve(fcm->curve);
}
+
+ rna_tag_animation_update(bmain, id, true);
}
static void rna_FModifier_verify_data_update(Main *bmain, Scene *scene, PointerRNA *ptr)
@@ -909,14 +910,21 @@ static void rna_FModifierStepped_frame_end_set(PointerRNA *ptr, float value)
}
static BezTriple *rna_FKeyframe_points_insert(
- FCurve *fcu, float frame, float value, int keyframe_type, int flag)
+ ID *id, FCurve *fcu, Main *bmain, float frame, float value, int keyframe_type, int flag)
{
int index = insert_vert_fcurve(
fcu, frame, value, (char)keyframe_type, flag | INSERTKEY_NO_USERPREF);
- return ((fcu->bezt) && (index >= 0)) ? (fcu->bezt + index) : NULL;
+
+ if ((fcu->bezt) && (index >= 0)) {
+ rna_tag_animation_update(bmain, id, true);
+
+ return fcu->bezt + index;
+ }
+
+ return NULL;
}
-static void rna_FKeyframe_points_add(FCurve *fcu, int tot)
+static void rna_FKeyframe_points_add(ID *id, FCurve *fcu, Main *bmain, int tot)
{
if (tot > 0) {
BezTriple *bezt;
@@ -933,13 +941,13 @@ static void rna_FKeyframe_points_add(FCurve *fcu, int tot)
bezt->h1 = bezt->h2 = HD_AUTO_ANIM;
bezt++;
}
+
+ rna_tag_animation_update(bmain, id, true);
}
}
-static void rna_FKeyframe_points_remove(FCurve *fcu,
- ReportList *reports,
- PointerRNA *bezt_ptr,
- bool do_fast)
+static void rna_FKeyframe_points_remove(
+ ID *id, FCurve *fcu, Main *bmain, ReportList *reports, PointerRNA *bezt_ptr, bool do_fast)
{
BezTriple *bezt = bezt_ptr->data;
int index = (int)(bezt - fcu->bezt);
@@ -950,16 +958,19 @@ static void rna_FKeyframe_points_remove(FCurve *fcu,
delete_fcurve_key(fcu, index, !do_fast);
RNA_POINTER_INVALIDATE(bezt_ptr);
+
+ rna_tag_animation_update(bmain, id, true);
}
-static FCM_EnvelopeData *rna_FModifierEnvelope_points_add(FModifier *fmod,
- ReportList *reports,
- float frame)
+static FCM_EnvelopeData *rna_FModifierEnvelope_points_add(
+ ID *id, FModifier *fmod, Main *bmain, ReportList *reports, float frame)
{
FCM_EnvelopeData fed;
FMod_Envelope *env = (FMod_Envelope *)fmod->data;
int i;
+ rna_tag_animation_update(bmain, id, true);
+
/* init template data */
fed.min = -1.0f;
fed.max = 1.0f;
@@ -996,9 +1007,8 @@ static FCM_EnvelopeData *rna_FModifierEnvelope_points_add(FModifier *fmod,
return (env->data + i);
}
-static void rna_FModifierEnvelope_points_remove(FModifier *fmod,
- ReportList *reports,
- PointerRNA *point)
+static void rna_FModifierEnvelope_points_remove(
+ ID *id, FModifier *fmod, Main *bmain, ReportList *reports, PointerRNA *point)
{
FCM_EnvelopeData *cp = point->data;
FMod_Envelope *env = (FMod_Envelope *)fmod->data;
@@ -1011,6 +1021,8 @@ static void rna_FModifierEnvelope_points_remove(FModifier *fmod,
return;
}
+ rna_tag_animation_update(bmain, id, true);
+
if (env->totvert > 1) {
/* move data after the removed point */
@@ -1034,19 +1046,9 @@ static void rna_FModifierEnvelope_points_remove(FModifier *fmod,
RNA_POINTER_INVALIDATE(point);
}
-static void rna_Keyframe_update(Main *UNUSED(bmain), Scene *UNUSED(scene), PointerRNA *ptr)
+static void rna_Keyframe_update(Main *bmain, Scene *UNUSED(scene), PointerRNA *ptr)
{
- ID *id = ptr->id.data;
- AnimData *adt = BKE_animdata_from_id(id);
-
- DEG_id_tag_update(id, ID_RECALC_ANIMATION);
-
- if (adt != NULL) {
- if (adt->action != NULL) {
- /* action is separate datablock, needs separate tag */
- DEG_id_tag_update(&adt->action->id, ID_RECALC_ANIMATION);
- }
- }
+ rna_tag_animation_update(bmain, (ID *)ptr->id.data, true);
}
#else
@@ -1217,7 +1219,7 @@ static void rna_def_fmodifier_envelope_control_points(BlenderRNA *brna, Property
func = RNA_def_function(srna, "add", "rna_FModifierEnvelope_points_add");
RNA_def_function_ui_description(func, "Add a control point to a FModifierEnvelope");
- RNA_def_function_flag(func, FUNC_USE_REPORTS);
+ RNA_def_function_flag(func, FUNC_USE_SELF_ID | FUNC_USE_MAIN | FUNC_USE_REPORTS);
parm = RNA_def_float(func,
"frame",
0.0f,
@@ -1234,7 +1236,7 @@ static void rna_def_fmodifier_envelope_control_points(BlenderRNA *brna, Property
func = RNA_def_function(srna, "remove", "rna_FModifierEnvelope_points_remove");
RNA_def_function_ui_description(func, "Remove a control-point from an FModifierEnvelope");
- RNA_def_function_flag(func, FUNC_USE_REPORTS);
+ RNA_def_function_flag(func, FUNC_USE_SELF_ID | FUNC_USE_MAIN | FUNC_USE_REPORTS);
parm = RNA_def_pointer(
func, "point", "FModifierEnvelopeControlPoint", "", "Control-point to remove");
RNA_def_parameter_flags(parm, PROP_NEVER_NULL, PARM_REQUIRED | PARM_RNAPTR);
@@ -2111,6 +2113,7 @@ static void rna_def_fcurve_keyframe_points(BlenderRNA *brna, PropertyRNA *cprop)
func = RNA_def_function(srna, "insert", "rna_FKeyframe_points_insert");
RNA_def_function_ui_description(func, "Add a keyframe point to a F-Curve");
+ RNA_def_function_flag(func, FUNC_USE_SELF_ID | FUNC_USE_MAIN);
parm = RNA_def_float(func,
"frame",
0.0f,
@@ -2143,13 +2146,14 @@ static void rna_def_fcurve_keyframe_points(BlenderRNA *brna, PropertyRNA *cprop)
func = RNA_def_function(srna, "add", "rna_FKeyframe_points_add");
RNA_def_function_ui_description(func, "Add a keyframe point to a F-Curve");
+ RNA_def_function_flag(func, FUNC_USE_SELF_ID | FUNC_USE_MAIN);
parm = RNA_def_int(
func, "count", 1, 0, INT_MAX, "Number", "Number of points to add to the spline", 0, INT_MAX);
RNA_def_parameter_flags(parm, 0, PARM_REQUIRED);
func = RNA_def_function(srna, "remove", "rna_FKeyframe_points_remove");
RNA_def_function_ui_description(func, "Remove keyframe from an F-Curve");
- RNA_def_function_flag(func, FUNC_USE_REPORTS);
+ RNA_def_function_flag(func, FUNC_USE_SELF_ID | FUNC_USE_MAIN | FUNC_USE_REPORTS);
parm = RNA_def_pointer(func, "keyframe", "Keyframe", "", "Keyframe to remove");
RNA_def_parameter_flags(parm, PROP_NEVER_NULL, PARM_REQUIRED | PARM_RNAPTR);
RNA_def_parameter_clear_flags(parm, PROP_THICK_WRAP, 0);
@@ -2361,6 +2365,7 @@ static void rna_def_fcurve(BlenderRNA *brna)
/* -- update / recalculate -- */
func = RNA_def_function(srna, "update", "rna_FCurve_update_data_ex");
+ RNA_def_function_flag(func, FUNC_USE_SELF_ID | FUNC_USE_MAIN);
RNA_def_function_ui_description(
func, "Ensure keyframes are sorted in chronological order and handles are set correctly");
diff --git a/source/blender/makesrna/intern/rna_gpencil.c b/source/blender/makesrna/intern/rna_gpencil.c
index c7071ee5155..a78eebd2618 100644
--- a/source/blender/makesrna/intern/rna_gpencil.c
+++ b/source/blender/makesrna/intern/rna_gpencil.c
@@ -281,9 +281,9 @@ static void set_parent(bGPDlayer *gpl, Object *par, const int type, const char *
}
/* set parent object and inverse matrix */
-static void rna_GPencilLayer_parent_set(struct ReportList *UNUSED(reports),
- PointerRNA *ptr,
- PointerRNA value)
+static void rna_GPencilLayer_parent_set(PointerRNA *ptr,
+ PointerRNA value,
+ struct ReportList *UNUSED(reports))
{
bGPDlayer *gpl = (bGPDlayer *)ptr->data;
Object *par = (Object *)value.data;
@@ -377,9 +377,9 @@ static PointerRNA rna_GPencil_active_layer_get(PointerRNA *ptr)
return rna_pointer_inherit_refine(ptr, NULL, NULL);
}
-static void rna_GPencil_active_layer_set(struct ReportList *UNUSED(reports),
- PointerRNA *ptr,
- PointerRNA value)
+static void rna_GPencil_active_layer_set(PointerRNA *ptr,
+ PointerRNA value,
+ struct ReportList *UNUSED(reports))
{
bGPdata *gpd = ptr->id.data;
@@ -652,6 +652,8 @@ static void rna_GPencil_stroke_point_pop(ID *id,
static bGPDstroke *rna_GPencil_stroke_new(bGPDframe *frame)
{
bGPDstroke *stroke = MEM_callocN(sizeof(bGPDstroke), "gp_stroke");
+ stroke->gradient_f = 1.0f;
+ ARRAY_SET_ITEMS(stroke->gradient_s, 1.0f, 1.0f);
BLI_addtail(&frame->strokes, stroke);
return stroke;
@@ -844,7 +846,7 @@ static void rna_def_gpencil_stroke_point(BlenderRNA *brna)
prop = RNA_def_property(srna, "pressure", PROP_FLOAT, PROP_FACTOR);
RNA_def_property_float_sdna(prop, NULL, "pressure");
- RNA_def_property_range(prop, 0.0f, 1.0f);
+ RNA_def_property_range(prop, 0.0f, FLT_MAX);
RNA_def_property_ui_text(prop, "Pressure", "Pressure of tablet at point when drawing it");
RNA_def_property_update(prop, NC_GPENCIL | ND_DATA, "rna_GPencil_update");
@@ -895,11 +897,11 @@ static void rna_def_gpencil_stroke_points_api(BlenderRNA *brna, PropertyRNA *cpr
"pressure",
1.0f,
0.0f,
- 1.0f,
+ FLT_MAX,
"Pressure",
"Pressure for newly created points",
0.0f,
- 1.0f);
+ FLT_MAX);
RNA_def_float(func,
"strength",
1.0f,
diff --git a/source/blender/makesrna/intern/rna_gpencil_modifier.c b/source/blender/makesrna/intern/rna_gpencil_modifier.c
index afefa66e2ae..cca291a0aae 100644
--- a/source/blender/makesrna/intern/rna_gpencil_modifier.c
+++ b/source/blender/makesrna/intern/rna_gpencil_modifier.c
@@ -297,7 +297,7 @@ static void greasepencil_modifier_object_set(Object *self,
# define RNA_GP_MOD_OBJECT_SET(_type, _prop, _obtype) \
static void rna_##_type##GpencilModifier_##_prop##_set( \
- struct ReportList *UNUSED(reports), PointerRNA *ptr, PointerRNA value) \
+ PointerRNA *ptr, PointerRNA value, struct ReportList *UNUSED(reports)) \
{ \
_type##GpencilModifierData *tmd = (_type##GpencilModifierData *)ptr->data; \
greasepencil_modifier_object_set(ptr->id.data, &tmd->_prop, _obtype, value); \
@@ -309,9 +309,9 @@ RNA_GP_MOD_OBJECT_SET(Mirror, object, OB_EMPTY);
# undef RNA_GP_MOD_OBJECT_SET
-static void rna_HookGpencilModifier_object_set(struct ReportList *UNUSED(reports),
- PointerRNA *ptr,
- PointerRNA value)
+static void rna_HookGpencilModifier_object_set(PointerRNA *ptr,
+ PointerRNA value,
+ struct ReportList *UNUSED(reports))
{
HookGpencilModifierData *hmd = ptr->data;
Object *ob = (Object *)value.data;
diff --git a/source/blender/makesrna/intern/rna_image.c b/source/blender/makesrna/intern/rna_image.c
index 40c8c7e1582..d5cefaefbb1 100644
--- a/source/blender/makesrna/intern/rna_image.c
+++ b/source/blender/makesrna/intern/rna_image.c
@@ -332,7 +332,10 @@ static int rna_Image_frame_duration_get(PointerRNA *ptr)
int duration = 1;
if (BKE_image_has_anim(ima)) {
- duration = IMB_anim_get_duration(((ImageAnim *)ima->anims.first)->anim, IMB_TC_RECORD_RUN);
+ struct anim *anim = ((ImageAnim *)ima->anims.first)->anim;
+ if (anim) {
+ duration = IMB_anim_get_duration(anim, IMB_TC_RECORD_RUN);
+ }
}
else {
/* acquire ensures ima->anim is set, if possible! */
@@ -479,9 +482,9 @@ static PointerRNA rna_render_slots_active_get(PointerRNA *ptr)
return rna_pointer_inherit_refine(ptr, &RNA_RenderSlot, render_slot);
}
-static void rna_render_slots_active_set(struct ReportList *UNUSED(reports),
- PointerRNA *ptr,
- PointerRNA value)
+static void rna_render_slots_active_set(PointerRNA *ptr,
+ PointerRNA value,
+ struct ReportList *UNUSED(reports))
{
Image *image = (Image *)ptr->id.data;
if (value.id.data == image) {
@@ -680,12 +683,26 @@ static void rna_def_image(BlenderRNA *brna)
"STRAIGHT",
0,
"Straight",
- "Transparent RGB and alpha pixels are unmodified"},
+ "Store RGB and alpha channels separately with alpha acting as a mask, also known as "
+ "unassociated alpha. Commonly used by image editing applications and file formats like "
+ "PNG"},
{IMA_ALPHA_PREMUL,
"PREMUL",
0,
"Premultiplied",
- "Transparent RGB pixels are multiplied by the alpha channel"},
+ "Store RGB channels with alpha multipled in, also known as associated alpha. The natural "
+ "format for renders and used by file formats like OpenEXR"},
+ {IMA_ALPHA_CHANNEL_PACKED,
+ "CHANNEL_PACKED",
+ 0,
+ "Channel Packed",
+ "Different images are packed in the RGB and alpha channels, and they should not "
+ "affect each other. Channel packing is commonly used by game engines to save memory"},
+ {IMA_ALPHA_IGNORE,
+ "NONE",
+ 0,
+ "None",
+ "Ignore alpha channel from the file and make image fully opaque"},
{0, NULL, 0, NULL, NULL},
};
@@ -744,15 +761,6 @@ static void rna_def_image(BlenderRNA *brna)
"Apply render part of display transformation when displaying this image on the screen");
RNA_def_property_update(prop, NC_IMAGE | ND_DISPLAY, NULL);
- prop = RNA_def_property(srna, "use_alpha", PROP_BOOLEAN, PROP_NONE);
- RNA_def_property_override_flag(prop, PROPOVERRIDE_OVERRIDABLE_STATIC);
- RNA_def_property_boolean_negative_sdna(prop, NULL, "flag", IMA_IGNORE_ALPHA);
- RNA_def_property_ui_text(
- prop,
- "Use Alpha",
- "Use the alpha channel information from the image or make image fully opaque");
- RNA_def_property_update(prop, NC_IMAGE | ND_DISPLAY, "rna_Image_colormanage_update");
-
prop = RNA_def_property(srna, "use_deinterlace", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_override_flag(prop, PROPOVERRIDE_OVERRIDABLE_STATIC);
RNA_def_property_boolean_sdna(prop, NULL, "flag", IMA_DEINTERLACE);
@@ -910,8 +918,10 @@ static void rna_def_image(BlenderRNA *brna)
prop = RNA_def_property(srna, "alpha_mode", PROP_ENUM, PROP_NONE);
RNA_def_property_override_flag(prop, PROPOVERRIDE_OVERRIDABLE_STATIC);
RNA_def_property_enum_items(prop, alpha_mode_items);
- RNA_def_property_ui_text(
- prop, "Alpha Mode", "Representation of alpha information in the RGBA pixels");
+ RNA_def_property_ui_text(prop,
+ "Alpha Mode",
+ "Representation of alpha in the image file, to convert to and from "
+ "when saving and loading the image");
RNA_def_property_update(prop, NC_IMAGE | ND_DISPLAY, "rna_Image_colormanage_update");
/* multiview */
diff --git a/source/blender/makesrna/intern/rna_internal.h b/source/blender/makesrna/intern/rna_internal.h
index 5b7388b49e7..1ea35ed4029 100644
--- a/source/blender/makesrna/intern/rna_internal.h
+++ b/source/blender/makesrna/intern/rna_internal.h
@@ -116,6 +116,16 @@ typedef struct BlenderDefRNA {
ListBase allocs;
struct StructRNA *laststruct;
int error, silent, preprocess, verify, animate;
+ /* Keep last. */
+#ifndef RNA_RUNTIME
+ struct {
+ /** #RNA_def_property_update */
+ struct {
+ int noteflag;
+ const char *updatefunc;
+ } property_update;
+ } fallback;
+#endif
} BlenderDefRNA;
extern BlenderDefRNA DefRNA;
@@ -278,9 +288,9 @@ int rna_object_shapekey_index_set(struct ID *id, PointerRNA value, int current);
/* ViewLayer related functions defined in rna_scene.c but required in rna_layer.c */
void rna_def_freestyle_settings(struct BlenderRNA *brna);
struct PointerRNA rna_FreestyleLineSet_linestyle_get(struct PointerRNA *ptr);
-void rna_FreestyleLineSet_linestyle_set(struct ReportList *reports,
- struct PointerRNA *ptr,
- struct PointerRNA value);
+void rna_FreestyleLineSet_linestyle_set(struct PointerRNA *ptr,
+ struct PointerRNA value,
+ struct ReportList *reports);
struct FreestyleLineSet *rna_FreestyleSettings_lineset_add(struct ID *id,
struct FreestyleSettings *config,
struct Main *bmain,
@@ -342,6 +352,10 @@ bool rna_GPencil_datablocks_obdata_poll(struct PointerRNA *ptr, const struct Poi
char *rna_TextureSlot_path(struct PointerRNA *ptr);
char *rna_Node_ImageUser_path(struct PointerRNA *ptr);
+/* Set U.is_dirty and redraw. */
+void rna_userdef_is_dirty_update_impl(void);
+void rna_userdef_is_dirty_update(struct Main *bmain, struct Scene *scene, struct PointerRNA *ptr);
+
/* API functions */
void RNA_api_action(StructRNA *srna);
diff --git a/source/blender/makesrna/intern/rna_internal_types.h b/source/blender/makesrna/intern/rna_internal_types.h
index 14d850be012..ccead626bb6 100644
--- a/source/blender/makesrna/intern/rna_internal_types.h
+++ b/source/blender/makesrna/intern/rna_internal_types.h
@@ -86,9 +86,9 @@ typedef const EnumPropertyItem *(*PropEnumItemFunc)(struct bContext *C,
bool *r_free);
typedef PointerRNA (*PropPointerGetFunc)(struct PointerRNA *ptr);
typedef StructRNA *(*PropPointerTypeFunc)(struct PointerRNA *ptr);
-typedef void (*PropPointerSetFunc)(struct ReportList *reports,
- struct PointerRNA *ptr,
- const PointerRNA value);
+typedef void (*PropPointerSetFunc)(struct PointerRNA *ptr,
+ const PointerRNA value,
+ struct ReportList *reports);
typedef bool (*PropPointerPollFunc)(struct PointerRNA *ptr, const PointerRNA value);
typedef bool (*PropPointerPollFuncPy)(struct PointerRNA *ptr,
const PointerRNA value,
diff --git a/source/blender/makesrna/intern/rna_key.c b/source/blender/makesrna/intern/rna_key.c
index 65233d5ccc1..c5997f27dc2 100644
--- a/source/blender/makesrna/intern/rna_key.c
+++ b/source/blender/makesrna/intern/rna_key.c
@@ -316,9 +316,9 @@ static PointerRNA rna_ShapeKey_relative_key_get(PointerRNA *ptr)
return rna_object_shapekey_index_get(ptr->id.data, kb->relative);
}
-static void rna_ShapeKey_relative_key_set(struct ReportList *UNUSED(reports),
- PointerRNA *ptr,
- PointerRNA value)
+static void rna_ShapeKey_relative_key_set(PointerRNA *ptr,
+ PointerRNA value,
+ struct ReportList *UNUSED(reports))
{
KeyBlock *kb = (KeyBlock *)ptr->data;
diff --git a/source/blender/makesrna/intern/rna_layer.c b/source/blender/makesrna/intern/rna_layer.c
index 63bb091b406..55009aa660d 100644
--- a/source/blender/makesrna/intern/rna_layer.c
+++ b/source/blender/makesrna/intern/rna_layer.c
@@ -67,9 +67,9 @@ static PointerRNA rna_ViewLayer_active_layer_collection_get(PointerRNA *ptr)
return rna_pointer_inherit_refine(ptr, &RNA_LayerCollection, lc);
}
-static void rna_ViewLayer_active_layer_collection_set(struct ReportList *UNUSED(reports),
- PointerRNA *ptr,
- PointerRNA value)
+static void rna_ViewLayer_active_layer_collection_set(PointerRNA *ptr,
+ PointerRNA value,
+ struct ReportList *UNUSED(reports))
{
ViewLayer *view_layer = (ViewLayer *)ptr->data;
LayerCollection *lc = (LayerCollection *)value.data;
@@ -86,9 +86,9 @@ static PointerRNA rna_LayerObjects_active_object_get(PointerRNA *ptr)
ptr, &RNA_Object, view_layer->basact ? view_layer->basact->object : NULL);
}
-static void rna_LayerObjects_active_object_set(struct ReportList *UNUSED(reports),
- PointerRNA *ptr,
- PointerRNA value)
+static void rna_LayerObjects_active_object_set(PointerRNA *ptr,
+ PointerRNA value,
+ struct ReportList *UNUSED(reports))
{
ViewLayer *view_layer = (ViewLayer *)ptr->data;
if (value.data)
@@ -411,6 +411,7 @@ static void rna_def_object_base(BlenderRNA *brna)
prop = RNA_def_property(srna, "hide_viewport", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "flag", BASE_HIDDEN);
+ RNA_def_property_flag(prop, PROP_LIB_EXCEPTION);
RNA_def_property_override_flag(prop, PROPOVERRIDE_OVERRIDABLE_STATIC);
RNA_def_property_ui_icon(prop, ICON_HIDE_OFF, -1);
RNA_def_property_ui_text(prop, "Hide in Viewport", "Temporarily hide in viewport");
diff --git a/source/blender/makesrna/intern/rna_linestyle.c b/source/blender/makesrna/intern/rna_linestyle.c
index b98b21a7722..1ef5fb17ed8 100644
--- a/source/blender/makesrna/intern/rna_linestyle.c
+++ b/source/blender/makesrna/intern/rna_linestyle.c
@@ -356,9 +356,9 @@ static PointerRNA rna_LineStyle_active_texture_get(PointerRNA *ptr)
return rna_pointer_inherit_refine(ptr, &RNA_Texture, tex);
}
-static void rna_LineStyle_active_texture_set(struct ReportList *UNUSED(reports),
- PointerRNA *ptr,
- PointerRNA value)
+static void rna_LineStyle_active_texture_set(PointerRNA *ptr,
+ PointerRNA value,
+ struct ReportList *UNUSED(reports))
{
FreestyleLineStyle *linestyle = (FreestyleLineStyle *)ptr->id.data;
diff --git a/source/blender/makesrna/intern/rna_main_api.c b/source/blender/makesrna/intern/rna_main_api.c
index bd06cfc1936..aa8de7f23db 100644
--- a/source/blender/makesrna/intern/rna_main_api.c
+++ b/source/blender/makesrna/intern/rna_main_api.c
@@ -332,7 +332,11 @@ static Mesh *rna_Main_meshes_new(Main *bmain, const char *name)
}
/* copied from Mesh_getFromObject and adapted to RNA interface */
-static Mesh *rna_Main_meshes_new_from_object(Main *bmain, ReportList *reports, Object *object)
+static Mesh *rna_Main_meshes_new_from_object(Main *bmain,
+ ReportList *reports,
+ Object *object,
+ bool preserve_all_data_layers,
+ Depsgraph *depsgraph)
{
switch (object->type) {
case OB_FONT:
@@ -346,7 +350,7 @@ static Mesh *rna_Main_meshes_new_from_object(Main *bmain, ReportList *reports, O
return NULL;
}
- return BKE_mesh_new_from_object_to_bmain(bmain, object);
+ return BKE_mesh_new_from_object_to_bmain(bmain, depsgraph, object, preserve_all_data_layers);
}
static Light *rna_Main_lights_new(Main *bmain, const char *name, int type)
@@ -966,6 +970,19 @@ void RNA_def_main_meshes(BlenderRNA *brna, PropertyRNA *cprop)
RNA_def_function_flag(func, FUNC_USE_REPORTS);
parm = RNA_def_pointer(func, "object", "Object", "", "Object to create mesh from");
RNA_def_parameter_flags(parm, PROP_NEVER_NULL, PARM_REQUIRED);
+ RNA_def_boolean(func,
+ "preserve_all_data_layers",
+ false,
+ "",
+ "Preserve all data layers in the mesh, like UV maps and vertex groups. "
+ "By default Blender only computes the subset of data layers needed for viewport "
+ "display and rendering, for better performance");
+ RNA_def_pointer(
+ func,
+ "depsgraph",
+ "Depsgraph",
+ "Dependency Graph",
+ "Evaluated dependency graph which is required when preserve_all_data_layers is true");
parm = RNA_def_pointer(func,
"mesh",
"Mesh",
diff --git a/source/blender/makesrna/intern/rna_mask.c b/source/blender/makesrna/intern/rna_mask.c
index 563372dd4cf..7334c5baec0 100644
--- a/source/blender/makesrna/intern/rna_mask.c
+++ b/source/blender/makesrna/intern/rna_mask.c
@@ -116,9 +116,9 @@ static void rna_Mask_update_parent(Main *bmain, Scene *scene, PointerRNA *ptr)
}
/* note: this function exists only to avoid id refcounting */
-static void rna_MaskParent_id_set(struct ReportList *UNUSED(reports),
- PointerRNA *ptr,
- PointerRNA value)
+static void rna_MaskParent_id_set(PointerRNA *ptr,
+ PointerRNA value,
+ struct ReportList *UNUSED(reports))
{
MaskParent *mpar = (MaskParent *)ptr->data;
@@ -193,9 +193,9 @@ static PointerRNA rna_Mask_layer_active_get(PointerRNA *ptr)
return rna_pointer_inherit_refine(ptr, &RNA_MaskLayer, masklay);
}
-static void rna_Mask_layer_active_set(struct ReportList *UNUSED(reports),
- PointerRNA *ptr,
- PointerRNA value)
+static void rna_Mask_layer_active_set(PointerRNA *ptr,
+ PointerRNA value,
+ struct ReportList *UNUSED(reports))
{
Mask *mask = (Mask *)ptr->id.data;
MaskLayer *masklay = (MaskLayer *)value.data;
@@ -230,9 +230,9 @@ static PointerRNA rna_MaskLayer_active_spline_get(PointerRNA *ptr)
return rna_pointer_inherit_refine(ptr, &RNA_MaskSpline, masklay->act_spline);
}
-static void rna_MaskLayer_active_spline_set(struct ReportList *UNUSED(reports),
- PointerRNA *ptr,
- PointerRNA value)
+static void rna_MaskLayer_active_spline_set(PointerRNA *ptr,
+ PointerRNA value,
+ struct ReportList *UNUSED(reports))
{
MaskLayer *masklay = (MaskLayer *)ptr->data;
MaskSpline *spline = (MaskSpline *)value.data;
@@ -251,9 +251,9 @@ static PointerRNA rna_MaskLayer_active_spline_point_get(PointerRNA *ptr)
return rna_pointer_inherit_refine(ptr, &RNA_MaskSplinePoint, masklay->act_point);
}
-static void rna_MaskLayer_active_spline_point_set(struct ReportList *UNUSED(reports),
- PointerRNA *ptr,
- PointerRNA value)
+static void rna_MaskLayer_active_spline_point_set(PointerRNA *ptr,
+ PointerRNA value,
+ struct ReportList *UNUSED(reports))
{
MaskLayer *masklay = (MaskLayer *)ptr->data;
MaskSpline *spline;
diff --git a/source/blender/makesrna/intern/rna_material.c b/source/blender/makesrna/intern/rna_material.c
index 0aa7ac67555..5038740b0aa 100644
--- a/source/blender/makesrna/intern/rna_material.c
+++ b/source/blender/makesrna/intern/rna_material.c
@@ -332,9 +332,9 @@ static int rna_GpencilColorData_is_fill_visible_get(PointerRNA *ptr)
return ((pcolor->fill_rgba[3] > GPENCIL_ALPHA_OPACITY_THRESH) || (pcolor->fill_style > 0));
}
-static void rna_GpencilColorData_stroke_image_set(struct ReportList *UNUSED(reports),
- PointerRNA *ptr,
- PointerRNA value)
+static void rna_GpencilColorData_stroke_image_set(PointerRNA *ptr,
+ PointerRNA value,
+ struct ReportList *UNUSED(reports))
{
MaterialGPencilStyle *pcolor = ptr->data;
ID *id = value.data;
@@ -343,9 +343,9 @@ static void rna_GpencilColorData_stroke_image_set(struct ReportList *UNUSED(repo
pcolor->sima = (struct Image *)id;
}
-static void rna_GpencilColorData_fill_image_set(struct ReportList *UNUSED(reports),
- PointerRNA *ptr,
- PointerRNA value)
+static void rna_GpencilColorData_fill_image_set(PointerRNA *ptr,
+ PointerRNA value,
+ struct ReportList *UNUSED(reports))
{
MaterialGPencilStyle *pcolor = (MaterialGPencilStyle *)ptr->data;
ID *id = value.data;
diff --git a/source/blender/makesrna/intern/rna_mesh_utils.h b/source/blender/makesrna/intern/rna_mesh_utils.h
index 2da35b55bd5..9c5b4f9d5b3 100644
--- a/source/blender/makesrna/intern/rna_mesh_utils.h
+++ b/source/blender/makesrna/intern/rna_mesh_utils.h
@@ -84,7 +84,7 @@
} \
\
static void rna_Mesh_##collection_name##_##active_type##_set( \
- struct ReportList *UNUSED(reports), PointerRNA *ptr, PointerRNA value) \
+ PointerRNA *ptr, PointerRNA value, struct ReportList *UNUSED(reports)) \
{ \
Mesh *me = rna_mesh(ptr); \
CustomData *data = rna_mesh_##customdata_type(ptr); \
diff --git a/source/blender/makesrna/intern/rna_modifier.c b/source/blender/makesrna/intern/rna_modifier.c
index a7fe69134c8..4dca37c8bfd 100644
--- a/source/blender/makesrna/intern/rna_modifier.c
+++ b/source/blender/makesrna/intern/rna_modifier.c
@@ -722,7 +722,7 @@ static void modifier_object_set(Object *self, Object **ob_p, int type, PointerRN
# define RNA_MOD_OBJECT_SET(_type, _prop, _obtype) \
static void rna_##_type##Modifier_##_prop##_set( \
- struct ReportList *UNUSED(reports), PointerRNA *ptr, PointerRNA value) \
+ PointerRNA *ptr, PointerRNA value, struct ReportList *UNUSED(reports)) \
{ \
_type##ModifierData *tmd = (_type##ModifierData *)ptr->data; \
modifier_object_set(ptr->id.data, &tmd->_prop, _obtype, value); \
@@ -744,9 +744,9 @@ RNA_MOD_OBJECT_SET(Shrinkwrap, target, OB_MESH);
RNA_MOD_OBJECT_SET(Shrinkwrap, auxTarget, OB_MESH);
RNA_MOD_OBJECT_SET(SurfaceDeform, target, OB_MESH);
-static void rna_HookModifier_object_set(struct ReportList *UNUSED(reports),
- PointerRNA *ptr,
- PointerRNA value)
+static void rna_HookModifier_object_set(PointerRNA *ptr,
+ PointerRNA value,
+ struct ReportList *UNUSED(reports))
{
Object *owner = (Object *)ptr->id.data;
HookModifierData *hmd = ptr->data;
@@ -829,9 +829,9 @@ static PointerRNA rna_UVProjector_object_get(PointerRNA *ptr)
return rna_pointer_inherit_refine(ptr, &RNA_Object, *ob);
}
-static void rna_UVProjector_object_set(struct ReportList *UNUSED(reports),
- PointerRNA *ptr,
- PointerRNA value)
+static void rna_UVProjector_object_set(PointerRNA *ptr,
+ PointerRNA value,
+ struct ReportList *UNUSED(reports))
{
Object **ob_p = (Object **)ptr->data;
Object *ob = (Object *)value.data;
@@ -1403,9 +1403,9 @@ static PointerRNA rna_ParticleInstanceModifier_particle_system_get(PointerRNA *p
return rptr;
}
-static void rna_ParticleInstanceModifier_particle_system_set(struct ReportList *UNUSED(reports),
- PointerRNA *ptr,
- const PointerRNA value)
+static void rna_ParticleInstanceModifier_particle_system_set(PointerRNA *ptr,
+ const PointerRNA value,
+ struct ReportList *UNUSED(reports))
{
ParticleInstanceModifierData *psmd = ptr->data;
diff --git a/source/blender/makesrna/intern/rna_nodetree.c b/source/blender/makesrna/intern/rna_nodetree.c
index 17072a61bcd..d634a34bc5b 100644
--- a/source/blender/makesrna/intern/rna_nodetree.c
+++ b/source/blender/makesrna/intern/rna_nodetree.c
@@ -814,9 +814,9 @@ static PointerRNA rna_NodeTree_active_node_get(PointerRNA *ptr)
return rna_pointer_inherit_refine(ptr, &RNA_Node, node);
}
-static void rna_NodeTree_active_node_set(struct ReportList *UNUSED(reports),
- PointerRNA *ptr,
- const PointerRNA value)
+static void rna_NodeTree_active_node_set(PointerRNA *ptr,
+ const PointerRNA value,
+ struct ReportList *UNUSED(reports))
{
bNodeTree *ntree = (bNodeTree *)ptr->data;
bNode *node = (bNode *)value.data;
@@ -1610,9 +1610,9 @@ static IDProperty *rna_Node_idprops(PointerRNA *ptr, bool create)
return node->prop;
}
-static void rna_Node_parent_set(struct ReportList *UNUSED(reports),
- PointerRNA *ptr,
- PointerRNA value)
+static void rna_Node_parent_set(PointerRNA *ptr,
+ PointerRNA value,
+ struct ReportList *UNUSED(reports))
{
bNode *node = ptr->data;
bNode *parent = value.data;
@@ -2687,9 +2687,9 @@ static void rna_NodeGroup_update(Main *bmain, Scene *UNUSED(scene), PointerRNA *
ED_node_tag_update_nodetree(bmain, ntree, node);
}
-static void rna_NodeGroup_node_tree_set(struct ReportList *UNUSED(reports),
- PointerRNA *ptr,
- const PointerRNA value)
+static void rna_NodeGroup_node_tree_set(PointerRNA *ptr,
+ const PointerRNA value,
+ struct ReportList *UNUSED(reports))
{
bNodeTree *ntree = ptr->id.data;
bNode *node = ptr->data;
@@ -2797,9 +2797,9 @@ static void rna_Matte_t2_set(PointerRNA *ptr, float value)
chroma->t2 = value;
}
-static void rna_Node_scene_set(struct ReportList *UNUSED(reports),
- PointerRNA *ptr,
- PointerRNA value)
+static void rna_Node_scene_set(PointerRNA *ptr,
+ PointerRNA value,
+ struct ReportList *UNUSED(reports))
{
bNode *node = (bNode *)ptr->data;
@@ -3353,9 +3353,9 @@ static PointerRNA rna_ShaderNodePointDensity_psys_get(PointerRNA *ptr)
return value;
}
-static void rna_ShaderNodePointDensity_psys_set(struct ReportList *UNUSED(reports),
- PointerRNA *ptr,
- PointerRNA value)
+static void rna_ShaderNodePointDensity_psys_set(PointerRNA *ptr,
+ PointerRNA value,
+ struct ReportList *UNUSED(reports))
{
bNode *node = ptr->data;
NodeShaderTexPointDensity *shader_point_density = node->storage;
diff --git a/source/blender/makesrna/intern/rna_object.c b/source/blender/makesrna/intern/rna_object.c
index b4453996095..e2f566cfdab 100644
--- a/source/blender/makesrna/intern/rna_object.c
+++ b/source/blender/makesrna/intern/rna_object.c
@@ -427,7 +427,7 @@ static void rna_Object_dependency_update(Main *bmain, Scene *UNUSED(scene), Poin
WM_main_add_notifier(NC_OBJECT | ND_PARENT, ptr->id.data);
}
-static void rna_Object_data_set(struct ReportList *reports, PointerRNA *ptr, PointerRNA value)
+static void rna_Object_data_set(PointerRNA *ptr, PointerRNA value, struct ReportList *reports)
{
Object *ob = (Object *)ptr->data;
ID *id = value.data;
@@ -534,9 +534,9 @@ static bool rna_Object_data_poll(PointerRNA *ptr, const PointerRNA value)
return true;
}
-static void rna_Object_parent_set(struct ReportList *UNUSED(reports),
- PointerRNA *ptr,
- PointerRNA value)
+static void rna_Object_parent_set(PointerRNA *ptr,
+ PointerRNA value,
+ struct ReportList *UNUSED(reports))
{
Object *ob = (Object *)ptr->data;
Object *par = (Object *)value.data;
@@ -621,9 +621,9 @@ static const EnumPropertyItem *rna_Object_instance_type_itemf(bContext *UNUSED(C
return item;
}
-static void rna_Object_dup_collection_set(struct ReportList *UNUSED(reports),
- PointerRNA *ptr,
- PointerRNA value)
+static void rna_Object_dup_collection_set(PointerRNA *ptr,
+ PointerRNA value,
+ struct ReportList *UNUSED(reports))
{
Object *ob = (Object *)ptr->data;
Collection *grp = (Collection *)value.data;
@@ -899,9 +899,9 @@ static PointerRNA rna_Object_active_material_get(PointerRNA *ptr)
return rna_pointer_inherit_refine(ptr, &RNA_Material, ma);
}
-static void rna_Object_active_material_set(struct ReportList *UNUSED(reports),
- PointerRNA *ptr,
- PointerRNA value)
+static void rna_Object_active_material_set(PointerRNA *ptr,
+ PointerRNA value,
+ struct ReportList *UNUSED(reports))
{
Object *ob = (Object *)ptr->id.data;
@@ -1100,9 +1100,9 @@ static PointerRNA rna_MaterialSlot_material_get(PointerRNA *ptr)
return rna_pointer_inherit_refine(ptr, &RNA_Material, ma);
}
-static void rna_MaterialSlot_material_set(struct ReportList *UNUSED(reports),
- PointerRNA *ptr,
- PointerRNA value)
+static void rna_MaterialSlot_material_set(PointerRNA *ptr,
+ PointerRNA value,
+ struct ReportList *UNUSED(reports))
{
Object *ob = (Object *)ptr->id.data;
int index = (Material **)ptr->data - ob->mat;
@@ -1290,9 +1290,9 @@ static PointerRNA rna_Object_active_constraint_get(PointerRNA *ptr)
return rna_pointer_inherit_refine(ptr, &RNA_Constraint, con);
}
-static void rna_Object_active_constraint_set(struct ReportList *UNUSED(reports),
- PointerRNA *ptr,
- PointerRNA value)
+static void rna_Object_active_constraint_set(PointerRNA *ptr,
+ PointerRNA value,
+ struct ReportList *UNUSED(reports))
{
Object *ob = (Object *)ptr->id.data;
BKE_constraints_active_set(&ob->constraints, (bConstraint *)value.data);
diff --git a/source/blender/makesrna/intern/rna_object_api.c b/source/blender/makesrna/intern/rna_object_api.c
index 7362f6ba610..f5c83df0f45 100644
--- a/source/blender/makesrna/intern/rna_object_api.c
+++ b/source/blender/makesrna/intern/rna_object_api.c
@@ -375,7 +375,10 @@ static void rna_Object_camera_fit_coords(
}
/* copied from Mesh_getFromObject and adapted to RNA interface */
-static Mesh *rna_Object_to_mesh(Object *object, ReportList *reports)
+static Mesh *rna_Object_to_mesh(Object *object,
+ ReportList *reports,
+ bool preserve_all_data_layers,
+ Depsgraph *depsgraph)
{
/* TODO(sergey): Make it more re-usable function, de-duplicate with
* rna_Main_meshes_new_from_object. */
@@ -391,7 +394,7 @@ static Mesh *rna_Object_to_mesh(Object *object, ReportList *reports)
return NULL;
}
- return BKE_object_to_mesh(object);
+ return BKE_object_to_mesh(depsgraph, object, preserve_all_data_layers);
}
static void rna_Object_to_mesh_clear(Object *object)
@@ -703,7 +706,13 @@ void rna_Object_me_eval_info(
static bool rna_Object_update_from_editmode(Object *ob, Main *bmain)
{
/* fail gracefully if we aren't in edit-mode. */
- return ED_object_editmode_load(bmain, ob);
+ const bool result = ED_object_editmode_load(bmain, ob);
+ if (result) {
+ /* Loading edit mesh to mesh changes geometry, and scripts might expect it to be properly
+ * informed about changes. */
+ DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY);
+ }
+ return result;
}
#else /* RNA_RUNTIME */
@@ -898,6 +907,19 @@ void RNA_api_object(StructRNA *srna)
"data-block. To force free it use to_mesh_clear(). "
"The result is temporary and can not be used by objects from the main database");
RNA_def_function_flag(func, FUNC_USE_REPORTS);
+ RNA_def_boolean(func,
+ "preserve_all_data_layers",
+ false,
+ "",
+ "Preserve all data layers in the mesh, like UV maps and vertex groups. "
+ "By default Blender only computes the subset of data layers needed for viewport "
+ "display and rendering, for better performance");
+ RNA_def_pointer(
+ func,
+ "depsgraph",
+ "Depsgraph",
+ "Dependency Graph",
+ "Evaluated dependency graph which is required when preserve_all_data_layers is true");
parm = RNA_def_pointer(func, "mesh", "Mesh", "", "Mesh created from object");
RNA_def_function_return(func, parm);
diff --git a/source/blender/makesrna/intern/rna_palette.c b/source/blender/makesrna/intern/rna_palette.c
index cd6ed9bc7e4..9af6387389c 100644
--- a/source/blender/makesrna/intern/rna_palette.c
+++ b/source/blender/makesrna/intern/rna_palette.c
@@ -74,9 +74,9 @@ static PointerRNA rna_Palette_active_color_get(PointerRNA *ptr)
return rna_pointer_inherit_refine(ptr, NULL, NULL);
}
-static void rna_Palette_active_color_set(struct ReportList *UNUSED(reports),
- PointerRNA *ptr,
- PointerRNA value)
+static void rna_Palette_active_color_set(PointerRNA *ptr,
+ PointerRNA value,
+ struct ReportList *UNUSED(reports))
{
Palette *palette = ptr->data;
PaletteColor *color = value.data;
diff --git a/source/blender/makesrna/intern/rna_particle.c b/source/blender/makesrna/intern/rna_particle.c
index 9ef5bcd4fd1..a3178e0407f 100644
--- a/source/blender/makesrna/intern/rna_particle.c
+++ b/source/blender/makesrna/intern/rna_particle.c
@@ -534,6 +534,11 @@ static void rna_ParticleSystem_uv_on_emitter(ParticleSystem *particlesystem,
int uv_no,
float r_uv[2])
{
+ if (modifier->mesh_final == NULL) {
+ BKE_report(reports, RPT_ERROR, "Object was not yet evaluated");
+ zero_v2(r_uv);
+ return;
+ }
if (!CustomData_has_layer(&modifier->mesh_final->ldata, CD_MLOOPUV)) {
BKE_report(reports, RPT_ERROR, "Mesh has no UV data");
zero_v2(r_uv);
@@ -792,9 +797,9 @@ static PointerRNA rna_particle_settings_get(PointerRNA *ptr)
return rna_pointer_inherit_refine(ptr, &RNA_ParticleSettings, part);
}
-static void rna_particle_settings_set(struct ReportList *UNUSED(reports),
- PointerRNA *ptr,
- PointerRNA value)
+static void rna_particle_settings_set(PointerRNA *ptr,
+ PointerRNA value,
+ struct ReportList *UNUSED(reports))
{
Object *ob = ptr->id.data;
ParticleSystem *psys = (ParticleSystem *)ptr->data;
@@ -1320,9 +1325,9 @@ static PointerRNA rna_ParticleSettings_active_texture_get(PointerRNA *ptr)
return rna_pointer_inherit_refine(ptr, &RNA_Texture, tex);
}
-static void rna_ParticleSettings_active_texture_set(struct ReportList *UNUSED(reports),
- PointerRNA *ptr,
- PointerRNA value)
+static void rna_ParticleSettings_active_texture_set(PointerRNA *ptr,
+ PointerRNA value,
+ struct ReportList *UNUSED(reports))
{
ParticleSettings *part = (ParticleSettings *)ptr->data;
diff --git a/source/blender/makesrna/intern/rna_pose.c b/source/blender/makesrna/intern/rna_pose.c
index 7b91248feac..3ab41f72322 100644
--- a/source/blender/makesrna/intern/rna_pose.c
+++ b/source/blender/makesrna/intern/rna_pose.c
@@ -373,9 +373,9 @@ static void rna_Itasc_update_rebuild(Main *bmain, Scene *scene, PointerRNA *ptr)
rna_Itasc_update(bmain, scene, ptr);
}
-static void rna_PoseChannel_bone_custom_set(struct ReportList *UNUSED(reports),
- PointerRNA *ptr,
- PointerRNA value)
+static void rna_PoseChannel_bone_custom_set(PointerRNA *ptr,
+ PointerRNA value,
+ struct ReportList *UNUSED(reports))
{
bPoseChannel *pchan = (bPoseChannel *)ptr->data;
@@ -404,9 +404,9 @@ static PointerRNA rna_PoseChannel_bone_group_get(PointerRNA *ptr)
return rna_pointer_inherit_refine(ptr, &RNA_BoneGroup, grp);
}
-static void rna_PoseChannel_bone_group_set(struct ReportList *UNUSED(reports),
- PointerRNA *ptr,
- PointerRNA value)
+static void rna_PoseChannel_bone_group_set(PointerRNA *ptr,
+ PointerRNA value,
+ struct ReportList *UNUSED(reports))
{
Object *ob = (Object *)ptr->id.data;
bPose *pose = (ob) ? ob->pose : NULL;
@@ -447,9 +447,9 @@ static PointerRNA rna_Pose_active_bone_group_get(PointerRNA *ptr)
ptr, &RNA_BoneGroup, BLI_findlink(&pose->agroups, pose->active_group - 1));
}
-static void rna_Pose_active_bone_group_set(struct ReportList *UNUSED(reports),
- PointerRNA *ptr,
- PointerRNA value)
+static void rna_Pose_active_bone_group_set(PointerRNA *ptr,
+ PointerRNA value,
+ struct ReportList *UNUSED(reports))
{
bPose *pose = (bPose *)ptr->data;
pose->active_group = BLI_findindex(&pose->agroups, value.data) + 1;
@@ -538,9 +538,9 @@ static PointerRNA rna_PoseChannel_active_constraint_get(PointerRNA *ptr)
return rna_pointer_inherit_refine(ptr, &RNA_Constraint, con);
}
-static void rna_PoseChannel_active_constraint_set(struct ReportList *UNUSED(reports),
- PointerRNA *ptr,
- PointerRNA value)
+static void rna_PoseChannel_active_constraint_set(PointerRNA *ptr,
+ PointerRNA value,
+ struct ReportList *UNUSED(reports))
{
bPoseChannel *pchan = (bPoseChannel *)ptr->data;
BKE_constraints_active_set(&pchan->constraints, (bConstraint *)value.data);
@@ -778,9 +778,9 @@ static bPoseChannel *rna_PoseChannel_ensure_own_pchan(Object *ob,
return ref_pchan;
}
-static void rna_PoseChannel_custom_shape_transform_set(struct ReportList *UNUSED(reports),
- PointerRNA *ptr,
- PointerRNA value)
+static void rna_PoseChannel_custom_shape_transform_set(PointerRNA *ptr,
+ PointerRNA value,
+ struct ReportList *UNUSED(reports))
{
bPoseChannel *pchan = (bPoseChannel *)ptr->data;
Object *ob = (Object *)ptr->id.data;
diff --git a/source/blender/makesrna/intern/rna_rna.c b/source/blender/makesrna/intern/rna_rna.c
index c5eff47c3aa..b8d42397841 100644
--- a/source/blender/makesrna/intern/rna_rna.c
+++ b/source/blender/makesrna/intern/rna_rna.c
@@ -2373,7 +2373,7 @@ bool rna_property_override_apply_default(Main *UNUSED(bmain),
switch (override_op) {
case IDOVERRIDESTATIC_OP_REPLACE:
- RNA_property_pointer_set(NULL, ptr_dst, prop_dst, value);
+ RNA_property_pointer_set(ptr_dst, prop_dst, value, NULL);
break;
default:
BLI_assert(0 && "Unsupported RNA override operation on pointer");
diff --git a/source/blender/makesrna/intern/rna_scene.c b/source/blender/makesrna/intern/rna_scene.c
index 55e2428235f..1dc9e71e87c 100644
--- a/source/blender/makesrna/intern/rna_scene.c
+++ b/source/blender/makesrna/intern/rna_scene.c
@@ -773,9 +773,9 @@ static PointerRNA rna_Scene_objects_get(CollectionPropertyIterator *iter)
/* End of read-only Iterator of all the scene objects. */
-static void rna_Scene_set_set(struct ReportList *UNUSED(reports),
- PointerRNA *ptr,
- PointerRNA value)
+static void rna_Scene_set_set(PointerRNA *ptr,
+ PointerRNA value,
+ struct ReportList *UNUSED(reports))
{
Scene *scene = (Scene *)ptr->data;
Scene *set = (Scene *)value.data;
@@ -972,9 +972,9 @@ static PointerRNA rna_Scene_active_keying_set_get(PointerRNA *ptr)
return rna_pointer_inherit_refine(ptr, &RNA_KeyingSet, ANIM_scene_get_active_keyingset(scene));
}
-static void rna_Scene_active_keying_set_set(struct ReportList *UNUSED(reports),
- PointerRNA *ptr,
- PointerRNA value)
+static void rna_Scene_active_keying_set_set(PointerRNA *ptr,
+ PointerRNA value,
+ struct ReportList *UNUSED(reports))
{
Scene *scene = (Scene *)ptr->data;
KeyingSet *ks = (KeyingSet *)value.data;
@@ -1440,9 +1440,9 @@ static PointerRNA rna_RenderSettings_active_view_get(PointerRNA *ptr)
return rna_pointer_inherit_refine(ptr, &RNA_SceneRenderView, srv);
}
-static void rna_RenderSettings_active_view_set(struct ReportList *UNUSED(reports),
- PointerRNA *ptr,
- PointerRNA value)
+static void rna_RenderSettings_active_view_set(PointerRNA *ptr,
+ PointerRNA value,
+ struct ReportList *UNUSED(reports))
{
RenderData *rd = (RenderData *)ptr->data;
SceneRenderView *srv = (SceneRenderView *)value.data;
@@ -2047,9 +2047,9 @@ PointerRNA rna_FreestyleLineSet_linestyle_get(PointerRNA *ptr)
return rna_pointer_inherit_refine(ptr, &RNA_FreestyleLineStyle, lineset->linestyle);
}
-void rna_FreestyleLineSet_linestyle_set(struct ReportList *UNUSED(reports),
- PointerRNA *ptr,
- PointerRNA value)
+void rna_FreestyleLineSet_linestyle_set(PointerRNA *ptr,
+ PointerRNA value,
+ struct ReportList *UNUSED(reports))
{
FreestyleLineSet *lineset = (FreestyleLineSet *)ptr->data;
@@ -2645,23 +2645,6 @@ static void rna_def_tool_settings(BlenderRNA *brna)
{0, NULL, 0, NULL, NULL},
};
- static const EnumPropertyItem edge_tag_items[] = {
- {EDGE_MODE_SELECT, "SELECT", 0, "Select", ""},
- {EDGE_MODE_TAG_SEAM, "SEAM", 0, "Tag Seam", ""},
- {EDGE_MODE_TAG_SHARP, "SHARP", 0, "Tag Sharp", ""},
- {EDGE_MODE_TAG_CREASE, "CREASE", 0, "Tag Crease", ""},
- {EDGE_MODE_TAG_BEVEL, "BEVEL", 0, "Tag Bevel", ""},
- {EDGE_MODE_TAG_FREESTYLE, "FREESTYLE", 0, "Tag Freestyle Edge Mark", ""},
- {0, NULL, 0, NULL, NULL},
- };
-
- static EnumPropertyItem mod_weighted_strength[] = {
- {FACE_STRENGTH_WEAK, "Weak", 0, "Weak", ""},
- {FACE_STRENGTH_MEDIUM, "Medium", 0, "Medium", ""},
- {FACE_STRENGTH_STRONG, "Strong", 0, "Strong", ""},
- {0, NULL, 0, NULL, NULL},
- };
-
static const EnumPropertyItem draw_groupuser_items[] = {
{OB_DRAW_GROUPUSER_NONE, "NONE", 0, "None", ""},
{OB_DRAW_GROUPUSER_ACTIVE,
@@ -2903,8 +2886,7 @@ static void rna_def_tool_settings(BlenderRNA *brna)
prop = RNA_def_property(srna, "double_threshold", PROP_FLOAT, PROP_DISTANCE);
RNA_def_property_float_sdna(prop, NULL, "doublimit");
- RNA_def_property_ui_text(
- prop, "Double Threshold", "Limit for removing duplicates and 'Auto Merge'");
+ RNA_def_property_ui_text(prop, "Merge Threshold", "Threshold distance for Auto Merge");
RNA_def_property_range(prop, 0.0, 1.0);
RNA_def_property_ui_range(prop, 0.0, 0.1, 0.01, 6);
@@ -2925,7 +2907,8 @@ static void rna_def_tool_settings(BlenderRNA *brna)
prop = RNA_def_property(srna, "use_mesh_automerge", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "automerge", 0);
RNA_def_property_ui_text(
- prop, "AutoMerge Editing", "Automatically merge vertices moved to the same location");
+ prop, "Auto Merge", "Automatically merge vertices moved to the same location");
+ RNA_def_property_ui_icon(prop, ICON_AUTOMERGE_OFF, 1);
RNA_def_property_update(prop, NC_SCENE | ND_TOOLSETTINGS, NULL); /* header redraw */
prop = RNA_def_property(srna, "use_snap", PROP_BOOLEAN, PROP_NONE);
@@ -3203,13 +3186,6 @@ static void rna_def_tool_settings(BlenderRNA *brna)
RNA_def_property_float_sdna(prop, NULL, "vgroup_weight");
RNA_def_property_ui_text(prop, "Vertex Group Weight", "Weight to assign in vertex groups");
- /* use with MESH_OT_shortest_path_pick */
- prop = RNA_def_property(srna, "edge_path_mode", PROP_ENUM, PROP_NONE);
- RNA_def_property_enum_sdna(prop, NULL, "edge_mode");
- RNA_def_property_enum_items(prop, edge_tag_items);
- RNA_def_property_ui_text(
- prop, "Edge Tag Mode", "The edge flag to tag when selecting the shortest path");
-
prop = RNA_def_property(srna, "use_edge_path_live_unwrap", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "edge_mode_live_unwrap", 1);
RNA_def_property_ui_text(prop, "Live Unwrap", "Changing edges seam re-calculates UV unwrap");
@@ -3218,10 +3194,6 @@ static void rna_def_tool_settings(BlenderRNA *brna)
RNA_def_property_ui_text(prop, "Normal Vector", "Normal Vector used to copy, add or multiply");
RNA_def_property_ui_range(prop, -10000.0, 10000.0, 1, 3);
- prop = RNA_def_property(srna, "face_strength", PROP_ENUM, PROP_NONE);
- RNA_def_property_enum_items(prop, mod_weighted_strength);
- RNA_def_property_ui_text(prop, "Face Strength", "Set strength of face to specified value");
-
/* Unified Paint Settings */
prop = RNA_def_property(srna, "unified_paint_settings", PROP_POINTER, PROP_NONE);
RNA_def_property_flag(prop, PROP_NEVER_NULL);
@@ -6663,7 +6635,7 @@ static void rna_def_scene_eevee(BlenderRNA *brna)
RNA_def_property_override_flag(prop, PROPOVERRIDE_OVERRIDABLE_STATIC);
prop = RNA_def_property(srna, "gi_filter_quality", PROP_FLOAT, PROP_NONE);
- RNA_def_property_float_default(prop, 1.0f);
+ RNA_def_property_float_default(prop, 3.0f);
RNA_def_property_ui_text(
prop, "Filter Quality", "Take more samples during cubemap filtering to remove artifacts");
RNA_def_property_range(prop, 1.0f, 8.0f);
diff --git a/source/blender/makesrna/intern/rna_sequencer.c b/source/blender/makesrna/intern/rna_sequencer.c
index 687ba96abc2..5a80dc5fe8c 100644
--- a/source/blender/makesrna/intern/rna_sequencer.c
+++ b/source/blender/makesrna/intern/rna_sequencer.c
@@ -106,12 +106,14 @@ static void rna_SequenceElement_update(Main *UNUSED(bmain), Scene *UNUSED(scene)
/* slow but we can't avoid! */
seq = BKE_sequencer_from_elem(&ed->seqbase, se);
if (seq) {
- BKE_sequence_invalidate_cache(scene, seq);
+ BKE_sequence_invalidate_cache_raw(scene, seq);
}
}
}
-static void rna_Sequence_update(Main *UNUSED(bmain), Scene *UNUSED(scene), PointerRNA *ptr)
+static void rna_Sequence_invalidate_raw_update(Main *UNUSED(bmain),
+ Scene *UNUSED(scene),
+ PointerRNA *ptr)
{
Scene *scene = (Scene *)ptr->id.data;
Editing *ed = BKE_sequencer_editing_get(scene, false);
@@ -119,7 +121,35 @@ static void rna_Sequence_update(Main *UNUSED(bmain), Scene *UNUSED(scene), Point
if (ed) {
Sequence *seq = (Sequence *)ptr->data;
- BKE_sequence_invalidate_cache(scene, seq);
+ BKE_sequence_invalidate_cache_raw(scene, seq);
+ }
+}
+
+static void rna_Sequence_invalidate_preprocessed_update(Main *UNUSED(bmain),
+ Scene *UNUSED(scene),
+ PointerRNA *ptr)
+{
+ Scene *scene = (Scene *)ptr->id.data;
+ Editing *ed = BKE_sequencer_editing_get(scene, false);
+
+ if (ed) {
+ Sequence *seq = (Sequence *)ptr->data;
+
+ BKE_sequence_invalidate_cache_preprocessed(scene, seq);
+ }
+}
+
+static void rna_Sequence_invalidate_composite_update(Main *UNUSED(bmain),
+ Scene *UNUSED(scene),
+ PointerRNA *ptr)
+{
+ Scene *scene = (Scene *)ptr->id.data;
+ Editing *ed = BKE_sequencer_editing_get(scene, false);
+
+ if (ed) {
+ Sequence *seq = (Sequence *)ptr->data;
+
+ BKE_sequence_invalidate_cache_composite(scene, seq);
}
}
@@ -141,6 +171,7 @@ static void rna_SequenceEditor_update_cache(Main *UNUSED(bmain),
Editing *ed = scene->ed;
BKE_sequencer_free_imbuf(scene, &ed->seqbase, false);
+ BKE_sequencer_cache_cleanup(scene);
}
static void rna_SequenceEditor_sequences_all_next(CollectionPropertyIterator *iter)
@@ -193,7 +224,7 @@ static void rna_SequenceEditor_elements_begin(CollectionPropertyIterator *iter,
static void rna_Sequence_views_format_update(Main *bmain, Scene *scene, PointerRNA *ptr)
{
- rna_Sequence_update(bmain, scene, ptr);
+ rna_Sequence_invalidate_raw_update(bmain, scene, ptr);
}
static void do_sequence_frame_change_update(Scene *scene, Sequence *seq)
@@ -227,7 +258,7 @@ static void rna_Sequence_frame_change_update(Main *bmain, Scene *UNUSED(scene),
{
Scene *scene = (Scene *)ptr->id.data;
do_sequence_frame_change_update(scene, (Sequence *)ptr->data);
- rna_Sequence_update(bmain, scene, ptr);
+ rna_Sequence_invalidate_preprocessed_update(bmain, scene, ptr);
}
static void rna_Sequence_start_frame_set(PointerRNA *ptr, int value)
@@ -412,7 +443,7 @@ static void rna_SequenceTransform_update(Main *UNUSED(bmain),
Editing *ed = BKE_sequencer_editing_get(scene, false);
Sequence *seq = sequence_get_by_transform(ed, ptr->data);
- BKE_sequence_invalidate_cache(scene, seq);
+ BKE_sequence_invalidate_cache_preprocessed(scene, seq);
}
static int crop_seq_cmp_cb(Sequence *seq, void *arg_pt)
@@ -462,12 +493,12 @@ static void rna_SequenceCrop_update(Main *UNUSED(bmain), Scene *UNUSED(scene), P
Editing *ed = BKE_sequencer_editing_get(scene, false);
Sequence *seq = sequence_get_by_crop(ed, ptr->data);
- BKE_sequence_invalidate_cache(scene, seq);
+ BKE_sequence_invalidate_cache_preprocessed(scene, seq);
}
-static void rna_Sequence_text_font_set(struct ReportList *UNUSED(reports),
- PointerRNA *ptr,
- PointerRNA ptr_value)
+static void rna_Sequence_text_font_set(PointerRNA *ptr,
+ PointerRNA ptr_value,
+ struct ReportList *UNUSED(reports))
{
Sequence *seq = ptr->data;
TextVars *data = seq->effectdata;
@@ -748,26 +779,24 @@ static void rna_SequenceElement_filename_set(PointerRNA *ptr, const char *value)
}
# endif
-static void rna_Sequence_update_reopen_files(Main *UNUSED(bmain),
- Scene *UNUSED(scene),
- PointerRNA *ptr)
+static void rna_Sequence_reopen_files_update(Main *bmain, Scene *UNUSED(scene), PointerRNA *ptr)
{
Scene *scene = (Scene *)ptr->id.data;
Editing *ed = BKE_sequencer_editing_get(scene, false);
BKE_sequencer_free_imbuf(scene, &ed->seqbase, false);
+ rna_Sequence_invalidate_raw_update(bmain, scene, ptr);
if (RNA_struct_is_a(ptr->type, &RNA_SoundSequence))
BKE_sequencer_update_sound_bounds(scene, ptr->data);
}
-static void rna_Sequence_mute_update(Main *bmain, Scene *UNUSED(scene), PointerRNA *ptr)
+static void rna_Sequence_mute_update(Main *UNUSED(bmain), Scene *UNUSED(scene), PointerRNA *ptr)
{
Scene *scene = (Scene *)ptr->id.data;
Editing *ed = BKE_sequencer_editing_get(scene, false);
BKE_sequencer_update_muting(ed);
- rna_Sequence_update(bmain, scene, ptr);
}
static void rna_Sequence_filepath_update(Main *bmain, Scene *UNUSED(scene), PointerRNA *ptr)
@@ -776,16 +805,15 @@ static void rna_Sequence_filepath_update(Main *bmain, Scene *UNUSED(scene), Poin
Sequence *seq = (Sequence *)(ptr->data);
BKE_sequence_reload_new_file(scene, seq, true);
BKE_sequence_calc(scene, seq);
- rna_Sequence_update(bmain, scene, ptr);
+ rna_Sequence_invalidate_raw_update(bmain, scene, ptr);
}
-static void rna_Sequence_sound_update(Main *bmain, Scene *scene, PointerRNA *ptr)
+static void rna_Sequence_sound_update(Main *UNUSED(bmain), Scene *UNUSED(scene), PointerRNA *ptr)
{
Sequence *seq = (Sequence *)ptr->data;
if (seq->sound != NULL) {
BKE_sound_update_scene_sound(seq->scene_sound, seq->sound);
}
- rna_Sequence_update(bmain, scene, ptr);
}
static int seqproxy_seq_cmp_cb(Sequence *seq, void *arg_pt)
@@ -826,7 +854,7 @@ static void rna_SequenceProxy_update(Main *UNUSED(bmain), Scene *UNUSED(scene),
Editing *ed = BKE_sequencer_editing_get(scene, false);
Sequence *seq = sequence_get_by_proxy(ed, ptr->data);
- BKE_sequence_invalidate_cache(scene, seq);
+ BKE_sequence_invalidate_cache_raw(scene, seq);
}
/* do_versions? */
@@ -922,10 +950,7 @@ static void rna_SequenceColorBalance_update(Main *UNUSED(bmain),
SequenceModifierData *smd;
Sequence *seq = sequence_get_by_colorbalance(ed, ptr->data, &smd);
- if (smd == NULL)
- BKE_sequence_invalidate_cache(scene, seq);
- else
- BKE_sequence_invalidate_cache_for_modifier(scene, seq);
+ BKE_sequence_invalidate_cache_preprocessed(scene, seq);
}
static void rna_SequenceEditor_overlay_lock_set(PointerRNA *ptr, bool value)
@@ -1079,7 +1104,7 @@ static void rna_SequenceModifier_update(Main *UNUSED(bmain), Scene *UNUSED(scene
Editing *ed = BKE_sequencer_editing_get(scene, false);
Sequence *seq = sequence_get_by_modifier(ed, ptr->data);
- BKE_sequence_invalidate_cache_for_modifier(scene, seq);
+ BKE_sequence_invalidate_cache_preprocessed(scene, seq);
}
static bool rna_SequenceModifier_otherSequence_poll(PointerRNA *ptr, PointerRNA value)
@@ -1110,7 +1135,7 @@ static SequenceModifierData *rna_Sequence_modifier_new(
smd = BKE_sequence_modifier_new(seq, name, type);
- BKE_sequence_invalidate_cache_for_modifier(scene, seq);
+ BKE_sequence_invalidate_cache_preprocessed(scene, seq);
WM_main_add_notifier(NC_SCENE | ND_SEQUENCER, NULL);
@@ -1132,7 +1157,7 @@ static void rna_Sequence_modifier_remove(Sequence *seq,
}
RNA_POINTER_INVALIDATE(smd_ptr);
- BKE_sequence_invalidate_cache_for_modifier(scene, seq);
+ BKE_sequence_invalidate_cache_preprocessed(scene, seq);
WM_main_add_notifier(NC_SCENE | ND_SEQUENCER, NULL);
}
@@ -1143,7 +1168,7 @@ static void rna_Sequence_modifier_clear(Sequence *seq, bContext *C)
BKE_sequence_modifier_clear(seq);
- BKE_sequence_invalidate_cache_for_modifier(scene, seq);
+ BKE_sequence_invalidate_cache_preprocessed(scene, seq);
WM_main_add_notifier(NC_SCENE | ND_SEQUENCER, NULL);
}
@@ -1342,12 +1367,12 @@ static void rna_def_strip_proxy(BlenderRNA *brna)
prop = RNA_def_property(srna, "use_proxy_custom_directory", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "storage", SEQ_STORAGE_PROXY_CUSTOM_DIR);
RNA_def_property_ui_text(prop, "Proxy Custom Directory", "Use a custom directory to store data");
- RNA_def_property_update(prop, NC_SCENE | ND_SEQUENCER, "rna_Sequence_update");
+ RNA_def_property_update(prop, NC_SCENE | ND_SEQUENCER, "rna_Sequence_invalidate_raw_update");
prop = RNA_def_property(srna, "use_proxy_custom_file", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "storage", SEQ_STORAGE_PROXY_CUSTOM_FILE);
RNA_def_property_ui_text(prop, "Proxy Custom File", "Use a custom file to read proxy data from");
- RNA_def_property_update(prop, NC_SCENE | ND_SEQUENCER, "rna_Sequence_update");
+ RNA_def_property_update(prop, NC_SCENE | ND_SEQUENCER, "rna_Sequence_invalidate_raw_update");
}
static void rna_def_color_balance(BlenderRNA *brna)
@@ -1555,7 +1580,7 @@ static void rna_def_sequence(BlenderRNA *brna)
RNA_def_property_enum_items(prop, seq_type_items);
RNA_def_property_ui_text(prop, "Type", "");
RNA_def_property_translation_context(prop, BLT_I18NCONTEXT_ID_SEQUENCE);
- RNA_def_property_update(prop, NC_SCENE | ND_SEQUENCER, "rna_Sequence_update");
+ RNA_def_property_update(prop, NC_SCENE | ND_SEQUENCER, "rna_Sequence_invalidate_raw_update");
/* flags */
prop = RNA_def_property(srna, "select", PROP_BOOLEAN, PROP_NONE);
@@ -1596,7 +1621,8 @@ static void rna_def_sequence(BlenderRNA *brna)
RNA_def_property_int_funcs(
prop, "rna_Sequence_frame_length_get", "rna_Sequence_frame_length_set", NULL);
RNA_def_property_editable_func(prop, "rna_Sequence_frame_editable");
- RNA_def_property_update(prop, NC_SCENE | ND_SEQUENCER, "rna_Sequence_update");
+ RNA_def_property_update(
+ prop, NC_SCENE | ND_SEQUENCER, "rna_Sequence_invalidate_preprocessed_update");
prop = RNA_def_property(srna, "frame_duration", PROP_INT, PROP_TIME);
RNA_def_property_int_sdna(prop, NULL, "len");
@@ -1612,7 +1638,8 @@ static void rna_def_sequence(BlenderRNA *brna)
RNA_def_property_int_funcs(
prop, NULL, "rna_Sequence_start_frame_set", NULL); /* overlap tests and calc_seq_disp */
RNA_def_property_editable_func(prop, "rna_Sequence_frame_editable");
- RNA_def_property_update(prop, NC_SCENE | ND_SEQUENCER, "rna_Sequence_update");
+ RNA_def_property_update(
+ prop, NC_SCENE | ND_SEQUENCER, "rna_Sequence_invalidate_preprocessed_update");
prop = RNA_def_property(srna, "frame_final_start", PROP_INT, PROP_TIME);
RNA_def_property_int_sdna(prop, NULL, "startdisp");
@@ -1625,7 +1652,8 @@ static void rna_def_sequence(BlenderRNA *brna)
/* overlap tests and calc_seq_disp */
RNA_def_property_int_funcs(prop, NULL, "rna_Sequence_start_frame_final_set", NULL);
RNA_def_property_editable_func(prop, "rna_Sequence_frame_editable");
- RNA_def_property_update(prop, NC_SCENE | ND_SEQUENCER, "rna_Sequence_update");
+ RNA_def_property_update(
+ prop, NC_SCENE | ND_SEQUENCER, "rna_Sequence_invalidate_preprocessed_update");
prop = RNA_def_property(srna, "frame_final_end", PROP_INT, PROP_TIME);
RNA_def_property_int_sdna(prop, NULL, "enddisp");
@@ -1635,7 +1663,8 @@ static void rna_def_sequence(BlenderRNA *brna)
/* overlap tests and calc_seq_disp */
RNA_def_property_int_funcs(prop, NULL, "rna_Sequence_end_frame_final_set", NULL);
RNA_def_property_editable_func(prop, "rna_Sequence_frame_editable");
- RNA_def_property_update(prop, NC_SCENE | ND_SEQUENCER, "rna_Sequence_update");
+ RNA_def_property_update(
+ prop, NC_SCENE | ND_SEQUENCER, "rna_Sequence_invalidate_preprocessed_update");
prop = RNA_def_property(srna, "frame_offset_start", PROP_INT, PROP_TIME);
RNA_def_property_int_sdna(prop, NULL, "startofs");
@@ -1671,14 +1700,16 @@ static void rna_def_sequence(BlenderRNA *brna)
RNA_def_property_range(prop, 1, MAXSEQ);
RNA_def_property_ui_text(prop, "Channel", "Y position of the sequence strip");
RNA_def_property_int_funcs(prop, NULL, "rna_Sequence_channel_set", NULL); /* overlap test */
- RNA_def_property_update(prop, NC_SCENE | ND_SEQUENCER, "rna_Sequence_update");
+ RNA_def_property_update(
+ prop, NC_SCENE | ND_SEQUENCER, "rna_Sequence_invalidate_preprocessed_update");
prop = RNA_def_property(srna, "use_linear_modifiers", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "flag", SEQ_USE_LINEAR_MODIFIERS);
RNA_def_property_ui_text(prop,
"Use Linear Modifiers",
"Calculate modifiers in linear space instead of sequencer's space");
- RNA_def_property_update(prop, NC_SCENE | ND_SEQUENCER, "rna_Sequence_update");
+ RNA_def_property_update(
+ prop, NC_SCENE | ND_SEQUENCER, "rna_Sequence_invalidate_preprocessed_update");
/* blending */
@@ -1687,7 +1718,8 @@ static void rna_def_sequence(BlenderRNA *brna)
RNA_def_property_enum_items(prop, blend_mode_items);
RNA_def_property_ui_text(
prop, "Blend Mode", "Method for controlling how the strip combines with other strips");
- RNA_def_property_update(prop, NC_SCENE | ND_SEQUENCER, "rna_Sequence_update");
+ RNA_def_property_update(
+ prop, NC_SCENE | ND_SEQUENCER, "rna_Sequence_invalidate_preprocessed_update");
prop = RNA_def_property(srna, "blend_alpha", PROP_FLOAT, PROP_FACTOR);
RNA_def_property_range(prop, 0.0f, 1.0f);
@@ -1695,14 +1727,16 @@ static void rna_def_sequence(BlenderRNA *brna)
prop, "Blend Opacity", "Percentage of how much the strip's colors affect other strips");
/* stupid 0-100 -> 0-1 */
RNA_def_property_float_funcs(prop, "rna_Sequence_opacity_get", "rna_Sequence_opacity_set", NULL);
- RNA_def_property_update(prop, NC_SCENE | ND_SEQUENCER, "rna_Sequence_update");
+ RNA_def_property_update(
+ prop, NC_SCENE | ND_SEQUENCER, "rna_Sequence_invalidate_composite_update");
prop = RNA_def_property(srna, "effect_fader", PROP_FLOAT, PROP_FACTOR);
RNA_def_property_range(prop, 0.0f, 1.0f);
RNA_def_property_ui_range(prop, 0.0f, 1.0f, 0.1, 3);
RNA_def_property_float_sdna(prop, NULL, "effect_fader");
RNA_def_property_ui_text(prop, "Effect fader position", "Custom fade value");
- RNA_def_property_update(prop, NC_SCENE | ND_SEQUENCER, "rna_Sequence_update");
+ RNA_def_property_update(
+ prop, NC_SCENE | ND_SEQUENCER, "rna_Sequence_invalidate_preprocessed_update");
prop = RNA_def_property(srna, "use_default_fade", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "flag", SEQ_USE_EFFECT_DEFAULT_FADE);
@@ -1711,7 +1745,8 @@ static void rna_def_sequence(BlenderRNA *brna)
"Use Default Fade",
"Fade effect using the built-in default (usually make transition as long as "
"effect strip)");
- RNA_def_property_update(prop, NC_SCENE | ND_SEQUENCER, "rna_Sequence_update");
+ RNA_def_property_update(
+ prop, NC_SCENE | ND_SEQUENCER, "rna_Sequence_invalidate_preprocessed_update");
prop = RNA_def_property(srna, "speed_factor", PROP_FLOAT, PROP_NONE);
RNA_def_property_float_sdna(prop, NULL, "speed_fader");
@@ -1720,7 +1755,8 @@ static void rna_def_sequence(BlenderRNA *brna)
"Speed factor",
"Multiply the current speed of the sequence with this number or remap current frame "
"to this frame");
- RNA_def_property_update(prop, NC_SCENE | ND_SEQUENCER, "rna_Sequence_update");
+ RNA_def_property_update(
+ prop, NC_SCENE | ND_SEQUENCER, "rna_Sequence_invalidate_preprocessed_update");
/* modifiers */
prop = RNA_def_property(srna, "modifiers", PROP_COLLECTION, PROP_NONE);
@@ -1918,40 +1954,41 @@ static void rna_def_filter_video(StructRNA *srna)
prop = RNA_def_property(srna, "use_deinterlace", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "flag", SEQ_FILTERY);
RNA_def_property_ui_text(prop, "Deinterlace", "Remove fields from video movies");
- RNA_def_property_update(prop, NC_SCENE | ND_SEQUENCER, "rna_Sequence_update_reopen_files");
+ RNA_def_property_update(prop, NC_SCENE | ND_SEQUENCER, "rna_Sequence_reopen_files_update");
prop = RNA_def_property(srna, "alpha_mode", PROP_ENUM, PROP_NONE);
RNA_def_property_enum_items(prop, alpha_mode_items);
RNA_def_property_ui_text(
prop, "Alpha Mode", "Representation of alpha information in the RGBA pixels");
- RNA_def_property_update(prop, NC_SCENE | ND_SEQUENCER, "rna_Sequence_update");
+ RNA_def_property_update(prop, NC_SCENE | ND_SEQUENCER, "rna_Sequence_invalidate_raw_update");
prop = RNA_def_property(srna, "use_flip_x", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "flag", SEQ_FLIPX);
RNA_def_property_ui_text(prop, "Flip X", "Flip on the X axis");
- RNA_def_property_update(prop, NC_SCENE | ND_SEQUENCER, "rna_Sequence_update");
+ RNA_def_property_update(prop, NC_SCENE | ND_SEQUENCER, "rna_Sequence_invalidate_raw_update");
prop = RNA_def_property(srna, "use_flip_y", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "flag", SEQ_FLIPY);
RNA_def_property_ui_text(prop, "Flip Y", "Flip on the Y axis");
- RNA_def_property_update(prop, NC_SCENE | ND_SEQUENCER, "rna_Sequence_update");
+ RNA_def_property_update(prop, NC_SCENE | ND_SEQUENCER, "rna_Sequence_invalidate_raw_update");
prop = RNA_def_property(srna, "use_float", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "flag", SEQ_MAKE_FLOAT);
RNA_def_property_ui_text(prop, "Convert Float", "Convert input to float data");
- RNA_def_property_update(prop, NC_SCENE | ND_SEQUENCER, "rna_Sequence_update");
+ RNA_def_property_update(prop, NC_SCENE | ND_SEQUENCER, "rna_Sequence_invalidate_raw_update");
prop = RNA_def_property(srna, "use_reverse_frames", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "flag", SEQ_REVERSE_FRAMES);
RNA_def_property_ui_text(prop, "Flip Time", "Reverse frame order");
- RNA_def_property_update(prop, NC_SCENE | ND_SEQUENCER, "rna_Sequence_update");
+ RNA_def_property_update(prop, NC_SCENE | ND_SEQUENCER, "rna_Sequence_invalidate_raw_update");
prop = RNA_def_property(srna, "color_multiply", PROP_FLOAT, PROP_UNSIGNED);
RNA_def_property_float_sdna(prop, NULL, "mul");
RNA_def_property_range(prop, 0.0f, 20.0f);
RNA_def_property_float_default(prop, 1.0f);
RNA_def_property_ui_text(prop, "Multiply Colors", "");
- RNA_def_property_update(prop, NC_SCENE | ND_SEQUENCER, "rna_Sequence_update");
+ RNA_def_property_update(
+ prop, NC_SCENE | ND_SEQUENCER, "rna_Sequence_invalidate_preprocessed_update");
prop = RNA_def_property(srna, "color_saturation", PROP_FLOAT, PROP_UNSIGNED);
RNA_def_property_float_sdna(prop, NULL, "sat");
@@ -1959,18 +1996,19 @@ static void rna_def_filter_video(StructRNA *srna)
RNA_def_property_ui_range(prop, 0.0f, 2.0f, 3, 3);
RNA_def_property_float_default(prop, 1.0f);
RNA_def_property_ui_text(prop, "Saturation", "Adjust the intensity of the input's color");
- RNA_def_property_update(prop, NC_SCENE | ND_SEQUENCER, "rna_Sequence_update");
+ RNA_def_property_update(
+ prop, NC_SCENE | ND_SEQUENCER, "rna_Sequence_invalidate_preprocessed_update");
prop = RNA_def_property(srna, "strobe", PROP_FLOAT, PROP_NONE);
RNA_def_property_range(prop, 1.0f, 30.0f);
RNA_def_property_ui_text(prop, "Strobe", "Only display every nth frame");
- RNA_def_property_update(prop, NC_SCENE | ND_SEQUENCER, "rna_Sequence_update");
+ RNA_def_property_update(prop, NC_SCENE | ND_SEQUENCER, "rna_Sequence_invalidate_raw_update");
prop = RNA_def_property(srna, "use_translation", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "flag", SEQ_USE_TRANSFORM);
RNA_def_property_ui_text(prop, "Use Translation", "Translate image before processing");
RNA_def_property_boolean_funcs(prop, NULL, "rna_Sequence_use_translation_set");
- RNA_def_property_update(prop, NC_SCENE | ND_SEQUENCER, "rna_Sequence_update");
+ RNA_def_property_update(prop, NC_SCENE | ND_SEQUENCER, "rna_Sequence_invalidate_raw_update");
prop = RNA_def_property(srna, "transform", PROP_POINTER, PROP_NONE);
RNA_def_property_pointer_sdna(prop, NULL, "strip->transform");
@@ -1980,7 +2018,7 @@ static void rna_def_filter_video(StructRNA *srna)
RNA_def_property_boolean_sdna(prop, NULL, "flag", SEQ_USE_CROP);
RNA_def_property_ui_text(prop, "Use Crop", "Crop image before processing");
RNA_def_property_boolean_funcs(prop, NULL, "rna_Sequence_use_crop_set");
- RNA_def_property_update(prop, NC_SCENE | ND_SEQUENCER, "rna_Sequence_update");
+ RNA_def_property_update(prop, NC_SCENE | ND_SEQUENCER, "rna_Sequence_invalidate_raw_update");
prop = RNA_def_property(srna, "crop", PROP_POINTER, PROP_NONE);
RNA_def_property_pointer_sdna(prop, NULL, "strip->crop");
@@ -2012,7 +2050,8 @@ static void rna_def_input(StructRNA *srna)
RNA_def_property_int_funcs(
prop, NULL, "rna_Sequence_anim_startofs_final_set", NULL); /* overlap tests */
RNA_def_property_ui_text(prop, "Animation Start Offset", "Animation start offset (trim start)");
- RNA_def_property_update(prop, NC_SCENE | ND_SEQUENCER, "rna_Sequence_update");
+ RNA_def_property_update(
+ prop, NC_SCENE | ND_SEQUENCER, "rna_Sequence_invalidate_preprocessed_update");
prop = RNA_def_property(srna, "animation_offset_end", PROP_INT, PROP_UNSIGNED);
RNA_def_property_int_sdna(prop, NULL, "anim_endofs");
@@ -2020,7 +2059,8 @@ static void rna_def_input(StructRNA *srna)
RNA_def_property_int_funcs(
prop, NULL, "rna_Sequence_anim_endofs_final_set", NULL); /* overlap tests */
RNA_def_property_ui_text(prop, "Animation End Offset", "Animation end offset (trim end)");
- RNA_def_property_update(prop, NC_SCENE | ND_SEQUENCER, "rna_Sequence_update");
+ RNA_def_property_update(
+ prop, NC_SCENE | ND_SEQUENCER, "rna_Sequence_invalidate_preprocessed_update");
}
static void rna_def_effect_inputs(StructRNA *srna, int count)
@@ -2087,7 +2127,7 @@ static void rna_def_image(BlenderRNA *brna)
prop = RNA_def_property(srna, "directory", PROP_STRING, PROP_DIRPATH);
RNA_def_property_string_sdna(prop, NULL, "strip->dir");
RNA_def_property_ui_text(prop, "Directory", "");
- RNA_def_property_update(prop, NC_SCENE | ND_SEQUENCER, "rna_Sequence_update");
+ RNA_def_property_update(prop, NC_SCENE | ND_SEQUENCER, "rna_Sequence_invalidate_raw_update");
prop = RNA_def_property(srna, "elements", PROP_COLLECTION, PROP_NONE);
RNA_def_property_collection_sdna(prop, NULL, "strip->stripdata", NULL);
@@ -2161,25 +2201,25 @@ static void rna_def_scene(BlenderRNA *brna)
prop = RNA_def_property(srna, "scene", PROP_POINTER, PROP_NONE);
RNA_def_property_flag(prop, PROP_EDITABLE);
RNA_def_property_ui_text(prop, "Scene", "Scene that this sequence uses");
- RNA_def_property_update(prop, NC_SCENE | ND_SEQUENCER, "rna_Sequence_update");
+ RNA_def_property_update(prop, NC_SCENE | ND_SEQUENCER, "rna_Sequence_invalidate_raw_update");
prop = RNA_def_property(srna, "scene_camera", PROP_POINTER, PROP_NONE);
RNA_def_property_flag(prop, PROP_EDITABLE);
RNA_def_property_pointer_funcs(prop, NULL, NULL, NULL, "rna_Camera_object_poll");
RNA_def_property_ui_text(prop, "Camera Override", "Override the scenes active camera");
- RNA_def_property_update(prop, NC_SCENE | ND_SEQUENCER, "rna_Sequence_update");
+ RNA_def_property_update(prop, NC_SCENE | ND_SEQUENCER, "rna_Sequence_invalidate_raw_update");
prop = RNA_def_property(srna, "use_sequence", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "flag", SEQ_SCENE_STRIPS);
RNA_def_property_ui_text(
prop, "Use Sequence", "Use scenes sequence strips directly, instead of rendering");
- RNA_def_property_update(prop, NC_SCENE | ND_SEQUENCER, "rna_Sequence_update");
+ RNA_def_property_update(prop, NC_SCENE | ND_SEQUENCER, "rna_Sequence_invalidate_raw_update");
prop = RNA_def_property(srna, "use_grease_pencil", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_negative_sdna(prop, NULL, "flag", SEQ_SCENE_NO_GPENCIL);
RNA_def_property_ui_text(
prop, "Use Grease Pencil", "Show Grease Pencil strokes in OpenGL previews");
- RNA_def_property_update(prop, NC_SCENE | ND_SEQUENCER, "rna_Sequence_update");
+ RNA_def_property_update(prop, NC_SCENE | ND_SEQUENCER, NULL);
rna_def_filter_video(srna);
rna_def_proxy(srna);
@@ -2202,7 +2242,7 @@ static void rna_def_movie(BlenderRNA *brna)
RNA_def_property_int_sdna(prop, NULL, "anim_preseek");
RNA_def_property_range(prop, 0, 50);
RNA_def_property_ui_text(prop, "MPEG Preseek", "For MPEG movies, preseek this many frames");
- RNA_def_property_update(prop, NC_SCENE | ND_SEQUENCER, "rna_Sequence_update");
+ RNA_def_property_update(prop, NC_SCENE | ND_SEQUENCER, NULL);
prop = RNA_def_property(srna, "stream_index", PROP_INT, PROP_NONE);
RNA_def_property_int_sdna(prop, NULL, "streamindex");
@@ -2211,7 +2251,7 @@ static void rna_def_movie(BlenderRNA *brna)
prop,
"Stream Index",
"For files with several movie streams, use the stream with the given index");
- RNA_def_property_update(prop, NC_SCENE | ND_SEQUENCER, "rna_Sequence_update_reopen_files");
+ RNA_def_property_update(prop, NC_SCENE | ND_SEQUENCER, "rna_Sequence_reopen_files_update");
prop = RNA_def_property(srna, "elements", PROP_COLLECTION, PROP_NONE);
RNA_def_property_collection_sdna(prop, NULL, "strip->stripdata", NULL);
@@ -2284,12 +2324,12 @@ static void rna_def_movieclip(BlenderRNA *brna)
prop = RNA_def_property(srna, "undistort", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "clip_flag", SEQ_MOVIECLIP_RENDER_UNDISTORTED);
RNA_def_property_ui_text(prop, "Undistort Clip", "Use the undistorted version of the clip");
- RNA_def_property_update(prop, NC_SCENE | ND_SEQUENCER, "rna_Sequence_update");
+ RNA_def_property_update(prop, NC_SCENE | ND_SEQUENCER, "rna_Sequence_invalidate_raw_update");
prop = RNA_def_property(srna, "stabilize2d", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "clip_flag", SEQ_MOVIECLIP_RENDER_STABILIZED);
RNA_def_property_ui_text(prop, "Stabilize 2D Clip", "Use the 2D stabilized version of the clip");
- RNA_def_property_update(prop, NC_SCENE | ND_SEQUENCER, "rna_Sequence_update");
+ RNA_def_property_update(prop, NC_SCENE | ND_SEQUENCER, "rna_Sequence_invalidate_raw_update");
rna_def_filter_video(srna);
rna_def_input(srna);
@@ -2308,7 +2348,7 @@ static void rna_def_mask(BlenderRNA *brna)
prop = RNA_def_property(srna, "mask", PROP_POINTER, PROP_NONE);
RNA_def_property_flag(prop, PROP_EDITABLE);
RNA_def_property_ui_text(prop, "Mask", "Mask that this sequence uses");
- RNA_def_property_update(prop, NC_SCENE | ND_SEQUENCER, "rna_Sequence_update");
+ RNA_def_property_update(prop, NC_SCENE | ND_SEQUENCER, "rna_Sequence_invalidate_raw_update");
rna_def_filter_video(srna);
rna_def_input(srna);
@@ -2337,7 +2377,7 @@ static void rna_def_sound(BlenderRNA *brna)
RNA_def_property_ui_text(prop, "Volume", "Playback volume of the sound");
RNA_def_property_translation_context(prop, BLT_I18NCONTEXT_ID_SOUND);
RNA_def_property_float_funcs(prop, NULL, "rna_Sequence_volume_set", NULL);
- RNA_def_property_update(prop, NC_SCENE | ND_SEQUENCER, "rna_Sequence_update");
+ RNA_def_property_update(prop, NC_SCENE | ND_SEQUENCER, NULL);
prop = RNA_def_property(srna, "pitch", PROP_FLOAT, PROP_NONE);
RNA_def_property_float_sdna(prop, NULL, "pitch");
@@ -2345,14 +2385,14 @@ static void rna_def_sound(BlenderRNA *brna)
RNA_def_property_ui_text(prop, "Pitch", "Playback pitch of the sound");
RNA_def_property_translation_context(prop, BLT_I18NCONTEXT_ID_SOUND);
RNA_def_property_float_funcs(prop, NULL, "rna_Sequence_pitch_set", NULL);
- RNA_def_property_update(prop, NC_SCENE | ND_SEQUENCER, "rna_Sequence_update");
+ RNA_def_property_update(prop, NC_SCENE | ND_SEQUENCER, NULL);
prop = RNA_def_property(srna, "pan", PROP_FLOAT, PROP_NONE);
RNA_def_property_float_sdna(prop, NULL, "pan");
RNA_def_property_range(prop, -2.0f, 2.0f);
RNA_def_property_ui_text(prop, "Pan", "Playback panning of the sound (only for Mono sources)");
RNA_def_property_float_funcs(prop, NULL, "rna_Sequence_pan_set", NULL);
- RNA_def_property_update(prop, NC_SCENE | ND_SEQUENCER, "rna_Sequence_update");
+ RNA_def_property_update(prop, NC_SCENE | ND_SEQUENCER, NULL);
prop = RNA_def_property(srna, "show_waveform", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "flag", SEQ_AUDIO_DRAW_WAVEFORM);
@@ -2385,7 +2425,7 @@ static void rna_def_multicam(StructRNA *srna)
RNA_def_property_int_sdna(prop, NULL, "multicam_source");
RNA_def_property_range(prop, 0, MAXSEQ - 1);
RNA_def_property_ui_text(prop, "Multicam Source Channel", "");
- RNA_def_property_update(prop, NC_SCENE | ND_SEQUENCER, "rna_Sequence_update");
+ RNA_def_property_update(prop, NC_SCENE | ND_SEQUENCER, "rna_Sequence_invalidate_raw_update");
rna_def_input(srna);
}
@@ -2417,25 +2457,29 @@ static void rna_def_wipe(StructRNA *srna)
RNA_def_property_range(prop, 0.0f, 1.0f);
RNA_def_property_ui_text(
prop, "Blur Width", "Width of the blur edge, in percentage relative to the image size");
- RNA_def_property_update(prop, NC_SCENE | ND_SEQUENCER, "rna_Sequence_update");
+ RNA_def_property_update(
+ prop, NC_SCENE | ND_SEQUENCER, "rna_Sequence_invalidate_preprocessed_update");
prop = RNA_def_property(srna, "angle", PROP_FLOAT, PROP_ANGLE);
RNA_def_property_range(prop, DEG2RADF(-90.0f), DEG2RADF(90.0f));
RNA_def_property_ui_text(prop, "Angle", "Edge angle");
- RNA_def_property_update(prop, NC_SCENE | ND_SEQUENCER, "rna_Sequence_update");
+ RNA_def_property_update(
+ prop, NC_SCENE | ND_SEQUENCER, "rna_Sequence_invalidate_preprocessed_update");
prop = RNA_def_property(srna, "direction", PROP_ENUM, PROP_NONE);
RNA_def_property_enum_sdna(prop, NULL, "forward");
RNA_def_property_enum_items(prop, wipe_direction_items);
RNA_def_property_ui_text(prop, "Direction", "Wipe direction");
- RNA_def_property_update(prop, NC_SCENE | ND_SEQUENCER, "rna_Sequence_update");
+ RNA_def_property_update(
+ prop, NC_SCENE | ND_SEQUENCER, "rna_Sequence_invalidate_preprocessed_update");
prop = RNA_def_property(srna, "transition_type", PROP_ENUM, PROP_NONE);
RNA_def_property_enum_sdna(prop, NULL, "wipetype");
RNA_def_property_enum_items(prop, wipe_type_items);
RNA_def_property_translation_context(prop, BLT_I18NCONTEXT_ID_SEQUENCE);
RNA_def_property_ui_text(prop, "Transition Type", "");
- RNA_def_property_update(prop, NC_SCENE | ND_SEQUENCER, "rna_Sequence_update");
+ RNA_def_property_update(
+ prop, NC_SCENE | ND_SEQUENCER, "rna_Sequence_invalidate_preprocessed_update");
}
static void rna_def_glow(StructRNA *srna)
@@ -2448,36 +2492,42 @@ static void rna_def_glow(StructRNA *srna)
RNA_def_property_float_sdna(prop, NULL, "fMini");
RNA_def_property_range(prop, 0.0f, 1.0f);
RNA_def_property_ui_text(prop, "Threshold", "Minimum intensity to trigger a glow");
- RNA_def_property_update(prop, NC_SCENE | ND_SEQUENCER, "rna_Sequence_update");
+ RNA_def_property_update(
+ prop, NC_SCENE | ND_SEQUENCER, "rna_Sequence_invalidate_preprocessed_update");
prop = RNA_def_property(srna, "clamp", PROP_FLOAT, PROP_FACTOR);
RNA_def_property_float_sdna(prop, NULL, "fClamp");
RNA_def_property_range(prop, 0.0f, 1.0f);
RNA_def_property_ui_text(prop, "Clamp", "Brightness limit of intensity");
- RNA_def_property_update(prop, NC_SCENE | ND_SEQUENCER, "rna_Sequence_update");
+ RNA_def_property_update(
+ prop, NC_SCENE | ND_SEQUENCER, "rna_Sequence_invalidate_preprocessed_update");
prop = RNA_def_property(srna, "boost_factor", PROP_FLOAT, PROP_NONE);
RNA_def_property_float_sdna(prop, NULL, "fBoost");
RNA_def_property_range(prop, 0.0f, 10.0f);
RNA_def_property_ui_text(prop, "Boost Factor", "Brightness multiplier");
- RNA_def_property_update(prop, NC_SCENE | ND_SEQUENCER, "rna_Sequence_update");
+ RNA_def_property_update(
+ prop, NC_SCENE | ND_SEQUENCER, "rna_Sequence_invalidate_preprocessed_update");
prop = RNA_def_property(srna, "blur_radius", PROP_FLOAT, PROP_NONE);
RNA_def_property_float_sdna(prop, NULL, "dDist");
RNA_def_property_range(prop, 0.5f, 20.0f);
RNA_def_property_ui_text(prop, "Blur Distance", "Radius of glow effect");
- RNA_def_property_update(prop, NC_SCENE | ND_SEQUENCER, "rna_Sequence_update");
+ RNA_def_property_update(
+ prop, NC_SCENE | ND_SEQUENCER, "rna_Sequence_invalidate_preprocessed_update");
prop = RNA_def_property(srna, "quality", PROP_INT, PROP_NONE);
RNA_def_property_int_sdna(prop, NULL, "dQuality");
RNA_def_property_range(prop, 1, 5);
RNA_def_property_ui_text(prop, "Quality", "Accuracy of the blur effect");
- RNA_def_property_update(prop, NC_SCENE | ND_SEQUENCER, "rna_Sequence_update");
+ RNA_def_property_update(
+ prop, NC_SCENE | ND_SEQUENCER, "rna_Sequence_invalidate_preprocessed_update");
prop = RNA_def_property(srna, "use_only_boost", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "bNoComp", 0);
RNA_def_property_ui_text(prop, "Only Boost", "Show the glow buffer only");
- RNA_def_property_update(prop, NC_SCENE | ND_SEQUENCER, "rna_Sequence_update");
+ RNA_def_property_update(
+ prop, NC_SCENE | ND_SEQUENCER, "rna_Sequence_invalidate_preprocessed_update");
}
static void rna_def_transform(StructRNA *srna)
@@ -2503,49 +2553,57 @@ static void rna_def_transform(StructRNA *srna)
RNA_def_property_float_sdna(prop, NULL, "ScalexIni");
RNA_def_property_ui_text(prop, "Scale X", "Amount to scale the input in the X axis");
RNA_def_property_ui_range(prop, 0, 10, 3, 6);
- RNA_def_property_update(prop, NC_SCENE | ND_SEQUENCER, "rna_Sequence_update");
+ RNA_def_property_update(
+ prop, NC_SCENE | ND_SEQUENCER, "rna_Sequence_invalidate_preprocessed_update");
prop = RNA_def_property(srna, "scale_start_y", PROP_FLOAT, PROP_UNSIGNED);
RNA_def_property_float_sdna(prop, NULL, "ScaleyIni");
RNA_def_property_ui_text(prop, "Scale Y", "Amount to scale the input in the Y axis");
RNA_def_property_ui_range(prop, 0, 10, 3, 6);
- RNA_def_property_update(prop, NC_SCENE | ND_SEQUENCER, "rna_Sequence_update");
+ RNA_def_property_update(
+ prop, NC_SCENE | ND_SEQUENCER, "rna_Sequence_invalidate_preprocessed_update");
prop = RNA_def_property(srna, "use_uniform_scale", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "uniform_scale", 0);
RNA_def_property_ui_text(prop, "Uniform Scale", "Scale uniformly, preserving aspect ratio");
- RNA_def_property_update(prop, NC_SCENE | ND_SEQUENCER, "rna_Sequence_update");
+ RNA_def_property_update(
+ prop, NC_SCENE | ND_SEQUENCER, "rna_Sequence_invalidate_preprocessed_update");
prop = RNA_def_property(srna, "translate_start_x", PROP_FLOAT, PROP_NONE);
RNA_def_property_float_sdna(prop, NULL, "xIni");
RNA_def_property_ui_text(prop, "Translate X", "Amount to move the input on the X axis");
RNA_def_property_ui_range(prop, -4000.0f, 4000.0f, 3, 6);
- RNA_def_property_update(prop, NC_SCENE | ND_SEQUENCER, "rna_Sequence_update");
+ RNA_def_property_update(
+ prop, NC_SCENE | ND_SEQUENCER, "rna_Sequence_invalidate_preprocessed_update");
prop = RNA_def_property(srna, "translate_start_y", PROP_FLOAT, PROP_NONE);
RNA_def_property_float_sdna(prop, NULL, "yIni");
RNA_def_property_ui_text(prop, "Translate Y", "Amount to move the input on the Y axis");
RNA_def_property_ui_range(prop, -4000.0f, 4000.0f, 3, 6);
- RNA_def_property_update(prop, NC_SCENE | ND_SEQUENCER, "rna_Sequence_update");
+ RNA_def_property_update(
+ prop, NC_SCENE | ND_SEQUENCER, "rna_Sequence_invalidate_preprocessed_update");
prop = RNA_def_property(srna, "rotation_start", PROP_FLOAT, PROP_NONE);
RNA_def_property_float_sdna(prop, NULL, "rotIni");
RNA_def_property_ui_text(prop, "Rotation", "Degrees to rotate the input");
- RNA_def_property_update(prop, NC_SCENE | ND_SEQUENCER, "rna_Sequence_update");
+ RNA_def_property_update(
+ prop, NC_SCENE | ND_SEQUENCER, "rna_Sequence_invalidate_preprocessed_update");
prop = RNA_def_property(srna, "translation_unit", PROP_ENUM, PROP_NONE);
RNA_def_property_enum_sdna(prop, NULL, "percent");
RNA_def_property_clear_flag(prop, PROP_ANIMATABLE); /* not meant to be animated */
RNA_def_property_enum_items(prop, translation_unit_items);
RNA_def_property_ui_text(prop, "Translation Unit", "Unit of measure to translate the input");
- RNA_def_property_update(prop, NC_SCENE | ND_SEQUENCER, "rna_Sequence_update");
+ RNA_def_property_update(
+ prop, NC_SCENE | ND_SEQUENCER, "rna_Sequence_invalidate_preprocessed_update");
prop = RNA_def_property(srna, "interpolation", PROP_ENUM, PROP_NONE);
RNA_def_property_enum_items(prop, interpolation_items);
RNA_def_property_clear_flag(prop, PROP_ANIMATABLE); /* not meant to be animated */
RNA_def_property_ui_text(
prop, "Interpolation", "Method to determine how missing pixels are created");
- RNA_def_property_update(prop, NC_SCENE | ND_SEQUENCER, "rna_Sequence_update");
+ RNA_def_property_update(
+ prop, NC_SCENE | ND_SEQUENCER, "rna_Sequence_invalidate_preprocessed_update");
}
static void rna_def_solid_color(StructRNA *srna)
@@ -2557,7 +2615,8 @@ static void rna_def_solid_color(StructRNA *srna)
prop = RNA_def_property(srna, "color", PROP_FLOAT, PROP_COLOR_GAMMA);
RNA_def_property_float_sdna(prop, NULL, "col");
RNA_def_property_ui_text(prop, "Color", "Effect Strip color");
- RNA_def_property_update(prop, NC_SCENE | ND_SEQUENCER, "rna_Sequence_update");
+ RNA_def_property_update(
+ prop, NC_SCENE | ND_SEQUENCER, "rna_Sequence_invalidate_preprocessed_update");
}
static void rna_def_speed_control(StructRNA *srna)
@@ -2572,19 +2631,22 @@ static void rna_def_speed_control(StructRNA *srna)
RNA_def_property_ui_text(
prop, "Multiply Speed", "Multiply the resulting speed after the speed factor");
RNA_def_property_ui_range(prop, 0.0f, 100.0f, 1, -1);
- RNA_def_property_update(prop, NC_SCENE | ND_SEQUENCER, "rna_Sequence_update");
+ RNA_def_property_update(
+ prop, NC_SCENE | ND_SEQUENCER, "rna_Sequence_invalidate_preprocessed_update");
prop = RNA_def_property(srna, "use_as_speed", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "flags", SEQ_SPEED_INTEGRATE);
RNA_def_property_ui_text(
prop, "Use as speed", "Interpret the value as speed instead of a frame number");
- RNA_def_property_update(prop, NC_SCENE | ND_SEQUENCER, "rna_Sequence_update");
+ RNA_def_property_update(
+ prop, NC_SCENE | ND_SEQUENCER, "rna_Sequence_invalidate_preprocessed_update");
prop = RNA_def_property(srna, "use_scale_to_length", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "flags", SEQ_SPEED_COMPRESS_IPO_Y);
RNA_def_property_ui_text(
prop, "Scale to length", "Scale values from 0.0 to 1.0 to target sequence length");
- RNA_def_property_update(prop, NC_SCENE | ND_SEQUENCER, "rna_Sequence_update");
+ RNA_def_property_update(
+ prop, NC_SCENE | ND_SEQUENCER, "rna_Sequence_invalidate_preprocessed_update");
}
static void rna_def_gaussian_blur(StructRNA *srna)
@@ -2595,12 +2657,14 @@ static void rna_def_gaussian_blur(StructRNA *srna)
prop = RNA_def_property(srna, "size_x", PROP_FLOAT, PROP_UNSIGNED);
RNA_def_property_ui_text(prop, "Size X", "Size of the blur along X axis");
RNA_def_property_ui_range(prop, 0.0f, FLT_MAX, 1, -1);
- RNA_def_property_update(prop, NC_SCENE | ND_SEQUENCER, "rna_Sequence_update");
+ RNA_def_property_update(
+ prop, NC_SCENE | ND_SEQUENCER, "rna_Sequence_invalidate_preprocessed_update");
prop = RNA_def_property(srna, "size_y", PROP_FLOAT, PROP_UNSIGNED);
RNA_def_property_ui_text(prop, "Size Y", "Size of the blur along Y axis");
RNA_def_property_ui_range(prop, 0.0f, FLT_MAX, 1, -1);
- RNA_def_property_update(prop, NC_SCENE | ND_SEQUENCER, "rna_Sequence_update");
+ RNA_def_property_update(
+ prop, NC_SCENE | ND_SEQUENCER, "rna_Sequence_invalidate_preprocessed_update");
}
static void rna_def_text(StructRNA *srna)
@@ -2628,59 +2692,69 @@ static void rna_def_text(StructRNA *srna)
RNA_def_property_ui_text(prop, "Font", "Font of the text. Falls back to the UI font by default");
RNA_def_property_flag(prop, PROP_EDITABLE);
RNA_def_property_pointer_funcs(prop, NULL, "rna_Sequence_text_font_set", NULL, NULL);
- RNA_def_property_update(prop, NC_SCENE | ND_SEQUENCER, "rna_Sequence_update");
+ RNA_def_property_update(
+ prop, NC_SCENE | ND_SEQUENCER, "rna_Sequence_invalidate_preprocessed_update");
prop = RNA_def_property(srna, "font_size", PROP_INT, PROP_UNSIGNED);
RNA_def_property_int_sdna(prop, NULL, "text_size");
RNA_def_property_ui_text(prop, "Size", "Size of the text");
RNA_def_property_range(prop, 0.0, 2000);
RNA_def_property_ui_range(prop, 0.0f, 1000, 1, -1);
- RNA_def_property_update(prop, NC_SCENE | ND_SEQUENCER, "rna_Sequence_update");
+ RNA_def_property_update(
+ prop, NC_SCENE | ND_SEQUENCER, "rna_Sequence_invalidate_preprocessed_update");
prop = RNA_def_property(srna, "color", PROP_FLOAT, PROP_COLOR_GAMMA);
RNA_def_property_float_sdna(prop, NULL, "color");
RNA_def_property_ui_text(prop, "Color", "Text color");
- RNA_def_property_update(prop, NC_SCENE | ND_SEQUENCER, "rna_Sequence_update");
+ RNA_def_property_update(
+ prop, NC_SCENE | ND_SEQUENCER, "rna_Sequence_invalidate_preprocessed_update");
prop = RNA_def_property(srna, "shadow_color", PROP_FLOAT, PROP_COLOR_GAMMA);
RNA_def_property_float_sdna(prop, NULL, "shadow_color");
RNA_def_property_ui_text(prop, "Shadow Color", "");
- RNA_def_property_update(prop, NC_SCENE | ND_SEQUENCER, "rna_Sequence_update");
+ RNA_def_property_update(
+ prop, NC_SCENE | ND_SEQUENCER, "rna_Sequence_invalidate_preprocessed_update");
prop = RNA_def_property(srna, "location", PROP_FLOAT, PROP_XYZ);
RNA_def_property_float_sdna(prop, NULL, "loc");
RNA_def_property_ui_text(prop, "Location", "Location of the text");
RNA_def_property_range(prop, -FLT_MAX, FLT_MAX);
RNA_def_property_ui_range(prop, 0.0, 1.0, 1, -1);
- RNA_def_property_update(prop, NC_SCENE | ND_SEQUENCER, "rna_Sequence_update");
+ RNA_def_property_update(
+ prop, NC_SCENE | ND_SEQUENCER, "rna_Sequence_invalidate_preprocessed_update");
prop = RNA_def_property(srna, "wrap_width", PROP_FLOAT, PROP_NONE);
RNA_def_property_float_sdna(prop, NULL, "wrap_width");
RNA_def_property_ui_text(prop, "Wrap Width", "Word wrap width as factor, zero disables");
RNA_def_property_range(prop, 0, FLT_MAX);
RNA_def_property_ui_range(prop, 0.0, 1.0, 1, -1);
- RNA_def_property_update(prop, NC_SCENE | ND_SEQUENCER, "rna_Sequence_update");
+ RNA_def_property_update(
+ prop, NC_SCENE | ND_SEQUENCER, "rna_Sequence_invalidate_preprocessed_update");
prop = RNA_def_property(srna, "align_x", PROP_ENUM, PROP_NONE);
RNA_def_property_enum_sdna(prop, NULL, "align");
RNA_def_property_enum_items(prop, text_align_x_items);
RNA_def_property_ui_text(prop, "Align X", "Align the text along the X axis");
- RNA_def_property_update(prop, NC_SCENE | ND_SEQUENCER, "rna_Sequence_update");
+ RNA_def_property_update(
+ prop, NC_SCENE | ND_SEQUENCER, "rna_Sequence_invalidate_preprocessed_update");
prop = RNA_def_property(srna, "align_y", PROP_ENUM, PROP_NONE);
RNA_def_property_enum_sdna(prop, NULL, "align_y");
RNA_def_property_enum_items(prop, text_align_y_items);
RNA_def_property_ui_text(prop, "Align Y", "Align the image along the Y axis");
- RNA_def_property_update(prop, NC_SCENE | ND_SEQUENCER, "rna_Sequence_update");
+ RNA_def_property_update(
+ prop, NC_SCENE | ND_SEQUENCER, "rna_Sequence_invalidate_preprocessed_update");
prop = RNA_def_property(srna, "text", PROP_STRING, PROP_NONE);
RNA_def_property_ui_text(prop, "Text", "Text that will be displayed");
- RNA_def_property_update(prop, NC_SCENE | ND_SEQUENCER, "rna_Sequence_update");
+ RNA_def_property_update(
+ prop, NC_SCENE | ND_SEQUENCER, "rna_Sequence_invalidate_preprocessed_update");
prop = RNA_def_property(srna, "use_shadow", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "flag", SEQ_TEXT_SHADOW);
RNA_def_property_ui_text(prop, "Shadow", "Draw text with shadow");
- RNA_def_property_update(prop, NC_SCENE | ND_SEQUENCER, "rna_Sequence_update");
+ RNA_def_property_update(
+ prop, NC_SCENE | ND_SEQUENCER, "rna_Sequence_invalidate_preprocessed_update");
}
static void rna_def_color_mix(StructRNA *srna)
@@ -2719,13 +2793,15 @@ static void rna_def_color_mix(StructRNA *srna)
RNA_def_property_enum_items(prop, blend_color_items);
RNA_def_property_ui_text(
prop, "Blend Effect", "Method for controlling how the strip combines with other strips");
- RNA_def_property_update(prop, NC_SCENE | ND_SEQUENCER, "rna_Sequence_update");
+ RNA_def_property_update(
+ prop, NC_SCENE | ND_SEQUENCER, "rna_Sequence_invalidate_preprocessed_update");
prop = RNA_def_property(srna, "factor", PROP_FLOAT, PROP_FACTOR);
RNA_def_property_range(prop, 0.0f, 1.0f);
RNA_def_property_ui_text(
prop, "Blend Factor", "Percentage of how much the strip's colors affect other strips");
- RNA_def_property_update(prop, NC_SCENE | ND_SEQUENCER, "rna_Sequence_update");
+ RNA_def_property_update(
+ prop, NC_SCENE | ND_SEQUENCER, "rna_Sequence_invalidate_preprocessed_update");
}
static EffectInfo def_effects[] = {
diff --git a/source/blender/makesrna/intern/rna_shader_fx.c b/source/blender/makesrna/intern/rna_shader_fx.c
index 8696023fbe6..4aa87055e1b 100644
--- a/source/blender/makesrna/intern/rna_shader_fx.c
+++ b/source/blender/makesrna/intern/rna_shader_fx.c
@@ -186,7 +186,7 @@ static void shaderfx_object_set(Object *self, Object **ob_p, int type, PointerRN
# define RNA_FX_OBJECT_SET(_type, _prop, _obtype) \
static void rna_##_type##ShaderFx_##_prop##_set( \
- struct ReportList *UNUSED(reports), PointerRNA *ptr, PointerRNA value) \
+ PointerRNA *ptr, PointerRNA value, struct ReportList *UNUSED(reports)) \
{ \
_type##ShaderFxData *tmd = (_type##ShaderFxData *)ptr->data; \
shaderfx_object_set(ptr->id.data, &tmd->_prop, _obtype, value); \
diff --git a/source/blender/makesrna/intern/rna_space.c b/source/blender/makesrna/intern/rna_space.c
index dd1735027d9..8063b947a9c 100644
--- a/source/blender/makesrna/intern/rna_space.c
+++ b/source/blender/makesrna/intern/rna_space.c
@@ -346,15 +346,15 @@ const EnumPropertyItem rna_enum_shading_type_items[] = {
};
static const EnumPropertyItem rna_enum_viewport_lighting_items[] = {
- {V3D_LIGHTING_FLAT, "FLAT", 0, "Flat", "Display using flat lighting"},
{V3D_LIGHTING_STUDIO, "STUDIO", 0, "Studio", "Display using studio lighting"},
{V3D_LIGHTING_MATCAP, "MATCAP", 0, "MatCap", "Display using matcap material and lighting"},
+ {V3D_LIGHTING_FLAT, "FLAT", 0, "Flat", "Display using flat lighting"},
{0, NULL, 0, NULL, NULL},
};
static const EnumPropertyItem rna_enum_shading_color_type_items[] = {
- {V3D_SHADING_SINGLE_COLOR, "SINGLE", 0, "Single", "Show scene in a single color"},
{V3D_SHADING_MATERIAL_COLOR, "MATERIAL", 0, "Material", "Show material color"},
+ {V3D_SHADING_SINGLE_COLOR, "SINGLE", 0, "Single", "Show scene in a single color"},
{V3D_SHADING_OBJECT_COLOR, "OBJECT", 0, "Object", "Show object color"},
{V3D_SHADING_RANDOM_COLOR, "RANDOM", 0, "Random", "Show random object color"},
{V3D_SHADING_VERTEX_COLOR, "VERTEX", 0, "Vertex", "Show active vertex color"},
@@ -1083,10 +1083,10 @@ static const EnumPropertyItem *rna_View3DShading_color_type_itemf(bContext *UNUS
if (shading->type == OB_SOLID) {
RNA_enum_items_add_value(
- &item, &totitem, rna_enum_shading_color_type_items, V3D_SHADING_SINGLE_COLOR);
- RNA_enum_items_add_value(
&item, &totitem, rna_enum_shading_color_type_items, V3D_SHADING_MATERIAL_COLOR);
RNA_enum_items_add_value(
+ &item, &totitem, rna_enum_shading_color_type_items, V3D_SHADING_SINGLE_COLOR);
+ RNA_enum_items_add_value(
&item, &totitem, rna_enum_shading_color_type_items, V3D_SHADING_OBJECT_COLOR);
RNA_enum_items_add_value(
&item, &totitem, rna_enum_shading_color_type_items, V3D_SHADING_RANDOM_COLOR);
@@ -1329,9 +1329,9 @@ static bool rna_SpaceImageEditor_show_maskedit_get(PointerRNA *ptr)
return ED_space_image_check_show_maskedit(sima, view_layer);
}
-static void rna_SpaceImageEditor_image_set(struct ReportList *UNUSED(reports),
- PointerRNA *ptr,
- PointerRNA value)
+static void rna_SpaceImageEditor_image_set(PointerRNA *ptr,
+ PointerRNA value,
+ struct ReportList *UNUSED(reports))
{
SpaceImage *sima = (SpaceImage *)(ptr->data);
bScreen *sc = (bScreen *)ptr->id.data;
@@ -1343,9 +1343,9 @@ static void rna_SpaceImageEditor_image_set(struct ReportList *UNUSED(reports),
ED_space_image_set(G_MAIN, sima, obedit, (Image *)value.data, false);
}
-static void rna_SpaceImageEditor_mask_set(struct ReportList *UNUSED(reports),
- PointerRNA *ptr,
- PointerRNA value)
+static void rna_SpaceImageEditor_mask_set(PointerRNA *ptr,
+ PointerRNA value,
+ struct ReportList *UNUSED(reports))
{
SpaceImage *sima = (SpaceImage *)(ptr->data);
@@ -1511,9 +1511,9 @@ static void rna_SpaceTextEditor_word_wrap_set(PointerRNA *ptr, bool value)
st->left = 0;
}
-static void rna_SpaceTextEditor_text_set(struct ReportList *UNUSED(reports),
- PointerRNA *ptr,
- PointerRNA value)
+static void rna_SpaceTextEditor_text_set(PointerRNA *ptr,
+ PointerRNA value,
+ struct ReportList *UNUSED(reports))
{
SpaceText *st = (SpaceText *)(ptr->data);
@@ -1535,9 +1535,9 @@ static void rna_SpaceTextEditor_updateEdited(Main *UNUSED(bmain),
/* Space Properties */
/* note: this function exists only to avoid id refcounting */
-static void rna_SpaceProperties_pin_id_set(struct ReportList *UNUSED(reports),
- PointerRNA *ptr,
- PointerRNA value)
+static void rna_SpaceProperties_pin_id_set(PointerRNA *ptr,
+ PointerRNA value,
+ struct ReportList *UNUSED(reports))
{
SpaceProperties *sbuts = (SpaceProperties *)(ptr->data);
sbuts->pinid = value.data;
@@ -1739,9 +1739,9 @@ static void rna_ConsoleLine_cursor_index_range(
/* Space Dopesheet */
-static void rna_SpaceDopeSheetEditor_action_set(struct ReportList *UNUSED(reports),
- PointerRNA *ptr,
- PointerRNA value)
+static void rna_SpaceDopeSheetEditor_action_set(PointerRNA *ptr,
+ PointerRNA value,
+ struct ReportList *UNUSED(reports))
{
SpaceAction *saction = (SpaceAction *)(ptr->data);
bAction *act = (bAction *)value.data;
@@ -1963,9 +1963,9 @@ static void rna_Sequencer_view_type_update(Main *UNUSED(bmain),
/* Space Node Editor */
-static void rna_SpaceNodeEditor_node_tree_set(struct ReportList *UNUSED(reports),
- PointerRNA *ptr,
- const PointerRNA value)
+static void rna_SpaceNodeEditor_node_tree_set(PointerRNA *ptr,
+ const PointerRNA value,
+ struct ReportList *UNUSED(reports))
{
SpaceNode *snode = (SpaceNode *)ptr->data;
ED_node_tree_start(snode, (bNodeTree *)value.data, NULL, NULL);
@@ -2076,9 +2076,9 @@ static void rna_SpaceNodeEditor_cursor_location_from_region(SpaceNode *snode,
snode->cursor[1] /= UI_DPI_FAC;
}
-static void rna_SpaceClipEditor_clip_set(struct ReportList *UNUSED(reports),
- PointerRNA *ptr,
- PointerRNA value)
+static void rna_SpaceClipEditor_clip_set(PointerRNA *ptr,
+ PointerRNA value,
+ struct ReportList *UNUSED(reports))
{
SpaceClip *sc = (SpaceClip *)(ptr->data);
bScreen *screen = (bScreen *)ptr->id.data;
@@ -2086,9 +2086,9 @@ static void rna_SpaceClipEditor_clip_set(struct ReportList *UNUSED(reports),
ED_space_clip_set_clip(NULL, screen, sc, (MovieClip *)value.data);
}
-static void rna_SpaceClipEditor_mask_set(struct ReportList *UNUSED(reports),
- PointerRNA *ptr,
- PointerRNA value)
+static void rna_SpaceClipEditor_mask_set(PointerRNA *ptr,
+ PointerRNA value,
+ struct ReportList *UNUSED(reports))
{
SpaceClip *sc = (SpaceClip *)(ptr->data);
@@ -2484,7 +2484,7 @@ static void rna_def_space_generic_show_region_toggles(StructRNA *srna, int regio
if (region_type_mask & (1 << RGN_TYPE_TOOL_HEADER)) {
region_type_mask &= ~(1 << RGN_TYPE_TOOL_HEADER);
- DEF_SHOW_REGION_PROPERTY(show_region_tool_header, "Tool Header", "");
+ DEF_SHOW_REGION_PROPERTY(show_region_tool_header, "Tool Settings", "");
}
if (region_type_mask & (1 << RGN_TYPE_HEADER)) {
region_type_mask &= ~(1 << RGN_TYPE_HEADER);
@@ -3403,14 +3403,12 @@ static void rna_def_space_view3d_overlay(BlenderRNA *brna)
prop = RNA_def_property(srna, "show_edges", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "overlay.edit_flag", V3D_OVERLAY_EDIT_EDGES);
- RNA_def_property_ui_text(
- prop, "Draw Edges", "Display selected edges using highlights in the 3D view and UV editor");
+ RNA_def_property_ui_text(prop, "Draw Edges", "Display selected edges using highlights");
RNA_def_property_update(prop, NC_SPACE | ND_SPACE_VIEW3D, NULL);
prop = RNA_def_property(srna, "show_faces", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "overlay.edit_flag", V3D_OVERLAY_EDIT_FACES);
- RNA_def_property_ui_text(
- prop, "Draw Faces", "Display all faces as shades in the 3D view and UV editor");
+ RNA_def_property_ui_text(prop, "Draw Faces", "Display shading over all faces");
RNA_def_property_update(prop, NC_SPACE | ND_SPACE_VIEW3D, NULL);
prop = RNA_def_property(srna, "show_face_center", PROP_BOOLEAN, PROP_NONE);
diff --git a/source/blender/makesrna/intern/rna_space_api.c b/source/blender/makesrna/intern/rna_space_api.c
index 58a9429e528..52a197240da 100644
--- a/source/blender/makesrna/intern/rna_space_api.c
+++ b/source/blender/makesrna/intern/rna_space_api.c
@@ -50,7 +50,7 @@ static void rna_RegionView3D_update(ID *id, RegionView3D *rv3d, bContext *C)
ViewLayer *view_layer = WM_window_get_active_view_layer(win);
Depsgraph *depsgraph = BKE_scene_get_depsgraph(scene, view_layer, true);
- ED_view3d_update_viewmat(depsgraph, scene, v3d, ar, NULL, NULL, NULL);
+ ED_view3d_update_viewmat(depsgraph, scene, v3d, ar, NULL, NULL, NULL, false);
break;
}
}
diff --git a/source/blender/makesrna/intern/rna_tracking.c b/source/blender/makesrna/intern/rna_tracking.c
index 9be277aa15f..d08f7bc6035 100644
--- a/source/blender/makesrna/intern/rna_tracking.c
+++ b/source/blender/makesrna/intern/rna_tracking.c
@@ -144,9 +144,9 @@ static PointerRNA rna_tracking_active_track_get(PointerRNA *ptr)
return rna_pointer_inherit_refine(ptr, &RNA_MovieTrackingTrack, act_track);
}
-static void rna_tracking_active_track_set(struct ReportList *UNUSED(reports),
- PointerRNA *ptr,
- PointerRNA value)
+static void rna_tracking_active_track_set(PointerRNA *ptr,
+ PointerRNA value,
+ struct ReportList *UNUSED(reports))
{
MovieClip *clip = (MovieClip *)ptr->id.data;
MovieTrackingTrack *track = (MovieTrackingTrack *)value.data;
@@ -167,9 +167,9 @@ static PointerRNA rna_tracking_active_plane_track_get(PointerRNA *ptr)
return rna_pointer_inherit_refine(ptr, &RNA_MovieTrackingPlaneTrack, act_plane_track);
}
-static void rna_tracking_active_plane_track_set(struct ReportList *UNUSED(reports),
- PointerRNA *ptr,
- PointerRNA value)
+static void rna_tracking_active_plane_track_set(PointerRNA *ptr,
+ PointerRNA value,
+ struct ReportList *UNUSED(reports))
{
MovieClip *clip = (MovieClip *)ptr->id.data;
MovieTrackingPlaneTrack *plane_track = (MovieTrackingPlaneTrack *)value.data;
@@ -480,9 +480,9 @@ static PointerRNA rna_tracking_active_object_get(PointerRNA *ptr)
return rna_pointer_inherit_refine(ptr, &RNA_MovieTrackingObject, object);
}
-static void rna_tracking_active_object_set(struct ReportList *UNUSED(reports),
- PointerRNA *ptr,
- PointerRNA value)
+static void rna_tracking_active_object_set(PointerRNA *ptr,
+ PointerRNA value,
+ struct ReportList *UNUSED(reports))
{
MovieClip *clip = (MovieClip *)ptr->id.data;
MovieTrackingObject *object = (MovieTrackingObject *)value.data;
diff --git a/source/blender/makesrna/intern/rna_ui.c b/source/blender/makesrna/intern/rna_ui.c
index faa16f4f146..0dbafbde71c 100644
--- a/source/blender/makesrna/intern/rna_ui.c
+++ b/source/blender/makesrna/intern/rna_ui.c
@@ -317,19 +317,21 @@ static StructRNA *rna_Panel_register(Main *bmain,
pt->draw_header = (have_function[2]) ? panel_draw_header : NULL;
pt->draw_header_preset = (have_function[3]) ? panel_draw_header_preset : NULL;
- /* XXX use "no header" flag for some ordering of panels until we have real panel ordering */
- if (pt->flag & PNL_NO_HEADER) {
- PanelType *pth = art->paneltypes.first;
- while (pth && pth->flag & PNL_NO_HEADER)
- pth = pth->next;
-
- if (pth)
- BLI_insertlinkbefore(&art->paneltypes, pth, pt);
- else
- BLI_addtail(&art->paneltypes, pt);
+ /* Find position to insert panel based on order. */
+ PanelType *pt_iter = art->paneltypes.last;
+
+ for (; pt_iter; pt_iter = pt_iter->prev) {
+ /* No header has priority. */
+ if ((pt->flag & PNL_NO_HEADER) && !(pt_iter->flag & PNL_NO_HEADER)) {
+ continue;
+ }
+ if (pt_iter->order <= pt->order) {
+ break;
+ }
}
- else
- BLI_addtail(&art->paneltypes, pt);
+
+ /* Insert into list. */
+ BLI_insertlinkafter(&art->paneltypes, pt_iter, pt);
if (parent) {
pt->parent = parent;
@@ -1347,6 +1349,14 @@ static void rna_def_panel(BlenderRNA *brna)
RNA_def_property_flag(prop, PROP_REGISTER_OPTIONAL);
RNA_def_property_ui_text(prop, "Units X", "When set, defines popup panel width");
+ prop = RNA_def_property(srna, "bl_order", PROP_INT, PROP_UNSIGNED);
+ RNA_def_property_int_sdna(prop, NULL, "type->order");
+ RNA_def_property_flag(prop, PROP_REGISTER_OPTIONAL);
+ RNA_def_property_ui_text(
+ prop,
+ "Order",
+ "Panels with lower numbers are default ordered before panels with higher numbers");
+
prop = RNA_def_property(srna, "use_pin", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "flag", PNL_PIN);
RNA_def_property_ui_text(prop, "Pin", "");
diff --git a/source/blender/makesrna/intern/rna_ui_api.c b/source/blender/makesrna/intern/rna_ui_api.c
index 7ce9155e3d9..d50f97e88ca 100644
--- a/source/blender/makesrna/intern/rna_ui_api.c
+++ b/source/blender/makesrna/intern/rna_ui_api.c
@@ -95,13 +95,14 @@ static void rna_uiItemR(uiLayout *layout,
int icon,
bool expand,
bool slider,
- bool toggle,
+ int toggle,
bool icon_only,
bool event,
bool full_event,
bool emboss,
int index,
- int icon_value)
+ int icon_value,
+ bool invert_checkbox)
{
PropertyRNA *prop = RNA_struct_find_property(ptr, propname);
int flag = 0;
@@ -120,11 +121,17 @@ static void rna_uiItemR(uiLayout *layout,
flag |= (slider) ? UI_ITEM_R_SLIDER : 0;
flag |= (expand) ? UI_ITEM_R_EXPAND : 0;
- flag |= (toggle) ? UI_ITEM_R_TOGGLE : 0;
+ if (toggle == 1) {
+ flag |= UI_ITEM_R_TOGGLE;
+ }
+ else if (toggle == 0) {
+ flag |= UI_ITEM_R_ICON_NEVER;
+ }
flag |= (icon_only) ? UI_ITEM_R_ICON_ONLY : 0;
flag |= (event) ? UI_ITEM_R_EVENT : 0;
flag |= (full_event) ? UI_ITEM_R_FULL_EVENT : 0;
flag |= (emboss) ? 0 : UI_ITEM_R_NO_BG;
+ flag |= (invert_checkbox) ? UI_ITEM_R_CHECKBOX_INVERT : 0;
uiItemFullR(layout, ptr, prop, index, 0, flag, name, icon);
}
@@ -771,7 +778,17 @@ void RNA_api_ui_layout(StructRNA *srna)
api_ui_item_common(func);
RNA_def_boolean(func, "expand", false, "", "Expand button to show more detail");
RNA_def_boolean(func, "slider", false, "", "Use slider widget for numeric values");
- RNA_def_boolean(func, "toggle", false, "", "Use toggle widget for boolean values");
+ RNA_def_int(func,
+ "toggle",
+ -1,
+ -1,
+ 1,
+ "",
+ "Use toggle widget for boolean values, "
+ "or a checkbox when disabled "
+ "(the default is -1 which uses toggle only when an icon is displayed)",
+ -1,
+ 1);
RNA_def_boolean(func, "icon_only", false, "", "Draw only icons in buttons, no text");
RNA_def_boolean(func, "event", false, "", "Use button to input key events");
RNA_def_boolean(
@@ -789,6 +806,7 @@ void RNA_api_ui_layout(StructRNA *srna)
INT_MAX); /* RNA_NO_INDEX == -1 */
parm = RNA_def_property(func, "icon_value", PROP_INT, PROP_UNSIGNED);
RNA_def_property_ui_text(parm, "Icon Value", "Override automatic icon of the item");
+ RNA_def_boolean(func, "invert_checkbox", false, "", "Draw checkbox value inverted");
func = RNA_def_function(srna, "props_enum", "uiItemsEnumR");
api_ui_item_rna_common(func);
diff --git a/source/blender/makesrna/intern/rna_userdef.c b/source/blender/makesrna/intern/rna_userdef.c
index 217beea7dae..d06e938b262 100644
--- a/source/blender/makesrna/intern/rna_userdef.c
+++ b/source/blender/makesrna/intern/rna_userdef.c
@@ -184,6 +184,31 @@ static void rna_userdef_version_get(PointerRNA *ptr, int *value)
value[2] = userdef->subversionfile;
}
+# define USERDEF_TAG_DIRTY rna_userdef_is_dirty_update_impl()
+
+/* Use single function so we can more easily breakpoint it. */
+void rna_userdef_is_dirty_update_impl(void)
+{
+ /* We can't use 'ptr->data' because this update function
+ * is used for themes and other nested data. */
+ if (U.runtime.is_dirty == false) {
+ U.runtime.is_dirty = true;
+ WM_main_add_notifier(NC_WINDOW, NULL);
+ }
+}
+
+/**
+ * Use as a fallback update handler,
+ * never use 'ptr' unless it's type is checked.
+ */
+void rna_userdef_is_dirty_update(Main *UNUSED(bmain),
+ Scene *UNUSED(scene),
+ PointerRNA *UNUSED(ptr))
+{
+ rna_userdef_is_dirty_update_impl();
+}
+
+/** Take care not to use this if we expet 'is_dirty' to be tagged. */
static void rna_userdef_ui_update(Main *UNUSED(bmain),
Scene *UNUSED(scene),
PointerRNA *UNUSED(ptr))
@@ -193,11 +218,8 @@ static void rna_userdef_ui_update(Main *UNUSED(bmain),
static void rna_userdef_update(Main *UNUSED(bmain), Scene *UNUSED(scene), PointerRNA *UNUSED(ptr))
{
- /* We can't use 'ptr->data' because this update function
- * is used for themes and other nested data. */
- U.runtime.is_dirty = true;
-
WM_main_add_notifier(NC_WINDOW, NULL);
+ USERDEF_TAG_DIRTY;
}
static void rna_userdef_theme_update(Main *bmain, Scene *scene, PointerRNA *ptr)
@@ -224,24 +246,27 @@ static void rna_userdef_dpi_update(Main *UNUSED(bmain),
WM_main_add_notifier(NC_WINDOW, NULL); /* full redraw */
WM_main_add_notifier(NC_SCREEN | NA_EDITED, NULL); /* refresh region sizes */
+ USERDEF_TAG_DIRTY;
}
-static void rna_userdef_update_ui(Main *UNUSED(bmain),
- Scene *UNUSED(scene),
- PointerRNA *UNUSED(ptr))
+static void rna_userdef_screen_update(Main *UNUSED(bmain),
+ Scene *UNUSED(scene),
+ PointerRNA *UNUSED(ptr))
{
WM_main_add_notifier(NC_WINDOW, NULL);
WM_main_add_notifier(NC_SCREEN | NA_EDITED, NULL); /* refresh region sizes */
+ USERDEF_TAG_DIRTY;
}
-static void rna_userdef_update_ui_header_default(Main *bmain, Scene *scene, PointerRNA *ptr)
+static void rna_userdef_screen_update_header_default(Main *bmain, Scene *scene, PointerRNA *ptr)
{
if (U.uiflag & USER_HEADER_FROM_PREF) {
for (bScreen *screen = bmain->screens.first; screen; screen = screen->id.next) {
BKE_screen_header_alignment_reset(screen);
}
- rna_userdef_update_ui(bmain, scene, ptr);
+ rna_userdef_screen_update(bmain, scene, ptr);
}
+ USERDEF_TAG_DIRTY;
}
static void rna_userdef_language_update(Main *UNUSED(bmain),
@@ -251,6 +276,7 @@ static void rna_userdef_language_update(Main *UNUSED(bmain),
BLF_cache_clear();
BLT_lang_set(NULL);
UI_reinit_font();
+ USERDEF_TAG_DIRTY;
}
static void rna_userdef_script_autoexec_update(Main *UNUSED(bmain),
@@ -262,6 +288,8 @@ static void rna_userdef_script_autoexec_update(Main *UNUSED(bmain),
G.f &= ~G_FLAG_SCRIPT_AUTOEXEC;
else
G.f |= G_FLAG_SCRIPT_AUTOEXEC;
+
+ USERDEF_TAG_DIRTY;
}
static void rna_userdef_load_ui_update(Main *UNUSED(bmain), Scene *UNUSED(scene), PointerRNA *ptr)
@@ -271,6 +299,8 @@ static void rna_userdef_load_ui_update(Main *UNUSED(bmain), Scene *UNUSED(scene)
G.fileflags |= G_FILE_NO_UI;
else
G.fileflags &= ~G_FILE_NO_UI;
+
+ USERDEF_TAG_DIRTY;
}
static void rna_userdef_anisotropic_update(Main *bmain, Scene *scene, PointerRNA *ptr)
@@ -323,6 +353,7 @@ static void rna_userdef_tablet_api_update(Main *UNUSED(bmain),
PointerRNA *UNUSED(ptr))
{
WM_init_tablet_api();
+ USERDEF_TAG_DIRTY;
}
# ifdef WITH_INPUT_NDOF
@@ -332,6 +363,7 @@ static void rna_userdef_ndof_deadzone_update(Main *UNUSED(bmain),
{
UserDef *userdef = ptr->data;
WM_ndof_deadzone_set(userdef->ndof_deadzone);
+ USERDEF_TAG_DIRTY;
}
# endif
@@ -341,6 +373,7 @@ static void rna_userdef_keyconfig_reload_update(bContext *C,
PointerRNA *UNUSED(ptr))
{
WM_keyconfig_reload(C);
+ USERDEF_TAG_DIRTY;
}
static void rna_userdef_timecode_style_set(PointerRNA *ptr, int value)
@@ -410,6 +443,7 @@ static PointerRNA rna_UserDef_system_get(PointerRNA *ptr)
static void rna_UserDef_audio_update(Main *bmain, Scene *UNUSED(scene), PointerRNA *UNUSED(ptr))
{
BKE_sound_init(bmain);
+ USERDEF_TAG_DIRTY;
}
static void rna_Userdef_memcache_update(Main *UNUSED(bmain),
@@ -417,6 +451,7 @@ static void rna_Userdef_memcache_update(Main *UNUSED(bmain),
PointerRNA *UNUSED(ptr))
{
MEM_CacheLimiter_set_maximum(((size_t)U.memcachelimit) * 1024 * 1024);
+ USERDEF_TAG_DIRTY;
}
static void rna_UserDef_weight_color_update(Main *bmain, Scene *scene, PointerRNA *ptr)
@@ -459,7 +494,7 @@ static bAddon *rna_userdef_addon_new(void)
ListBase *addons_list = &U.addons;
bAddon *addon = BKE_addon_new();
BLI_addtail(addons_list, addon);
- U.runtime.is_dirty = true;
+ USERDEF_TAG_DIRTY;
return addon;
}
@@ -474,14 +509,14 @@ static void rna_userdef_addon_remove(ReportList *reports, PointerRNA *addon_ptr)
BLI_remlink(addons_list, addon);
BKE_addon_free(addon);
RNA_POINTER_INVALIDATE(addon_ptr);
- U.runtime.is_dirty = true;
+ USERDEF_TAG_DIRTY;
}
static bPathCompare *rna_userdef_pathcompare_new(void)
{
bPathCompare *path_cmp = MEM_callocN(sizeof(bPathCompare), "bPathCompare");
BLI_addtail(&U.autoexec_paths, path_cmp);
- U.runtime.is_dirty = true;
+ USERDEF_TAG_DIRTY;
return path_cmp;
}
@@ -495,7 +530,7 @@ static void rna_userdef_pathcompare_remove(ReportList *reports, PointerRNA *path
BLI_freelinkN(&U.autoexec_paths, path_cmp);
RNA_POINTER_INVALIDATE(path_cmp_ptr);
- U.runtime.is_dirty = true;
+ USERDEF_TAG_DIRTY;
}
static void rna_userdef_temp_update(Main *UNUSED(bmain),
@@ -503,6 +538,7 @@ static void rna_userdef_temp_update(Main *UNUSED(bmain),
PointerRNA *UNUSED(ptr))
{
BKE_tempdir_init(U.tempdir);
+ USERDEF_TAG_DIRTY;
}
static void rna_userdef_text_update(Main *UNUSED(bmain),
@@ -512,6 +548,7 @@ static void rna_userdef_text_update(Main *UNUSED(bmain),
BLF_cache_clear();
UI_reinit_font();
WM_main_add_notifier(NC_WINDOW, NULL);
+ USERDEF_TAG_DIRTY;
}
static PointerRNA rna_Theme_space_generic_get(PointerRNA *ptr)
@@ -578,6 +615,7 @@ static void rna_userdef_opensubdiv_update(Main *bmain,
for (object = bmain->objects.first; object; object = object->id.next) {
DEG_id_tag_update(&object->id, ID_RECALC_TRANSFORM);
}
+ USERDEF_TAG_DIRTY;
}
# endif
@@ -900,6 +938,11 @@ static void rna_UserDef_studiolight_light_ambient_get(PointerRNA *ptr, float *va
#else
+# define USERDEF_TAG_DIRTY_PROPERTY_UPDATE_ENABLE \
+ RNA_define_fallback_property_update(0, "rna_userdef_is_dirty_update")
+
+# define USERDEF_TAG_DIRTY_PROPERTY_UPDATE_DISABLE RNA_define_fallback_property_update(0, NULL)
+
/* TODO(sergey): This technically belongs to blenlib, but we don't link
* makesrna against it.
*/
@@ -2140,7 +2183,7 @@ static void rna_def_userdef_theme_space_graph(BlenderRNA *brna)
RNA_def_property_ui_text(prop, "Current Frame", "");
RNA_def_property_update(prop, 0, "rna_userdef_theme_update");
- prop = RNA_def_property(srna, "scrubbing_background", PROP_FLOAT, PROP_COLOR_GAMMA);
+ prop = RNA_def_property(srna, "time_scrub_background", PROP_FLOAT, PROP_COLOR_GAMMA);
RNA_def_property_array(prop, 4);
RNA_def_property_ui_text(prop, "Scrubbing/Markers Region", "");
RNA_def_property_update(prop, 0, "rna_userdef_theme_update");
@@ -2502,8 +2545,6 @@ static void rna_def_userdef_theme_space_node(BlenderRNA *brna)
rna_def_userdef_theme_spaces_main(srna);
rna_def_userdef_theme_spaces_list_main(srna);
- rna_def_userdef_theme_spaces_gpencil(srna);
-
prop = RNA_def_property(srna, "node_selected", PROP_FLOAT, PROP_COLOR_GAMMA);
RNA_def_property_float_sdna(prop, NULL, "select");
RNA_def_property_array(prop, 3);
@@ -2678,7 +2719,6 @@ static void rna_def_userdef_theme_space_image(BlenderRNA *brna)
RNA_def_struct_ui_text(srna, "Theme Image Editor", "Theme settings for the Image Editor");
rna_def_userdef_theme_spaces_main(srna);
- rna_def_userdef_theme_spaces_gpencil(srna);
rna_def_userdef_theme_spaces_vertex(srna);
rna_def_userdef_theme_spaces_face(srna);
@@ -2787,7 +2827,6 @@ static void rna_def_userdef_theme_space_seq(BlenderRNA *brna)
RNA_def_struct_ui_text(srna, "Theme Sequence Editor", "Theme settings for the Sequence Editor");
rna_def_userdef_theme_spaces_main(srna);
- rna_def_userdef_theme_spaces_gpencil(srna);
prop = RNA_def_property(srna, "grid", PROP_FLOAT, PROP_COLOR_GAMMA);
RNA_def_property_array(prop, 3);
@@ -2859,7 +2898,7 @@ static void rna_def_userdef_theme_space_seq(BlenderRNA *brna)
RNA_def_property_ui_text(prop, "Current Frame", "");
RNA_def_property_update(prop, 0, "rna_userdef_theme_update");
- prop = RNA_def_property(srna, "scrubbing_background", PROP_FLOAT, PROP_COLOR_GAMMA);
+ prop = RNA_def_property(srna, "time_scrub_background", PROP_FLOAT, PROP_COLOR_GAMMA);
RNA_def_property_array(prop, 4);
RNA_def_property_ui_text(prop, "Scrubbing/Markers Region", "");
RNA_def_property_update(prop, 0, "rna_userdef_theme_update");
@@ -2921,7 +2960,7 @@ static void rna_def_userdef_theme_space_action(BlenderRNA *brna)
RNA_def_property_ui_text(prop, "Current Frame", "");
RNA_def_property_update(prop, 0, "rna_userdef_theme_update");
- prop = RNA_def_property(srna, "scrubbing_background", PROP_FLOAT, PROP_COLOR_GAMMA);
+ prop = RNA_def_property(srna, "time_scrub_background", PROP_FLOAT, PROP_COLOR_GAMMA);
RNA_def_property_array(prop, 4);
RNA_def_property_ui_text(prop, "Scrubbing/Markers Region", "");
RNA_def_property_update(prop, 0, "rna_userdef_theme_update");
@@ -3219,7 +3258,7 @@ static void rna_def_userdef_theme_space_nla(BlenderRNA *brna)
RNA_def_property_ui_text(prop, "Current Frame", "");
RNA_def_property_update(prop, 0, "rna_userdef_theme_update");
- prop = RNA_def_property(srna, "scrubbing_background", PROP_FLOAT, PROP_COLOR_GAMMA);
+ prop = RNA_def_property(srna, "time_scrub_background", PROP_FLOAT, PROP_COLOR_GAMMA);
RNA_def_property_array(prop, 4);
RNA_def_property_ui_text(prop, "Scrubbing/Markers Region", "");
RNA_def_property_update(prop, 0, "rna_userdef_theme_update");
@@ -3274,8 +3313,6 @@ static void rna_def_userdef_theme_space_clip(BlenderRNA *brna)
rna_def_userdef_theme_spaces_main(srna);
rna_def_userdef_theme_spaces_list_main(srna);
- rna_def_userdef_theme_spaces_gpencil(srna);
-
prop = RNA_def_property(srna, "marker_outline", PROP_FLOAT, PROP_COLOR_GAMMA);
RNA_def_property_float_sdna(prop, NULL, "marker_outline");
RNA_def_property_array(prop, 3);
@@ -3330,7 +3367,7 @@ static void rna_def_userdef_theme_space_clip(BlenderRNA *brna)
RNA_def_property_ui_text(prop, "Current Frame", "");
RNA_def_property_update(prop, 0, "rna_userdef_theme_update");
- prop = RNA_def_property(srna, "scrubbing_background", PROP_FLOAT, PROP_COLOR_GAMMA);
+ prop = RNA_def_property(srna, "time_scrub_background", PROP_FLOAT, PROP_COLOR_GAMMA);
RNA_def_property_array(prop, 4);
RNA_def_property_ui_text(prop, "Scrubbing/Markers Region", "");
RNA_def_property_update(prop, 0, "rna_userdef_theme_update");
@@ -3743,12 +3780,16 @@ static void rna_def_userdef_addon_pref(BlenderRNA *brna)
RNA_def_struct_idprops_func(srna, "rna_AddonPref_idprops");
RNA_def_struct_flag(srna, STRUCT_NO_DATABLOCK_IDPROPERTIES); /* Mandatory! */
+ USERDEF_TAG_DIRTY_PROPERTY_UPDATE_DISABLE;
+
/* registration */
RNA_define_verify_sdna(0);
prop = RNA_def_property(srna, "bl_idname", PROP_STRING, PROP_NONE);
RNA_def_property_string_sdna(prop, NULL, "module");
RNA_def_property_flag(prop, PROP_REGISTER);
RNA_define_verify_sdna(1);
+
+ USERDEF_TAG_DIRTY_PROPERTY_UPDATE_ENABLE;
}
static void rna_def_userdef_dothemes(BlenderRNA *brna)
@@ -4065,7 +4106,7 @@ static void rna_def_userdef_view(BlenderRNA *brna)
RNA_def_property_boolean_negative_sdna(prop, NULL, "app_flag", USER_APP_LOCK_UI_LAYOUT);
RNA_def_property_ui_text(
prop, "Editor Corner Splitting", "Split and join editors by dragging from corners");
- RNA_def_property_update(prop, 0, "rna_userdef_update_ui");
+ RNA_def_property_update(prop, 0, "rna_userdef_screen_update");
/* menus */
prop = RNA_def_property(srna, "use_mouse_over_open", PROP_BOOLEAN, PROP_NONE);
@@ -4166,7 +4207,7 @@ static void rna_def_userdef_view(BlenderRNA *brna)
RNA_def_property_enum_items(prop, header_align_items);
RNA_def_property_enum_bitflag_sdna(prop, NULL, "uiflag");
RNA_def_property_ui_text(prop, "Header Position", "Default header position for new space-types");
- RNA_def_property_update(prop, 0, "rna_userdef_update_ui_header_default");
+ RNA_def_property_update(prop, 0, "rna_userdef_screen_update_header_default");
static const EnumPropertyItem text_hinting_items[] = {
{0, "AUTO", 0, "Auto", ""},
@@ -5580,6 +5621,8 @@ static void rna_def_userdef_autoexec_path_collection(BlenderRNA *brna, PropertyR
void RNA_def_userdef(BlenderRNA *brna)
{
+ USERDEF_TAG_DIRTY_PROPERTY_UPDATE_ENABLE;
+
StructRNA *srna;
PropertyRNA *prop;
@@ -5740,6 +5783,8 @@ void RNA_def_userdef(BlenderRNA *brna)
rna_def_userdef_studiolights(brna);
rna_def_userdef_studiolight(brna);
rna_def_userdef_pathcompare(brna);
+
+ USERDEF_TAG_DIRTY_PROPERTY_UPDATE_DISABLE;
}
#endif
diff --git a/source/blender/makesrna/intern/rna_wm.c b/source/blender/makesrna/intern/rna_wm.c
index f3080d6f659..14994340ad3 100644
--- a/source/blender/makesrna/intern/rna_wm.c
+++ b/source/blender/makesrna/intern/rna_wm.c
@@ -49,6 +49,8 @@ static const EnumPropertyItem event_keymouse_value_items[] = {
{KM_CLICK, "CLICK", 0, "Click", ""},
{KM_DBL_CLICK, "DOUBLE_CLICK", 0, "Double Click", ""},
{KM_CLICK_DRAG, "CLICK_DRAG", 0, "Click Drag", ""},
+ /* Used for NDOF and trackpad events. */
+ {KM_NOTHING, "NOTHING", 0, "Nothing", ""},
{0, NULL, 0, NULL, NULL},
};
@@ -382,7 +384,6 @@ const EnumPropertyItem rna_enum_event_type_items[] = {
const EnumPropertyItem rna_enum_event_value_items[] = {
{KM_ANY, "ANY", 0, "Any", ""},
- {KM_NOTHING, "NOTHING", 0, "Nothing", ""},
{KM_PRESS, "PRESS", 0, "Press", ""},
{KM_RELEASE, "RELEASE", 0, "Release", ""},
{KM_CLICK, "CLICK", 0, "Click", ""},
@@ -396,6 +397,7 @@ const EnumPropertyItem rna_enum_event_value_items[] = {
{EVT_GESTURE_SW, "SOUTH_WEST", 0, "South-West", ""},
{EVT_GESTURE_W, "WEST", 0, "West", ""},
{EVT_GESTURE_NW, "NORTH_WEST", 0, "North-West", ""},
+ {KM_NOTHING, "NOTHING", 0, "Nothing", ""},
{0, NULL, 0, NULL, NULL},
};
@@ -451,11 +453,6 @@ static const EnumPropertyItem operator_flag_items[] = {
"is enabled"},
{OPTYPE_PRESET, "PRESET", 0, "Preset", "Display a preset button with the operators settings"},
{OPTYPE_INTERNAL, "INTERNAL", 0, "Internal", "Removes the operator from search results"},
- {OPTYPE_USE_EVAL_DATA,
- "USE_EVAL_DATA",
- 0,
- "Use Evaluated Data",
- "Uses evaluated data (i.e. needs a valid depsgraph for current context)"},
{0, NULL, 0, NULL, NULL},
};
#endif
@@ -694,9 +691,9 @@ static PointerRNA rna_PieMenu_layout_get(PointerRNA *ptr)
return rptr;
}
-static void rna_Window_scene_set(struct ReportList *UNUSED(reports),
- PointerRNA *ptr,
- PointerRNA value)
+static void rna_Window_scene_set(PointerRNA *ptr,
+ PointerRNA value,
+ struct ReportList *UNUSED(reports))
{
wmWindow *win = ptr->data;
@@ -740,9 +737,9 @@ static PointerRNA rna_Window_workspace_get(PointerRNA *ptr)
ptr, &RNA_WorkSpace, BKE_workspace_active_get(win->workspace_hook));
}
-static void rna_Window_workspace_set(struct ReportList *UNUSED(reports),
- PointerRNA *ptr,
- PointerRNA value)
+static void rna_Window_workspace_set(PointerRNA *ptr,
+ PointerRNA value,
+ struct ReportList *UNUSED(reports))
{
wmWindow *win = (wmWindow *)ptr->data;
@@ -778,9 +775,9 @@ PointerRNA rna_Window_screen_get(PointerRNA *ptr)
ptr, &RNA_Screen, BKE_workspace_active_screen_get(win->workspace_hook));
}
-static void rna_Window_screen_set(struct ReportList *UNUSED(reports),
- PointerRNA *ptr,
- PointerRNA value)
+static void rna_Window_screen_set(PointerRNA *ptr,
+ PointerRNA value,
+ struct ReportList *UNUSED(reports))
{
wmWindow *win = ptr->data;
WorkSpace *workspace = BKE_workspace_active_get(win->workspace_hook);
@@ -830,9 +827,9 @@ static PointerRNA rna_Window_view_layer_get(PointerRNA *ptr)
return rna_pointer_inherit_refine(&scene_ptr, &RNA_ViewLayer, view_layer);
}
-static void rna_Window_view_layer_set(struct ReportList *UNUSED(reports),
- PointerRNA *ptr,
- PointerRNA value)
+static void rna_Window_view_layer_set(PointerRNA *ptr,
+ PointerRNA value,
+ struct ReportList *UNUSED(reports))
{
wmWindow *win = ptr->data;
ViewLayer *view_layer = value.data;
@@ -1036,9 +1033,9 @@ static PointerRNA rna_WindowManager_active_keyconfig_get(PointerRNA *ptr)
return rna_pointer_inherit_refine(ptr, &RNA_KeyConfig, kc);
}
-static void rna_WindowManager_active_keyconfig_set(struct ReportList *UNUSED(reports),
- PointerRNA *ptr,
- PointerRNA value)
+static void rna_WindowManager_active_keyconfig_set(PointerRNA *ptr,
+ PointerRNA value,
+ struct ReportList *UNUSED(reports))
{
wmWindowManager *wm = ptr->data;
wmKeyConfig *kc = value.data;
diff --git a/source/blender/makesrna/intern/rna_wm_gizmo.c b/source/blender/makesrna/intern/rna_wm_gizmo.c
index 22162aa017b..b13c5da7002 100644
--- a/source/blender/makesrna/intern/rna_wm_gizmo.c
+++ b/source/blender/makesrna/intern/rna_wm_gizmo.c
@@ -744,7 +744,10 @@ static void rna_gizmogroup_draw_prepare_cb(const bContext *C, wmGizmoGroup *gzgr
RNA_parameter_list_free(&list);
}
-static void rna_gizmogroup_invoke_prepare_cb(const bContext *C, wmGizmoGroup *gzgroup, wmGizmo *gz)
+static void rna_gizmogroup_invoke_prepare_cb(const bContext *C,
+ wmGizmoGroup *gzgroup,
+ wmGizmo *gz,
+ const wmEvent *event)
{
extern FunctionRNA rna_GizmoGroup_invoke_prepare_func;
@@ -759,6 +762,7 @@ static void rna_gizmogroup_invoke_prepare_cb(const bContext *C, wmGizmoGroup *gz
RNA_parameter_list_create(&list, &gzgroup_ptr, func);
RNA_parameter_set_lookup(&list, "context", &C);
RNA_parameter_set_lookup(&list, "gizmo", &gz);
+ RNA_parameter_set_lookup(&list, "event", &event);
gzgroup->type->ext.call((bContext *)C, &gzgroup_ptr, func, &list);
RNA_parameter_list_free(&list);
diff --git a/source/blender/modifiers/intern/MOD_weighted_normal.c b/source/blender/modifiers/intern/MOD_weighted_normal.c
index 7fbaa24b579..0accbe607eb 100644
--- a/source/blender/modifiers/intern/MOD_weighted_normal.c
+++ b/source/blender/modifiers/intern/MOD_weighted_normal.c
@@ -35,6 +35,8 @@
#include "MOD_modifiertypes.h"
#include "MOD_util.h"
+#include "bmesh.h"
+
#define CLNORS_VALID_VEC_LEN (1e-6f)
typedef struct ModePair {
diff --git a/source/blender/nodes/shader/nodes/node_shader_bsdf_principled.c b/source/blender/nodes/shader/nodes/node_shader_bsdf_principled.c
index 6c3e082f36a..48065cb10c9 100644
--- a/source/blender/nodes/shader/nodes/node_shader_bsdf_principled.c
+++ b/source/blender/nodes/shader/nodes/node_shader_bsdf_principled.c
@@ -164,7 +164,7 @@ static int node_shader_gpu_bsdf_principled(GPUMaterial *mat,
else if (use_subsurf && use_diffuse && !use_refract && !use_clear) {
static char name[] = "node_bsdf_principled_subsurface";
node_name = name;
- flag = GPU_MATFLAG_DIFFUSE | GPU_MATFLAG_SSS | GPU_MATFLAG_GLOSSY;
+ flag = GPU_MATFLAG_DIFFUSE | GPU_MATFLAG_GLOSSY;
}
else if (!use_subsurf && !use_diffuse && use_refract && !use_clear && !socket_not_zero(4)) {
static char name[] = "node_bsdf_principled_glass";
@@ -174,7 +174,11 @@ static int node_shader_gpu_bsdf_principled(GPUMaterial *mat,
else {
static char name[] = "node_bsdf_principled";
node_name = name;
- flag = GPU_MATFLAG_DIFFUSE | GPU_MATFLAG_GLOSSY | GPU_MATFLAG_SSS | GPU_MATFLAG_REFRACT;
+ flag = GPU_MATFLAG_DIFFUSE | GPU_MATFLAG_GLOSSY | GPU_MATFLAG_REFRACT;
+ }
+
+ if (use_subsurf) {
+ flag |= GPU_MATFLAG_SSS;
}
GPU_material_flag_set(mat, flag);
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 a9183cd10ef..786386bb63e 100644
--- a/source/blender/nodes/shader/nodes/node_shader_tex_image.c
+++ b/source/blender/nodes/shader/nodes/node_shader_tex_image.c
@@ -180,8 +180,12 @@ static int node_shader_gpu_tex_image(GPUMaterial *mat,
}
if (out[0].hasoutput) {
+ /* When the alpha socket is used, unpremultiply alpha. This makes it so
+ * that if we blend the color with a transparent shader using alpha as
+ * a factor, we don't multiply alpha into the color twice. */
if (out[1].hasoutput &&
- !IMB_colormanagement_space_name_is_data(ima->colorspace_settings.name)) {
+ !(ELEM(ima->alpha_mode, IMA_ALPHA_IGNORE, IMA_ALPHA_CHANNEL_PACKED) ||
+ IMB_colormanagement_space_name_is_data(ima->colorspace_settings.name))) {
GPU_link(mat, "tex_color_alpha_unpremultiply", out[0].link, &out[0].link);
}
else {
diff --git a/source/blender/physics/intern/implicit_blender.c b/source/blender/physics/intern/implicit_blender.c
index cdd4d66d485..d64846e4dcc 100644
--- a/source/blender/physics/intern/implicit_blender.c
+++ b/source/blender/physics/intern/implicit_blender.c
@@ -608,17 +608,16 @@ DO_INLINE void initdiag_bfmatrix(fmatrix3x3 *matrix, float m3[3][3])
/* STATUS: verified */
DO_INLINE void mul_bfmatrix_lfvector(float (*to)[3], fmatrix3x3 *from, lfVector *fLongVector)
{
- unsigned int i = 0;
unsigned int vcount = from[0].vcount;
lfVector *temp = create_lfvector(vcount);
zero_lfvector(to, vcount);
-# pragma omp parallel sections private(i) if (vcount > CLOTH_OPENMP_LIMIT)
+# pragma omp parallel sections if (vcount > CLOTH_OPENMP_LIMIT)
{
# pragma omp section
{
- for (i = from[0].vcount; i < from[0].vcount + from[0].scount; i++) {
+ for (unsigned int i = from[0].vcount; i < from[0].vcount + from[0].scount; i++) {
/* This is the lower triangle of the sparse matrix,
* therefore multiplication occurs with transposed submatrices. */
muladd_fmatrixT_fvector(to[from[i].c], from[i].m, fLongVector[from[i].r]);
@@ -626,7 +625,7 @@ DO_INLINE void mul_bfmatrix_lfvector(float (*to)[3], fmatrix3x3 *from, lfVector
}
# pragma omp section
{
- for (i = 0; i < from[0].vcount + from[0].scount; i++) {
+ for (unsigned int i = 0; i < from[0].vcount + from[0].scount; i++) {
muladd_fmatrix_fvector(temp[from[i].r], from[i].m, fLongVector[from[i].c]);
}
}
diff --git a/source/blender/python/intern/bpy_app_handlers.c b/source/blender/python/intern/bpy_app_handlers.c
index 7134bf520ac..dde3d026d47 100644
--- a/source/blender/python/intern/bpy_app_handlers.c
+++ b/source/blender/python/intern/bpy_app_handlers.c
@@ -61,6 +61,7 @@ static PyStructSequence_Field app_cb_info_fields[] = {
{(char *)"depsgraph_update_pre", (char *)"on depsgraph update (pre)"},
{(char *)"depsgraph_update_post", (char *)"on depsgraph update (post)"},
{(char *)"version_update", (char *)"on ending the versioning code"},
+ {(char *)"load_factory_preferences_post", (char *)"on loading factory preferences (after)"},
{(char *)"load_factory_startup_post", (char *)"on loading factory startup (after)"},
/* sets the permanent tag */
diff --git a/source/blender/python/intern/bpy_rna.c b/source/blender/python/intern/bpy_rna.c
index e5487a6a0c9..092c9061bb7 100644
--- a/source/blender/python/intern/bpy_rna.c
+++ b/source/blender/python/intern/bpy_rna.c
@@ -2032,7 +2032,7 @@ static int pyrna_py_to_prop(
ReportList reports;
BKE_reports_init(&reports, RPT_STORE);
RNA_property_pointer_set(
- &reports, ptr, prop, value == Py_None ? PointerRNA_NULL : param->ptr);
+ ptr, prop, value == Py_None ? PointerRNA_NULL : param->ptr, &reports);
int err = (BPy_reports_to_error(&reports, PyExc_RuntimeError, true));
if (err == -1) {
Py_XDECREF(value_new);
diff --git a/source/blender/python/mathutils/mathutils_Matrix.c b/source/blender/python/mathutils/mathutils_Matrix.c
index 7cc9ba50d90..2e664616639 100644
--- a/source/blender/python/mathutils/mathutils_Matrix.c
+++ b/source/blender/python/mathutils/mathutils_Matrix.c
@@ -585,6 +585,34 @@ static PyObject *C_Matrix_Translation(PyObject *cls, PyObject *value)
return Matrix_CreatePyObject(&mat[0][0], 4, 4, (PyTypeObject *)cls);
}
+/* ----------------------------------mathutils.Matrix.Diagonal() ------------- */
+PyDoc_STRVAR(C_Matrix_Diagonal_doc,
+ ".. classmethod:: Diagonal(vector)\n"
+ "\n"
+ " Create a diagonal (scaling) matrix using the values from the vector.\n"
+ "\n"
+ " :arg vector: The vector of values for the diagonal.\n"
+ " :type vector: :class:`Vector`\n"
+ " :return: A diagonal matrix.\n"
+ " :rtype: :class:`Matrix`\n");
+static PyObject *C_Matrix_Diagonal(PyObject *cls, PyObject *value)
+{
+ float mat[16] = {0.0f};
+ float vec[4];
+
+ int size = mathutils_array_parse(
+ vec, 2, 4, value, "mathutils.Matrix.Diagonal(vector), invalid vector arg");
+
+ if (size == -1) {
+ return NULL;
+ }
+
+ for (int i = 0; i < size; i++) {
+ mat[size * i + i] = vec[i];
+ }
+
+ return Matrix_CreatePyObject(mat, size, size, (PyTypeObject *)cls);
+}
/* ----------------------------------mathutils.Matrix.Scale() ------------- */
/* mat is a 1D array of floats - row[0][0], row[0][1], row[1][0], etc. */
PyDoc_STRVAR(C_Matrix_Scale_doc,
@@ -3085,6 +3113,7 @@ static struct PyMethodDef Matrix_methods[] = {
{"Rotation", (PyCFunction)C_Matrix_Rotation, METH_VARARGS | METH_CLASS, C_Matrix_Rotation_doc},
{"Scale", (PyCFunction)C_Matrix_Scale, METH_VARARGS | METH_CLASS, C_Matrix_Scale_doc},
{"Shear", (PyCFunction)C_Matrix_Shear, METH_VARARGS | METH_CLASS, C_Matrix_Shear_doc},
+ {"Diagonal", (PyCFunction)C_Matrix_Diagonal, METH_O | METH_CLASS, C_Matrix_Diagonal_doc},
{"Translation",
(PyCFunction)C_Matrix_Translation,
METH_O | METH_CLASS,
diff --git a/source/blender/render/intern/include/render_types.h b/source/blender/render/intern/include/render_types.h
index 63fd3f1d0bd..efa328cf14d 100644
--- a/source/blender/render/intern/include/render_types.h
+++ b/source/blender/render/intern/include/render_types.h
@@ -37,6 +37,7 @@
#include "RE_pipeline.h"
+struct GHash;
struct Main;
struct Object;
struct RenderEngine;
@@ -112,11 +113,16 @@ struct Render {
struct Object *camera_override;
ThreadRWMutex partsmutex;
- ListBase parts;
+ struct GHash *parts;
/* render engine */
struct RenderEngine *engine;
+ /* NOTE: This is a minimal dependency graph and evaluated scene which is enough to access view
+ * layer visibility and use for post-precessing (compositor and sequencer). */
+ Depsgraph *pipeline_depsgraph;
+ Scene *pipeline_scene_eval;
+
#ifdef WITH_FREESTYLE
struct Main *freestyle_bmain;
ListBase freestyle_renders;
diff --git a/source/blender/render/intern/source/external_engine.c b/source/blender/render/intern/source/external_engine.c
index 9a955b5e8f5..a5bf5adc243 100644
--- a/source/blender/render/intern/source/external_engine.c
+++ b/source/blender/render/intern/source/external_engine.c
@@ -29,9 +29,11 @@
#include "BLT_translation.h"
+#include "BLI_utildefines.h"
+#include "BLI_ghash.h"
#include "BLI_listbase.h"
+#include "BLI_rect.h"
#include "BLI_string.h"
-#include "BLI_utildefines.h"
#include "DNA_object_types.h"
@@ -169,18 +171,10 @@ void RE_engine_free(RenderEngine *engine)
static RenderPart *get_part_from_result(Render *re, RenderResult *result)
{
- RenderPart *pa;
-
- for (pa = re->parts.first; pa; pa = pa->next) {
- if (result->tilerect.xmin == pa->disprect.xmin - re->disprect.xmin &&
- result->tilerect.ymin == pa->disprect.ymin - re->disprect.ymin &&
- result->tilerect.xmax == pa->disprect.xmax - re->disprect.xmin &&
- result->tilerect.ymax == pa->disprect.ymax - re->disprect.ymin) {
- return pa;
- }
- }
+ rcti key = result->tilerect;
+ BLI_rcti_translate(&key, re->disprect.xmin, re->disprect.ymin);
- return NULL;
+ return BLI_ghash_lookup(re->parts, &key);
}
RenderResult *RE_engine_begin_result(
@@ -458,7 +452,6 @@ rcti *RE_engine_get_current_tiles(Render *re, int *r_total_tiles, bool *r_needs_
{
static rcti tiles_static[BLENDER_MAX_THREADS];
const int allocation_step = BLENDER_MAX_THREADS;
- RenderPart *pa;
int total_tiles = 0;
rcti *tiles = tiles_static;
int allocation_size = BLENDER_MAX_THREADS;
@@ -467,13 +460,15 @@ rcti *RE_engine_get_current_tiles(Render *re, int *r_total_tiles, bool *r_needs_
*r_needs_free = false;
- if (re->engine && (re->engine->flag & RE_ENGINE_HIGHLIGHT_TILES) == 0) {
+ if (!re->parts || (re->engine && (re->engine->flag & RE_ENGINE_HIGHLIGHT_TILES) == 0)) {
*r_total_tiles = 0;
BLI_rw_mutex_unlock(&re->partsmutex);
return NULL;
}
- for (pa = re->parts.first; pa; pa = pa->next) {
+ GHashIterator pa_iter;
+ GHASH_ITER (pa_iter, re->parts) {
+ RenderPart *pa = BLI_ghashIterator_getValue(&pa_iter);
if (pa->status == PART_STATUS_IN_PROGRESS) {
if (total_tiles >= allocation_size) {
/* Just in case we're using crazy network rendering with more
diff --git a/source/blender/render/intern/source/imagetexture.c b/source/blender/render/intern/source/imagetexture.c
index c147794dae7..1aa16dc1019 100644
--- a/source/blender/render/intern/source/imagetexture.c
+++ b/source/blender/render/intern/source/imagetexture.c
@@ -233,7 +233,7 @@ int imagewrap(Tex *tex,
/* keep this before interpolation [#29761] */
if (ima) {
- if ((tex->imaflag & TEX_USEALPHA) && (ima->flag & IMA_IGNORE_ALPHA) == 0) {
+ if ((tex->imaflag & TEX_USEALPHA) && (ima->alpha_mode != IMA_ALPHA_IGNORE)) {
if ((tex->imaflag & TEX_CALCALPHA) == 0) {
texres->talpha = true;
}
@@ -1056,7 +1056,7 @@ static int imagewraposa_aniso(Tex *tex,
image_mipmap_test(tex, ibuf);
if (ima) {
- if ((tex->imaflag & TEX_USEALPHA) && (ima->flag & IMA_IGNORE_ALPHA) == 0) {
+ if ((tex->imaflag & TEX_USEALPHA) && (ima->alpha_mode != IMA_ALPHA_IGNORE)) {
if ((tex->imaflag & TEX_CALCALPHA) == 0) {
texres->talpha = 1;
}
@@ -1512,7 +1512,7 @@ int imagewraposa(Tex *tex,
image_mipmap_test(tex, ibuf);
if (ima) {
- if ((tex->imaflag & TEX_USEALPHA) && (ima->flag & IMA_IGNORE_ALPHA) == 0) {
+ if ((tex->imaflag & TEX_USEALPHA) && (ima->alpha_mode != IMA_ALPHA_IGNORE)) {
if ((tex->imaflag & TEX_CALCALPHA) == 0) {
texres->talpha = true;
}
diff --git a/source/blender/render/intern/source/initrender.c b/source/blender/render/intern/source/initrender.c
index 4540e4e2cc2..acdd801bd86 100644
--- a/source/blender/render/intern/source/initrender.c
+++ b/source/blender/render/intern/source/initrender.c
@@ -31,6 +31,7 @@
#include "MEM_guardedalloc.h"
#include "BLI_math.h"
+#include "BLI_ghash.h"
#include "BLI_blenlib.h"
#include "BLI_utildefines.h"
@@ -245,7 +246,10 @@ void RE_GetCameraModelMatrix(Render *re, struct Object *camera, float r_mat[4][4
void RE_parts_free(Render *re)
{
- BLI_freelistN(&re->parts);
+ if (re->parts) {
+ BLI_ghash_free(re->parts, NULL, MEM_freeN);
+ re->parts = NULL;
+ }
}
void RE_parts_clamp(Render *re)
@@ -262,6 +266,9 @@ void RE_parts_init(Render *re)
RE_parts_free(re);
+ re->parts = BLI_ghash_new(
+ BLI_ghashutil_inthash_v4_p, BLI_ghashutil_inthash_v4_cmp, "render parts");
+
/* this is render info for caller, is not reset when parts are freed! */
re->i.totpart = 0;
re->i.curpart = 0;
@@ -323,7 +330,7 @@ void RE_parts_init(Render *re)
pa->rectx = rectx;
pa->recty = recty;
- BLI_addtail(&re->parts, pa);
+ BLI_ghash_insert(re->parts, &pa->disprect, pa);
re->i.totpart++;
}
}
diff --git a/source/blender/render/intern/source/pipeline.c b/source/blender/render/intern/source/pipeline.c
index 9c1c713ab94..76767d0d1d8 100644
--- a/source/blender/render/intern/source/pipeline.c
+++ b/source/blender/render/intern/source/pipeline.c
@@ -74,6 +74,7 @@
#include "DEG_depsgraph.h"
#include "DEG_depsgraph_build.h"
+#include "DEG_depsgraph_debug.h"
#include "DEG_depsgraph_query.h"
#include "PIL_time.h"
@@ -1430,10 +1431,10 @@ static void free_all_freestyle_renders(void)
/* returns fully composited render-result on given time step (in RenderData) */
static void do_render_composite(Render *re)
{
- bNodeTree *ntree = re->scene->nodetree;
+ bNodeTree *ntree = re->pipeline_scene_eval->nodetree;
int update_newframe = 0;
- if (composite_needs_render(re->scene, 1)) {
+ if (composite_needs_render(re->pipeline_scene_eval, 1)) {
/* save memory... free all cached images */
ntreeFreeCache(ntree);
@@ -1471,7 +1472,7 @@ static void do_render_composite(Render *re)
if (!re->test_break(re->tbh)) {
if (ntree) {
- ntreeCompositTagRender(re->scene);
+ ntreeCompositTagRender(re->pipeline_scene_eval);
}
if (ntree && re->scene->use_nodes && re->r.scemode & R_DOCOMP) {
@@ -1494,7 +1495,7 @@ static void do_render_composite(Render *re)
RenderView *rv;
for (rv = re->result->views.first; rv; rv = rv->next) {
- ntreeCompositExecTree(re->scene,
+ ntreeCompositExecTree(re->pipeline_scene_eval,
ntree,
&re->r,
true,
@@ -1595,12 +1596,8 @@ static void do_render_seq(Render *re)
tot_views = BKE_scene_multiview_num_views_get(&re->r);
ibuf_arr = MEM_mallocN(sizeof(ImBuf *) * tot_views, "Sequencer Views ImBufs");
- /* TODO(sergey): Currently depsgraph is only used to check whether it is an active
- * edit window or not to deal with unkeyed changes. We don't have depsgraph here yet,
- * but we also dont' deal with unkeyed changes. But still nice to get proper depsgraph
- * within tjhe render pipeline, somehow.
- */
- BKE_sequencer_new_render_data(re->main, NULL, re->scene, re_x, re_y, 100, true, &context);
+ BKE_sequencer_new_render_data(
+ re->main, re->pipeline_depsgraph, re->scene, re_x, re_y, 100, true, &context);
/* the renderresult gets destroyed during the rendering, so we first collect all ibufs
* and then we populate the final renderesult */
@@ -1613,7 +1610,7 @@ static void do_render_seq(Render *re)
ibuf_arr[view_id] = IMB_dupImBuf(out);
IMB_metadata_copy(ibuf_arr[view_id], out);
IMB_freeImBuf(out);
- BKE_sequencer_imbuf_from_sequencer_space(re->scene, ibuf_arr[view_id]);
+ BKE_sequencer_imbuf_from_sequencer_space(re->pipeline_scene_eval, ibuf_arr[view_id]);
}
else {
ibuf_arr[view_id] = NULL;
@@ -1641,9 +1638,9 @@ static void do_render_seq(Render *re)
}
if (recurs_depth == 0) { /* with nested scenes, only free on toplevel... */
- Editing *ed = re->scene->ed;
+ Editing *ed = re->pipeline_scene_eval->ed;
if (ed) {
- BKE_sequencer_free_imbuf(re->scene, &ed->seqbase, true);
+ BKE_sequencer_free_imbuf(re->pipeline_scene_eval, &ed->seqbase, true);
}
}
IMB_freeImBuf(ibuf_arr[view_id]);
@@ -2071,6 +2068,32 @@ void RE_SetReports(Render *re, ReportList *reports)
re->reports = reports;
}
+static void render_update_depsgraph(Render *re)
+{
+ Scene *scene = re->scene;
+ /* TODO(sergey): This doesn't run any callbacks and doesn't do sound update. But we can not use
+ * BKE_scene_graph_update_for_newframe() because that one builds dependency graph for view layer
+ * and not for the render pipeline. */
+ DEG_evaluate_on_framechange(re->main, re->pipeline_depsgraph, CFRA);
+}
+
+static void render_init_depsgraph(Render *re)
+{
+ Scene *scene = re->scene;
+ ViewLayer *view_layer = BKE_view_layer_default_render(re->scene);
+
+ re->pipeline_depsgraph = DEG_graph_new(scene, view_layer, DAG_EVAL_RENDER);
+ DEG_debug_name_set(re->pipeline_depsgraph, "RENDER PIPELINE");
+
+ /* Make sure there is a correct evaluated scene pointer. */
+ DEG_graph_build_for_render_pipeline(re->pipeline_depsgraph, re->main, scene, view_layer);
+
+ /* Update immediately so we have proper evaluated scene. */
+ render_update_depsgraph(re);
+
+ re->pipeline_scene_eval = DEG_get_evaluated_scene(re->pipeline_depsgraph);
+}
+
/* general Blender frame render call */
void RE_RenderFrame(Render *re,
Main *bmain,
@@ -2093,6 +2116,8 @@ void RE_RenderFrame(Render *re,
const RenderData rd = scene->r;
MEM_reset_peak_memory();
+ render_init_depsgraph(re);
+
BLI_callback_exec(re->main, (ID *)scene, BLI_CB_EVT_RENDER_PRE);
do_render_all_options(re);
@@ -2490,6 +2515,8 @@ void RE_RenderAnim(Render *re,
return;
}
+ render_init_depsgraph(re);
+
if (is_movie) {
size_t width, height;
int i;
@@ -2556,6 +2583,8 @@ void RE_RenderAnim(Render *re,
BKE_animsys_evaluate_animdata(NULL, scene, &scene->id, adt, ctime, ADT_RECALC_ALL);
}
+ render_update_depsgraph(re);
+
/* only border now, todo: camera lens. (ton) */
render_initialize_from_main(re, &rd, bmain, scene, single_layer, camera_override, 1, 0);
@@ -2746,6 +2775,11 @@ void RE_CleanAfterRender(Render *re)
{
/* Destroy the opengl context in the correct thread. */
RE_gl_context_destroy(re);
+ if (re->pipeline_depsgraph != NULL) {
+ DEG_graph_free(re->pipeline_depsgraph);
+ }
+ re->pipeline_depsgraph = NULL;
+ re->pipeline_scene_eval = NULL;
}
/* note; repeated win/disprect calc... solve that nicer, also in compo */
diff --git a/source/blender/render/intern/source/render_result.c b/source/blender/render/intern/source/render_result.c
index 9ca9472e571..04dabad611f 100644
--- a/source/blender/render/intern/source/render_result.c
+++ b/source/blender/render/intern/source/render_result.c
@@ -29,6 +29,7 @@
#include "MEM_guardedalloc.h"
#include "BLI_utildefines.h"
+#include "BLI_ghash.h"
#include "BLI_listbase.h"
#include "BLI_hash_md5.h"
#include "BLI_path_util.h"
@@ -1174,13 +1175,14 @@ static void save_render_result_tile(RenderResult *rr, RenderResult *rrpart, cons
void render_result_save_empty_result_tiles(Render *re)
{
- RenderPart *pa;
RenderResult *rr;
RenderLayer *rl;
for (rr = re->result; rr; rr = rr->next) {
for (rl = rr->layers.first; rl; rl = rl->next) {
- for (pa = re->parts.first; pa; pa = pa->next) {
+ GHashIterator pa_iter;
+ GHASH_ITER (pa_iter, re->parts) {
+ RenderPart *pa = BLI_ghashIterator_getValue(&pa_iter);
if (pa->status != PART_STATUS_MERGED) {
int party = pa->disprect.ymin - re->disprect.ymin;
int partx = pa->disprect.xmin - re->disprect.xmin;
diff --git a/source/blender/windowmanager/CMakeLists.txt b/source/blender/windowmanager/CMakeLists.txt
index 7e53c652ab5..64f506f03a8 100644
--- a/source/blender/windowmanager/CMakeLists.txt
+++ b/source/blender/windowmanager/CMakeLists.txt
@@ -74,6 +74,7 @@ set(SRC
intern/wm_toolsystem.c
intern/wm_tooltip.c
intern/wm_uilist_type.c
+ intern/wm_utils.c
intern/wm_window.c
gizmo/intern/wm_gizmo.c
gizmo/intern/wm_gizmo_group.c
diff --git a/source/blender/windowmanager/WM_api.h b/source/blender/windowmanager/WM_api.h
index 70f986732ad..a5eb892841c 100644
--- a/source/blender/windowmanager/WM_api.h
+++ b/source/blender/windowmanager/WM_api.h
@@ -60,6 +60,7 @@ struct wmEvent;
struct wmEventHandler;
struct wmEventHandler_Keymap;
struct wmEventHandler_UI;
+struct wmGenericUserData;
struct wmGesture;
struct wmJob;
struct wmMsgSubscribeKey;
@@ -598,6 +599,7 @@ bool WM_gesture_is_modal_first(const struct wmGesture *gesture);
/* fileselecting support */
void WM_event_add_fileselect(struct bContext *C, struct wmOperator *op);
void WM_event_fileselect_event(struct wmWindowManager *wm, void *ophandle, int eventval);
+int WM_event_modifier_flag(const struct wmEvent *event);
void WM_event_print(const struct wmEvent *event);
void WM_operator_region_active_win_set(struct bContext *C);
@@ -795,6 +797,12 @@ void WM_tooltip_init(struct bContext *C, struct wmWindow *win);
void WM_tooltip_refresh(struct bContext *C, struct wmWindow *win);
double WM_tooltip_time_closed(void);
+/* wm_utils.c */
+struct wmGenericCallback *WM_generic_callback_steal(struct wmGenericCallback *callback);
+void WM_generic_callback_free(struct wmGenericCallback *callback);
+
+void WM_generic_user_data_free(struct wmGenericUserData *user_data);
+
#ifdef __cplusplus
}
#endif
diff --git a/source/blender/windowmanager/WM_keymap.h b/source/blender/windowmanager/WM_keymap.h
index 53488cd1f71..4a9a9cf8705 100644
--- a/source/blender/windowmanager/WM_keymap.h
+++ b/source/blender/windowmanager/WM_keymap.h
@@ -114,6 +114,8 @@ void WM_keymap_add_context_enum_set_items(wmKeyMap *keymap,
wmKeyMap *WM_keymap_guess_from_context(const struct bContext *C);
wmKeyMap *WM_keymap_guess_opname(const struct bContext *C, const char *opname);
+bool WM_keymap_uses_event_modifier(wmKeyMap *keymap, const int event_modifier);
+
void WM_keymap_fix_linking(void);
/* Modal Keymap */
diff --git a/source/blender/windowmanager/WM_types.h b/source/blender/windowmanager/WM_types.h
index b3c36857dce..eddea3b2062 100644
--- a/source/blender/windowmanager/WM_types.h
+++ b/source/blender/windowmanager/WM_types.h
@@ -120,6 +120,19 @@ struct wmWindowManager;
/* Include external gizmo API's */
#include "gizmo/WM_gizmo_api.h"
+typedef struct wmGenericUserData {
+ void *data;
+ /** When NULL, use #MEM_freeN. */
+ void (*free_fn)(void *data);
+ bool use_free;
+} wmGenericUserData;
+
+typedef struct wmGenericCallback {
+ void (*exec)(struct bContext *C, void *user_data);
+ void *user_data;
+ void (*free_user_data)(void *user_data);
+} wmGenericCallback;
+
/* ************** wmOperatorType ************************ */
/* flag */
@@ -442,8 +455,7 @@ typedef struct wmGesture {
/* customdata for straight line is a recti: (xmin,ymin) is start, (xmax, ymax) is end */
/* free pointer to use for operator allocs (if set, its freed on exit)*/
- void *userdata;
- bool userdata_free;
+ wmGenericUserData user_data;
} wmGesture;
/* ************** wmEvent ************************ */
diff --git a/source/blender/windowmanager/gizmo/WM_gizmo_api.h b/source/blender/windowmanager/gizmo/WM_gizmo_api.h
index 9a272b27f87..bef3cd51aea 100644
--- a/source/blender/windowmanager/gizmo/WM_gizmo_api.h
+++ b/source/blender/windowmanager/gizmo/WM_gizmo_api.h
@@ -235,10 +235,21 @@ void WM_gizmo_target_property_subscribe_all(struct wmGizmo *gz,
/* wmGizmoGroup */
/* Callbacks for 'wmGizmoGroupType.setup_keymap' */
-struct wmKeyMap *WM_gizmogroup_keymap_common(const struct wmGizmoGroupType *gzgt,
- struct wmKeyConfig *config);
-struct wmKeyMap *WM_gizmogroup_keymap_common_select(const struct wmGizmoGroupType *gzgt,
- struct wmKeyConfig *config);
+struct wmKeyMap *WM_gizmogroup_keymap_template_ex(struct wmKeyConfig *config,
+ const char *idname,
+ const struct wmGizmoMapType_Params *params);
+struct wmKeyMap *WM_gizmogroup_keymap_template(const struct wmGizmoGroupType *gzgt,
+ struct wmKeyConfig *config);
+
+struct wmKeyMap *WM_gizmogroup_keymap_template_select_ex(
+ struct wmKeyConfig *config, const char *idname, const struct wmGizmoMapType_Params *params);
+struct wmKeyMap *WM_gizmogroup_keymap_template_select(const struct wmGizmoGroupType *gzgt,
+ struct wmKeyConfig *config);
+
+struct wmKeyMap *WM_gizmogroup_keymap_generic(const struct wmGizmoGroupType *gzgt,
+ struct wmKeyConfig *config);
+struct wmKeyMap *WM_gizmogroup_keymap_generic_select(const struct wmGizmoGroupType *gzgt,
+ struct wmKeyConfig *config);
void WM_gizmogroup_ensure_init(const struct bContext *C, struct wmGizmoGroup *gzgroup);
diff --git a/source/blender/windowmanager/gizmo/WM_gizmo_types.h b/source/blender/windowmanager/gizmo/WM_gizmo_types.h
index 7d38194db1b..cd8bcc6696b 100644
--- a/source/blender/windowmanager/gizmo/WM_gizmo_types.h
+++ b/source/blender/windowmanager/gizmo/WM_gizmo_types.h
@@ -182,6 +182,9 @@ struct wmGizmo {
/** Pointer back to group this gizmo is in (just for quick access). */
struct wmGizmoGroup *parent_gzgroup;
+ /** Optional keymap to use for this gizmo (overrides #wmGizmoGroupType.keymap) */
+ struct wmKeyMap *keymap;
+
void *py_instance;
/** Rna pointer to access properties. */
@@ -195,7 +198,11 @@ struct wmGizmo {
/** Optional ID for highlighting different parts of this gizmo.
* -1 when unset, otherwise a valid index. (Used as index to 'op_data'). */
int highlight_part;
- /** For single click button gizmos, use a different part as a fallback, -1 when unused. */
+
+ /**
+ * For gizmos that differentiate between click & drag,
+ * use a different part for any drag events, -1 when unused.
+ */
int drag_part;
/** Distance to bias this gizmo above others when picking
diff --git a/source/blender/windowmanager/gizmo/intern/wm_gizmo_group.c b/source/blender/windowmanager/gizmo/intern/wm_gizmo_group.c
index 5aecab122a2..f0e4c45843f 100644
--- a/source/blender/windowmanager/gizmo/intern/wm_gizmo_group.c
+++ b/source/blender/windowmanager/gizmo/intern/wm_gizmo_group.c
@@ -31,6 +31,7 @@
#include "MEM_guardedalloc.h"
+#include "BLI_buffer.h"
#include "BLI_listbase.h"
#include "BLI_string.h"
#include "BLI_math.h"
@@ -58,10 +59,6 @@
# include "BPY_extern.h"
#endif
-/* Allow gizmo part's to be single click only,
- * dragging falls back to activating their 'drag_part' action. */
-#define USE_DRAG_DETECT
-
/* -------------------------------------------------------------------- */
/** \name wmGizmoGroup
*
@@ -171,14 +168,48 @@ int WM_gizmo_cmp_temp_fl_reverse(const void *gz_a_ptr, const void *gz_b_ptr)
}
}
-wmGizmo *wm_gizmogroup_find_intersected_gizmo(const wmGizmoGroup *gzgroup,
+static bool wm_gizmo_keymap_uses_event_modifier(wmWindowManager *wm,
+ const wmGizmoGroup *gzgroup,
+ wmGizmo *gz,
+ const int event_modifier,
+ int *r_gzgroup_keymap_uses_modifier)
+{
+ if (gz->keymap) {
+ wmKeyMap *keymap = WM_keymap_active(wm, gz->keymap);
+ if (!WM_keymap_uses_event_modifier(keymap, event_modifier)) {
+ return false;
+ }
+ }
+ else if (gzgroup->type->keymap) {
+ if (*r_gzgroup_keymap_uses_modifier == -1) {
+ wmKeyMap *keymap = WM_keymap_active(wm, gzgroup->type->keymap);
+ *r_gzgroup_keymap_uses_modifier = WM_keymap_uses_event_modifier(keymap, event_modifier);
+ }
+ if (*r_gzgroup_keymap_uses_modifier == 0) {
+ return false;
+ }
+ }
+ return true;
+}
+
+wmGizmo *wm_gizmogroup_find_intersected_gizmo(wmWindowManager *wm,
+ const wmGizmoGroup *gzgroup,
bContext *C,
- const wmEvent *event,
+ const int event_modifier,
+ const int mval[2],
int *r_part)
{
+ int gzgroup_keymap_uses_modifier = -1;
+
for (wmGizmo *gz = gzgroup->gizmos.first; gz; gz = gz->next) {
if (gz->type->test_select && (gz->flag & (WM_GIZMO_HIDDEN | WM_GIZMO_HIDDEN_SELECT)) == 0) {
- if ((*r_part = gz->type->test_select(C, gz, event->mval)) != -1) {
+
+ if (!wm_gizmo_keymap_uses_event_modifier(
+ wm, gzgroup, gz, event_modifier, &gzgroup_keymap_uses_modifier)) {
+ continue;
+ }
+
+ if ((*r_part = gz->type->test_select(C, gz, mval)) != -1) {
return gz;
}
}
@@ -191,14 +222,24 @@ wmGizmo *wm_gizmogroup_find_intersected_gizmo(const wmGizmoGroup *gzgroup,
* Adds all gizmos of \a gzgroup that can be selected to the head of \a listbase.
* Added items need freeing!
*/
-void wm_gizmogroup_intersectable_gizmos_to_list(const wmGizmoGroup *gzgroup, ListBase *listbase)
+void wm_gizmogroup_intersectable_gizmos_to_list(wmWindowManager *wm,
+ const wmGizmoGroup *gzgroup,
+ const int event_modifier,
+ BLI_Buffer *visible_gizmos)
{
- for (wmGizmo *gz = gzgroup->gizmos.first; gz; gz = gz->next) {
+ int gzgroup_keymap_uses_modifier = -1;
+ for (wmGizmo *gz = gzgroup->gizmos.last; gz; gz = gz->prev) {
if ((gz->flag & (WM_GIZMO_HIDDEN | WM_GIZMO_HIDDEN_SELECT)) == 0) {
if (((gzgroup->type->flag & WM_GIZMOGROUPTYPE_3D) &&
(gz->type->draw_select || gz->type->test_select)) ||
((gzgroup->type->flag & WM_GIZMOGROUPTYPE_3D) == 0 && gz->type->test_select)) {
- BLI_addhead(listbase, BLI_genericNodeN(gz));
+
+ if (!wm_gizmo_keymap_uses_event_modifier(
+ wm, gzgroup, gz, event_modifier, &gzgroup_keymap_uses_modifier)) {
+ continue;
+ }
+
+ BLI_buffer_append(visible_gizmos, wmGizmo *, gz);
}
}
}
@@ -349,22 +390,6 @@ typedef struct GizmoTweakData {
int init_event; /* initial event type */
int flag; /* tweak flags */
-#ifdef USE_DRAG_DETECT
- /* True until the mouse is moved (only use when the operator has no modal).
- * this allows some gizmos to be click-only. */
- enum {
- /* Don't detect dragging. */
- DRAG_NOP = 0,
- /* Detect dragging (wait until a drag or click is detected). */
- DRAG_DETECT,
- /* Drag has started, idle until there is no active modal operator.
- * This is needed because finishing the modal operator also exits
- * the modal gizmo state (un-grabbs the cursor).
- * Ideally this workaround could be removed later. */
- DRAG_IDLE,
- } drag_state;
-#endif
-
} GizmoTweakData;
static bool gizmo_tweak_start(bContext *C, wmGizmoMap *gzmap, wmGizmo *gz, const wmEvent *event)
@@ -409,7 +434,7 @@ static bool gizmo_tweak_start_and_finish(
}
else {
if (gz->parent_gzgroup->type->invoke_prepare) {
- gz->parent_gzgroup->type->invoke_prepare(C, gz->parent_gzgroup, gz);
+ gz->parent_gzgroup->type->invoke_prepare(C, gz->parent_gzgroup, gz, event);
}
/* Allow for 'button' gizmos, single click to run an action. */
WM_gizmo_operator_invoke(C, gz, gzop);
@@ -449,47 +474,6 @@ static int gizmo_tweak_modal(bContext *C, wmOperator *op, const wmEvent *event)
return (OPERATOR_CANCELLED | OPERATOR_PASS_THROUGH);
}
-#ifdef USE_DRAG_DETECT
- wmGizmoMap *gzmap = mtweak->gzmap;
- if (mtweak->drag_state == DRAG_DETECT) {
- if (ELEM(event->type, MOUSEMOVE, INBETWEEN_MOUSEMOVE)) {
- if (len_manhattan_v2v2_int(&event->x, gzmap->gzmap_context.event_xy) >=
- WM_EVENT_CURSOR_CLICK_DRAG_THRESHOLD) {
- mtweak->drag_state = DRAG_IDLE;
- gz->highlight_part = gz->drag_part;
- }
- }
- else if (event->type == mtweak->init_event && event->val == KM_RELEASE) {
- mtweak->drag_state = DRAG_NOP;
- retval = OPERATOR_FINISHED;
- }
-
- if (mtweak->drag_state != DRAG_DETECT) {
- /* Follow logic in 'gizmo_tweak_invoke' */
- bool is_modal = false;
- if (gizmo_tweak_start_and_finish(C, gzmap, gz, event, &is_modal)) {
- if (is_modal) {
- clear_modal = false;
- }
- }
- else {
- if (!gizmo_tweak_start(C, gzmap, gz, event)) {
- retval = OPERATOR_FINISHED;
- }
- }
- }
- }
- if (mtweak->drag_state == DRAG_IDLE) {
- if (gzmap->gzmap_context.modal != NULL) {
- return OPERATOR_PASS_THROUGH;
- }
- else {
- gizmo_tweak_finish(C, op, false, false);
- return OPERATOR_FINISHED;
- }
- }
-#endif /* USE_DRAG_DETECT */
-
if (retval == OPERATOR_FINISHED) {
/* pass */
}
@@ -560,35 +544,22 @@ static int gizmo_tweak_invoke(bContext *C, wmOperator *op, const wmEvent *event)
return (OPERATOR_CANCELLED | OPERATOR_PASS_THROUGH);
}
- bool use_drag_fallback = false;
+ const int highlight_part_init = gz->highlight_part;
-#ifdef USE_DRAG_DETECT
- use_drag_fallback = !ELEM(gz->drag_part, -1, gz->highlight_part);
-#endif
-
- if (use_drag_fallback == false) {
- if (gizmo_tweak_start_and_finish(C, gzmap, gz, event, NULL)) {
- return OPERATOR_FINISHED;
+ if (gz->drag_part != -1) {
+ if (ISTWEAK(event->type) || (event->val == KM_CLICK_DRAG)) {
+ gz->highlight_part = gz->drag_part;
}
}
- bool use_drag_detect = false;
-#ifdef USE_DRAG_DETECT
- if (use_drag_fallback) {
- wmGizmoOpElem *gzop = WM_gizmo_operator_get(gz, gz->highlight_part);
- if (gzop && gzop->type) {
- if (gzop->type->modal == NULL) {
- use_drag_detect = true;
- }
- }
+ if (gizmo_tweak_start_and_finish(C, gzmap, gz, event, NULL)) {
+ return OPERATOR_FINISHED;
}
-#endif
- if (use_drag_detect == false) {
- if (!gizmo_tweak_start(C, gzmap, gz, event)) {
- /* failed to start */
- return OPERATOR_PASS_THROUGH;
- }
+ if (!gizmo_tweak_start(C, gzmap, gz, event)) {
+ /* failed to start */
+ gz->highlight_part = highlight_part_init;
+ return OPERATOR_PASS_THROUGH;
}
GizmoTweakData *mtweak = MEM_mallocN(sizeof(GizmoTweakData), __func__);
@@ -599,10 +570,6 @@ static int gizmo_tweak_invoke(bContext *C, wmOperator *op, const wmEvent *event)
mtweak->gzmap = gzmap;
mtweak->flag = 0;
-#ifdef USE_DRAG_DETECT
- mtweak->drag_state = use_drag_detect ? DRAG_DETECT : DRAG_NOP;
-#endif
-
op->customdata = mtweak;
WM_event_add_modal_handler(C, op);
@@ -630,7 +597,7 @@ void GIZMOGROUP_OT_gizmo_tweak(wmOperatorType *ot)
/** \} */
-static wmKeyMap *gizmogroup_tweak_modal_keymap(wmKeyConfig *keyconf, const char *gzgroupname)
+wmKeyMap *wm_gizmogroup_tweak_modal_keymap(wmKeyConfig *keyconf)
{
wmKeyMap *keymap;
char name[KMAP_MAX_NAME];
@@ -645,7 +612,7 @@ static wmKeyMap *gizmogroup_tweak_modal_keymap(wmKeyConfig *keyconf, const char
{0, NULL, 0, NULL, NULL},
};
- BLI_snprintf(name, sizeof(name), "%s Tweak Modal Map", gzgroupname);
+ STRNCPY(name, "Generic Gizmo Tweak Modal Map");
keymap = WM_modalkeymap_get(keyconf, name);
/* this function is called for each spacetype, only needs to add map once */
@@ -678,30 +645,54 @@ static wmKeyMap *gizmogroup_tweak_modal_keymap(wmKeyConfig *keyconf, const char
}
/**
- * Common default keymap for gizmo groups
+ * Common default keymap for gizmo groups.
+ *
+ * \param name: Typically #wmGizmoGroupType.name
+ * \param params: Typically #wmGizmoGroupType.gzmap_params
*/
-wmKeyMap *WM_gizmogroup_keymap_common(const wmGizmoGroupType *gzgt, wmKeyConfig *config)
+wmKeyMap *WM_gizmogroup_keymap_template_ex(wmKeyConfig *config,
+ const char *name,
+ const struct wmGizmoMapType_Params *params)
{
/* Use area and region id since we might have multiple gizmos
* with the same name in different areas/regions. */
- wmKeyMap *km = WM_keymap_ensure(
- config, gzgt->name, gzgt->gzmap_params.spaceid, gzgt->gzmap_params.regionid);
-
- WM_keymap_add_item(km, "GIZMOGROUP_OT_gizmo_tweak", LEFTMOUSE, KM_PRESS, KM_ANY, 0);
- gizmogroup_tweak_modal_keymap(config, gzgt->name);
+ wmKeyMap *km = WM_keymap_ensure(config, name, params->spaceid, params->regionid);
+ if (BLI_listbase_is_empty(&km->items)) {
+ WM_keymap_add_item(km, "GIZMOGROUP_OT_gizmo_tweak", LEFTMOUSE, KM_PRESS, KM_ANY, 0);
+ }
return km;
}
+wmKeyMap *WM_gizmogroup_keymap_template(const wmGizmoGroupType *gzgt, wmKeyConfig *config)
+{
+ return WM_gizmogroup_keymap_template_ex(config, gzgt->name, &gzgt->gzmap_params);
+}
+
+wmKeyMap *WM_gizmogroup_keymap_generic(const wmGizmoGroupType *UNUSED(gzgt), wmKeyConfig *config)
+{
+ struct wmGizmoMapType_Params params = {
+ .spaceid = SPACE_EMPTY,
+ .regionid = RGN_TYPE_WINDOW,
+ };
+ return WM_gizmogroup_keymap_template_ex(config, "Generic Gizmo", &params);
+}
+
/**
* Variation of #WM_gizmogroup_keymap_common but with keymap items for selection
+ *
+ * \param name: Typically #wmGizmoGroupType.name
+ * \param params: Typically #wmGizmoGroupType.gzmap_params
*/
-wmKeyMap *WM_gizmogroup_keymap_common_select(const wmGizmoGroupType *gzgt, wmKeyConfig *config)
+wmKeyMap *WM_gizmogroup_keymap_template_select_ex(wmKeyConfig *config,
+ const char *name,
+ const struct wmGizmoMapType_Params *params)
{
/* Use area and region id since we might have multiple gizmos
* with the same name in different areas/regions. */
- wmKeyMap *km = WM_keymap_ensure(
- config, gzgt->name, gzgt->gzmap_params.spaceid, gzgt->gzmap_params.regionid);
+ wmKeyMap *km = WM_keymap_ensure(config, name, params->spaceid, params->regionid);
+ const bool do_init = BLI_listbase_is_empty(&km->items);
+
/* FIXME(campbell) */
#if 0
const int select_mouse = (U.flag & USER_LMOUSESELECT) ? LEFTMOUSE : RIGHTMOUSE;
@@ -713,23 +704,42 @@ wmKeyMap *WM_gizmogroup_keymap_common_select(const wmGizmoGroupType *gzgt, wmKey
const int action_mouse = LEFTMOUSE;
#endif
- WM_keymap_add_item(km, "GIZMOGROUP_OT_gizmo_tweak", action_mouse, KM_PRESS, KM_ANY, 0);
- WM_keymap_add_item(km, "GIZMOGROUP_OT_gizmo_tweak", select_tweak, KM_ANY, 0, 0);
- gizmogroup_tweak_modal_keymap(config, gzgt->name);
+ if (do_init) {
+ WM_keymap_add_item(km, "GIZMOGROUP_OT_gizmo_tweak", action_mouse, KM_PRESS, KM_ANY, 0);
+ WM_keymap_add_item(km, "GIZMOGROUP_OT_gizmo_tweak", select_tweak, KM_ANY, 0, 0);
+ }
- wmKeyMapItem *kmi = WM_keymap_add_item(
- km, "GIZMOGROUP_OT_gizmo_select", select_mouse, KM_PRESS, 0, 0);
- RNA_boolean_set(kmi->ptr, "extend", false);
- RNA_boolean_set(kmi->ptr, "deselect", false);
- RNA_boolean_set(kmi->ptr, "toggle", false);
- kmi = WM_keymap_add_item(km, "GIZMOGROUP_OT_gizmo_select", select_mouse, KM_PRESS, KM_SHIFT, 0);
- RNA_boolean_set(kmi->ptr, "extend", false);
- RNA_boolean_set(kmi->ptr, "deselect", false);
- RNA_boolean_set(kmi->ptr, "toggle", true);
+ if (do_init) {
+ wmKeyMapItem *kmi = WM_keymap_add_item(
+ km, "GIZMOGROUP_OT_gizmo_select", select_mouse, KM_PRESS, 0, 0);
+ RNA_boolean_set(kmi->ptr, "extend", false);
+ RNA_boolean_set(kmi->ptr, "deselect", false);
+ RNA_boolean_set(kmi->ptr, "toggle", false);
+ kmi = WM_keymap_add_item(
+ km, "GIZMOGROUP_OT_gizmo_select", select_mouse, KM_PRESS, KM_SHIFT, 0);
+ RNA_boolean_set(kmi->ptr, "extend", false);
+ RNA_boolean_set(kmi->ptr, "deselect", false);
+ RNA_boolean_set(kmi->ptr, "toggle", true);
+ }
return km;
}
+wmKeyMap *WM_gizmogroup_keymap_template_select(const wmGizmoGroupType *gzgt, wmKeyConfig *config)
+{
+ return WM_gizmogroup_keymap_template_select_ex(config, gzgt->name, &gzgt->gzmap_params);
+}
+
+wmKeyMap *WM_gizmogroup_keymap_generic_select(const wmGizmoGroupType *UNUSED(gzgt),
+ wmKeyConfig *config)
+{
+ struct wmGizmoMapType_Params params = {
+ .spaceid = SPACE_EMPTY,
+ .regionid = RGN_TYPE_WINDOW,
+ };
+ return WM_gizmogroup_keymap_template_select_ex(config, "Generic Gizmo Select", &params);
+}
+
/** \} */ /* wmGizmoGroup */
/* -------------------------------------------------------------------- */
@@ -874,8 +884,12 @@ void WM_gizmomaptype_group_unlink(bContext *C,
WM_gizmomaptype_group_free(gzgt_ref);
}
+ /* TODO(campbell): Gizmos may share keymaps, for now don't
+ * remove however we could flag them as temporary/owned by the gizmo. */
+#if 0
/* Note, we may want to keep this keymap for editing */
WM_keymap_remove(gzgt->keyconf, gzgt->keymap);
+#endif
BLI_assert(WM_gizmomaptype_group_find_ptr(gzmap_type, gzgt) == NULL);
}
diff --git a/source/blender/windowmanager/gizmo/intern/wm_gizmo_group_type.c b/source/blender/windowmanager/gizmo/intern/wm_gizmo_group_type.c
index 7c8db18c0ca..d09e088af7f 100644
--- a/source/blender/windowmanager/gizmo/intern/wm_gizmo_group_type.c
+++ b/source/blender/windowmanager/gizmo/intern/wm_gizmo_group_type.c
@@ -97,10 +97,10 @@ static void wm_gizmogrouptype_append__end(wmGizmoGroupType *gzgt)
/* if not set, use default */
if (gzgt->setup_keymap == NULL) {
if (gzgt->flag & WM_GIZMOGROUPTYPE_SELECT) {
- gzgt->setup_keymap = WM_gizmogroup_keymap_common_select;
+ gzgt->setup_keymap = WM_gizmogroup_keymap_generic_select;
}
else {
- gzgt->setup_keymap = WM_gizmogroup_keymap_common;
+ gzgt->setup_keymap = WM_gizmogroup_keymap_generic;
}
}
diff --git a/source/blender/windowmanager/gizmo/intern/wm_gizmo_intern.h b/source/blender/windowmanager/gizmo/intern/wm_gizmo_intern.h
index 1a0babdccb5..1018cc4d58b 100644
--- a/source/blender/windowmanager/gizmo/intern/wm_gizmo_intern.h
+++ b/source/blender/windowmanager/gizmo/intern/wm_gizmo_intern.h
@@ -21,6 +21,7 @@
#ifndef __WM_GIZMO_INTERN_H__
#define __WM_GIZMO_INTERN_H__
+struct BLI_Buffer;
struct GHashIterator;
struct GizmoGeomInfo;
struct wmGizmoMap;
@@ -60,17 +61,23 @@ struct wmGizmoGroup *wm_gizmogroup_new_from_type(struct wmGizmoMap *gzmap,
struct wmGizmoGroupType *gzgt);
void wm_gizmogroup_free(bContext *C, struct wmGizmoGroup *gzgroup);
void wm_gizmogroup_gizmo_register(struct wmGizmoGroup *gzgroup, struct wmGizmo *gz);
-struct wmGizmo *wm_gizmogroup_find_intersected_gizmo(const struct wmGizmoGroup *gzgroup,
+struct wmGizmo *wm_gizmogroup_find_intersected_gizmo(wmWindowManager *wm,
+ const struct wmGizmoGroup *gzgroup,
struct bContext *C,
- const struct wmEvent *event,
+ const int event_modifier,
+ const int mval[2],
int *r_part);
-void wm_gizmogroup_intersectable_gizmos_to_list(const struct wmGizmoGroup *gzgroup,
- struct ListBase *listbase);
+void wm_gizmogroup_intersectable_gizmos_to_list(wmWindowManager *wm,
+ const struct wmGizmoGroup *gzgroup,
+ const int event_modifier,
+ struct BLI_Buffer *visible_gizmos);
bool wm_gizmogroup_is_visible_in_drawstep(const struct wmGizmoGroup *gzgroup,
const eWM_GizmoFlagMapDrawStep drawstep);
void wm_gizmogrouptype_setup_keymap(struct wmGizmoGroupType *gzgt, struct wmKeyConfig *keyconf);
+wmKeyMap *wm_gizmogroup_tweak_modal_keymap(struct wmKeyConfig *keyconf);
+
/* -------------------------------------------------------------------- */
/* wmGizmoMap */
diff --git a/source/blender/windowmanager/gizmo/intern/wm_gizmo_map.c b/source/blender/windowmanager/gizmo/intern/wm_gizmo_map.c
index 9f36af8b616..6783a294500 100644
--- a/source/blender/windowmanager/gizmo/intern/wm_gizmo_map.c
+++ b/source/blender/windowmanager/gizmo/intern/wm_gizmo_map.c
@@ -23,12 +23,12 @@
#include <string.h>
+#include "BLI_buffer.h"
#include "BLI_listbase.h"
#include "BLI_math.h"
#include "BLI_math_bits.h"
#include "BLI_rect.h"
#include "BLI_ghash.h"
-#include "BLI_array.h"
#include "BKE_context.h"
#include "BKE_global.h"
@@ -470,24 +470,19 @@ void WM_gizmomap_draw(wmGizmoMap *gzmap,
BLI_assert(BLI_listbase_is_empty(&draw_gizmos));
}
-static void gizmo_draw_select_3D_loop(const bContext *C,
- ListBase *visible_gizmos,
- const wmGizmo *gz_stop,
+static void gizmo_draw_select_3d_loop(const bContext *C,
+ wmGizmo **visible_gizmos,
+ const int visible_gizmos_len,
bool *r_use_select_bias)
{
- int select_id = 0;
- wmGizmo *gz;
/* TODO(campbell): this depends on depth buffer being written to,
* currently broken for the 3D view. */
bool is_depth_prev = false;
bool is_depth_skip_prev = false;
- for (LinkData *link = visible_gizmos->first; link; link = link->next, select_id++) {
- gz = link->data;
- if (gz == gz_stop) {
- break;
- }
+ for (int select_id = 0; select_id < visible_gizmos_len; select_id++) {
+ wmGizmo *gz = visible_gizmos[select_id];
if (gz->type->draw_select == NULL) {
continue;
}
@@ -531,11 +526,11 @@ static void gizmo_draw_select_3D_loop(const bContext *C,
}
}
-static int gizmo_find_intersected_3d_intern(ListBase *visible_gizmos,
+static int gizmo_find_intersected_3d_intern(wmGizmo **visible_gizmos,
+ const int visible_gizmos_len,
const bContext *C,
const int co[2],
- const int hotspot,
- const wmGizmo *gz_stop)
+ const int hotspot)
{
ScrArea *sa = CTX_wm_area(C);
ARegion *ar = CTX_wm_region(C);
@@ -554,13 +549,13 @@ static int gizmo_find_intersected_3d_intern(ListBase *visible_gizmos,
GPU_select_begin(buffer, ARRAY_SIZE(buffer), &rect, GPU_SELECT_NEAREST_FIRST_PASS, 0);
/* do the drawing */
- gizmo_draw_select_3D_loop(C, visible_gizmos, gz_stop, &use_select_bias);
+ gizmo_draw_select_3d_loop(C, visible_gizmos, visible_gizmos_len, &use_select_bias);
hits = GPU_select_end();
if (hits > 0) {
GPU_select_begin(buffer, ARRAY_SIZE(buffer), &rect, GPU_SELECT_NEAREST_SECOND_PASS, hits);
- gizmo_draw_select_3D_loop(C, visible_gizmos, gz_stop, &use_select_bias);
+ gizmo_draw_select_3d_loop(C, visible_gizmos, visible_gizmos_len, &use_select_bias);
GPU_select_end();
}
@@ -568,11 +563,6 @@ static int gizmo_find_intersected_3d_intern(ListBase *visible_gizmos,
CTX_wm_window(C), CTX_data_depsgraph(C), CTX_data_scene(C), ar, v3d, NULL, NULL, NULL);
if (use_select_bias && (hits > 1)) {
- wmGizmo **gizmo_table = NULL;
- BLI_array_staticdeclare(gizmo_table, 1024);
- for (LinkData *link = visible_gizmos->first; link; link = link->next) {
- BLI_array_append(gizmo_table, link->data);
- }
float co_direction[3];
float co_screen[3] = {co[0], co[1], 0.0f};
ED_view3d_win_to_vector(ar, (float[2]){UNPACK2(co)}, co_direction);
@@ -590,7 +580,7 @@ static int gizmo_find_intersected_3d_intern(ListBase *visible_gizmos,
for (int i = 0; i < hits; i++, buf_iter += 4) {
BLI_assert(buf_iter[3] != -1);
- wmGizmo *gz = gizmo_table[buf_iter[3] >> 8];
+ wmGizmo *gz = visible_gizmos[buf_iter[3] >> 8];
float co_3d[3];
co_screen[2] = int_as_float(buf_iter[1]);
GPU_matrix_unproject_model_inverted(co_screen, rv3d->viewinv, rv3d->winmat, viewport, co_3d);
@@ -605,7 +595,6 @@ static int gizmo_find_intersected_3d_intern(ListBase *visible_gizmos,
hit_found = buf_iter[3];
}
}
- BLI_array_free(gizmo_table);
return hit_found;
}
else {
@@ -619,10 +608,12 @@ static int gizmo_find_intersected_3d_intern(ListBase *visible_gizmos,
*/
static wmGizmo *gizmo_find_intersected_3d(bContext *C,
const int co[2],
- ListBase *visible_gizmos,
+ wmGizmo **visible_gizmos,
+ const int visible_gizmos_len,
int *r_part)
{
wmGizmo *result = NULL;
+ int visible_gizmos_len_trim = visible_gizmos_len;
int hit = -1;
*r_part = 0;
@@ -633,14 +624,15 @@ static wmGizmo *gizmo_find_intersected_3d(bContext *C,
/* Search for 3D gizmo's that use the 2D callback for checking intersections. */
bool has_3d = false;
{
- int select_id = 0;
- for (LinkData *link = visible_gizmos->first; link; link = link->next, select_id++) {
- wmGizmo *gz = link->data;
+ for (int select_id = 0; select_id < visible_gizmos_len; select_id++) {
+ wmGizmo *gz = visible_gizmos[select_id];
/* With both defined, favor the 3D, incase the gizmo can be used in 2D or 3D views. */
if (gz->type->test_select && (gz->type->draw_select == NULL)) {
if ((*r_part = gz->type->test_select(C, gz, co)) != -1) {
hit = select_id;
result = gz;
+ /* Don't search past this when checking intersections. */
+ visible_gizmos_len_trim = select_id;
break;
}
}
@@ -659,23 +651,19 @@ static wmGizmo *gizmo_find_intersected_3d(bContext *C,
10 * U.pixelsize,
};
for (int i = 0; i < ARRAY_SIZE(hotspot_radii); i++) {
- hit = gizmo_find_intersected_3d_intern(visible_gizmos, C, co, hotspot_radii[i], result);
+ hit = gizmo_find_intersected_3d_intern(
+ visible_gizmos, visible_gizmos_len_trim, C, co, hotspot_radii[i]);
if (hit != -1) {
break;
}
}
if (hit != -1) {
- LinkData *link = BLI_findlink(visible_gizmos, hit >> 8);
- if (link != NULL) {
- *r_part = hit & 255;
- result = link->data;
- }
- else {
- /* All gizmos should use selection ID they're given as part of the callback,
- * if they don't it will attempt tp lookup non-existing index. */
- BLI_assert(0);
- }
+ const int select_id = hit >> 8;
+ const int select_part = hit & 0xff;
+ BLI_assert(select_id < visible_gizmos_len);
+ *r_part = select_part;
+ result = visible_gizmos[select_id];
}
}
@@ -691,14 +679,26 @@ wmGizmo *wm_gizmomap_highlight_find(wmGizmoMap *gzmap,
const wmEvent *event,
int *r_part)
{
+ wmWindowManager *wm = CTX_wm_manager(C);
wmGizmo *gz = NULL;
- ListBase visible_3d_gizmos = {NULL};
+ BLI_buffer_declare_static(wmGizmo *, visible_3d_gizmos, BLI_BUFFER_NOP, 128);
bool do_step[WM_GIZMOMAP_DRAWSTEP_MAX];
+ int mval[2] = {UNPACK2(event->mval)};
+
+ /* Ensure for drag events we use the location where the user clicked.
+ * Without this click-dragging on a gizmo can accidentally act on the wrong gizmo. */
+ if (ISTWEAK(event->type) || (event->val == KM_CLICK_DRAG)) {
+ mval[0] += event->x - event->prevclickx;
+ mval[1] += event->y - event->prevclicky;
+ }
+
for (int i = 0; i < ARRAY_SIZE(do_step); i++) {
do_step[i] = WM_gizmo_context_check_drawstep(C, i);
}
+ const int event_modifier = WM_event_modifier_flag(event);
+
for (wmGizmoGroup *gzgroup = gzmap->groups.first; gzgroup; gzgroup = gzgroup->next) {
/* If it were important we could initialize here,
@@ -724,10 +724,12 @@ wmGizmo *wm_gizmomap_highlight_find(wmGizmoMap *gzmap,
/* cleared below */
}
if (step == WM_GIZMOMAP_DRAWSTEP_3D) {
- wm_gizmogroup_intersectable_gizmos_to_list(gzgroup, &visible_3d_gizmos);
+ wm_gizmogroup_intersectable_gizmos_to_list(
+ wm, gzgroup, event_modifier, &visible_3d_gizmos);
}
else if (step == WM_GIZMOMAP_DRAWSTEP_2D) {
- if ((gz = wm_gizmogroup_find_intersected_gizmo(gzgroup, C, event, r_part))) {
+ if ((gz = wm_gizmogroup_find_intersected_gizmo(
+ wm, gzgroup, C, event_modifier, mval, r_part))) {
break;
}
}
@@ -735,13 +737,14 @@ wmGizmo *wm_gizmomap_highlight_find(wmGizmoMap *gzmap,
}
}
- if (!BLI_listbase_is_empty(&visible_3d_gizmos)) {
+ if (visible_3d_gizmos.count) {
/* 2D gizmos get priority. */
if (gz == NULL) {
- gz = gizmo_find_intersected_3d(C, event->mval, &visible_3d_gizmos, r_part);
+ gz = gizmo_find_intersected_3d(
+ C, mval, visible_3d_gizmos.data, visible_3d_gizmos.count, r_part);
}
- BLI_freelistN(&visible_3d_gizmos);
}
+ BLI_buffer_free(&visible_3d_gizmos);
gzmap->update_flag[WM_GIZMOMAP_DRAWSTEP_3D] &= ~GIZMOMAP_IS_REFRESH_CALLBACK;
gzmap->update_flag[WM_GIZMOMAP_DRAWSTEP_2D] &= ~GIZMOMAP_IS_REFRESH_CALLBACK;
@@ -1021,7 +1024,7 @@ void wm_gizmomap_modal_set(
/* Use even if we don't have invoke, so we can setup data before an operator runs. */
if (gz->parent_gzgroup->type->invoke_prepare) {
- gz->parent_gzgroup->type->invoke_prepare(C, gz->parent_gzgroup, gz);
+ gz->parent_gzgroup->type->invoke_prepare(C, gz->parent_gzgroup, gz, event);
}
if (gz->type->invoke && (gz->type->modal || gz->custom_modal)) {
@@ -1216,6 +1219,8 @@ void wm_gizmos_keymap(wmKeyConfig *keyconf)
wm_gizmogrouptype_setup_keymap(gzgt_ref->type, keyconf);
}
}
+
+ wm_gizmogroup_tweak_modal_keymap(keyconf);
}
/** \} */ /* wmGizmoMapType */
diff --git a/source/blender/windowmanager/gizmo/wm_gizmo_fn.h b/source/blender/windowmanager/gizmo/wm_gizmo_fn.h
index 2aada0f202a..242b0f6de80 100644
--- a/source/blender/windowmanager/gizmo/wm_gizmo_fn.h
+++ b/source/blender/windowmanager/gizmo/wm_gizmo_fn.h
@@ -33,7 +33,8 @@ typedef void (*wmGizmoGroupFnRefresh)(const struct bContext *, struct wmGizmoGro
typedef void (*wmGizmoGroupFnDrawPrepare)(const struct bContext *, struct wmGizmoGroup *);
typedef void (*wmGizmoGroupFnInvokePrepare)(const struct bContext *,
struct wmGizmoGroup *,
- struct wmGizmo *);
+ struct wmGizmo *,
+ const struct wmEvent *);
typedef struct wmKeyMap *(*wmGizmoGroupFnSetupKeymap)(const struct wmGizmoGroupType *,
struct wmKeyConfig *)ATTR_WARN_UNUSED_RESULT;
typedef void (*wmGizmoGroupFnMsgBusSubscribe)(const struct bContext *,
diff --git a/source/blender/windowmanager/intern/wm_draw.c b/source/blender/windowmanager/intern/wm_draw.c
index 6ecbf4ef5ac..6b6a04cacad 100644
--- a/source/blender/windowmanager/intern/wm_draw.c
+++ b/source/blender/windowmanager/intern/wm_draw.c
@@ -917,6 +917,17 @@ void WM_draw_region_free(ARegion *ar)
ar->visible = 0;
}
+void wm_draw_region_test(bContext *C, ScrArea *sa, ARegion *ar)
+{
+ /* Function for redraw timer benchmark. */
+ bool use_viewport = wm_region_use_viewport(sa, ar);
+ wm_draw_region_buffer_create(ar, false, use_viewport);
+ wm_draw_region_bind(ar, 0);
+ ED_region_do_draw(C, ar);
+ wm_draw_region_unbind(ar, 0);
+ ar->do_draw = false;
+}
+
void WM_redraw_windows(bContext *C)
{
wmWindow *win_prev = CTX_wm_window(C);
diff --git a/source/blender/windowmanager/intern/wm_event_system.c b/source/blender/windowmanager/intern/wm_event_system.c
index 6683085e6d3..51b2ca6a3d0 100644
--- a/source/blender/windowmanager/intern/wm_event_system.c
+++ b/source/blender/windowmanager/intern/wm_event_system.c
@@ -732,6 +732,24 @@ void WM_operator_region_active_win_set(bContext *C)
}
}
+int WM_event_modifier_flag(const wmEvent *event)
+{
+ int flag = 0;
+ if (event->ctrl) {
+ flag |= KM_CTRL;
+ }
+ if (event->alt) {
+ flag |= KM_ALT;
+ }
+ if (event->shift) {
+ flag |= KM_SHIFT;
+ }
+ if (event->oskey) {
+ flag |= KM_OSKEY;
+ }
+ return flag;
+}
+
/* for debugging only, getting inspecting events manually is tedious */
void WM_event_print(const wmEvent *event)
{
@@ -2484,15 +2502,134 @@ static int wm_action_not_handled(int action)
return action == WM_HANDLER_CONTINUE || action == (WM_HANDLER_BREAK | WM_HANDLER_MODAL);
}
+#define PRINT \
+ if (do_debug_handler) \
+ printf
+
+static int wm_handlers_do_keymap_with_keymap_handler(
+ /* From 'wm_handlers_do_intern' */
+ bContext *C,
+ wmEvent *event,
+ ListBase *handlers,
+ wmEventHandler_Keymap *handler,
+ /* Additional. */
+ wmKeyMap *keymap,
+ const bool do_debug_handler)
+{
+ int action = WM_HANDLER_CONTINUE;
+
+ PRINT("%s: checking '%s' ...", __func__, keymap->idname);
+
+ if (keymap == NULL) {
+ /* Only callback is allowed to have NULL keymaps. */
+ BLI_assert(handler->dynamic.keymap_fn);
+ }
+ else {
+ if (WM_keymap_poll(C, keymap)) {
+
+ PRINT("pass\n");
+
+ for (wmKeyMapItem *kmi = keymap->items.first; kmi; kmi = kmi->next) {
+ if (wm_eventmatch(event, kmi)) {
+ struct wmEventHandler_KeymapPost keymap_post = handler->post;
+
+ PRINT("%s: item matched '%s'\n", __func__, kmi->idname);
+
+ /* weak, but allows interactive callback to not use rawkey */
+ event->keymap_idname = kmi->idname;
+
+ action |= wm_handler_operator_call(C, handlers, &handler->head, event, kmi->ptr);
+
+ if (action & WM_HANDLER_BREAK) {
+ /* not always_pass here, it denotes removed handler_base */
+ CLOG_INFO(WM_LOG_HANDLERS, 2, "handled! '%s'", kmi->idname);
+ if (keymap_post.post_fn != NULL) {
+ keymap_post.post_fn(keymap, kmi, keymap_post.user_data);
+ }
+ break;
+ }
+ else {
+ if (action & WM_HANDLER_HANDLED) {
+ CLOG_INFO(WM_LOG_HANDLERS, 2, "handled - and pass on! '%s'", kmi->idname);
+ }
+ else {
+ CLOG_INFO(WM_LOG_HANDLERS, 2, "un-handled '%s'", kmi->idname);
+ }
+ }
+ }
+ }
+ }
+ else {
+ PRINT("fail\n");
+ }
+ }
+
+ return action;
+}
+
+static bool wm_handlers_do_keymap_with_gizmo_handler(
+ /* From 'wm_handlers_do_intern' */
+ bContext *C,
+ wmEvent *event,
+ ListBase *handlers,
+ wmEventHandler_Gizmo *handler,
+ /* Additional. */
+ wmGizmoGroup *gzgroup,
+ wmKeyMap *keymap,
+ const bool do_debug_handler)
+{
+ int action = WM_HANDLER_CONTINUE;
+ wmKeyMapItem *kmi;
+
+ PRINT("%s: checking '%s' ...", __func__, keymap->idname);
+
+ if (WM_keymap_poll(C, keymap)) {
+ PRINT("pass\n");
+ for (kmi = keymap->items.first; kmi; kmi = kmi->next) {
+ if (wm_eventmatch(event, kmi)) {
+ PRINT("%s: item matched '%s'\n", __func__, kmi->idname);
+
+ /* weak, but allows interactive callback to not use rawkey */
+ event->keymap_idname = kmi->idname;
+
+ CTX_wm_gizmo_group_set(C, gzgroup);
+
+ /* handler->op is called later, we want keymap op to be triggered here */
+ action |= wm_handler_operator_call(C, handlers, &handler->head, event, kmi->ptr);
+
+ CTX_wm_gizmo_group_set(C, NULL);
+
+ if (action & WM_HANDLER_BREAK) {
+ if (G.debug & (G_DEBUG_EVENTS | G_DEBUG_HANDLERS)) {
+ printf("%s: handled - and pass on! '%s'\n", __func__, kmi->idname);
+ }
+ break;
+ }
+ else {
+ if (action & WM_HANDLER_HANDLED) {
+ if (G.debug & (G_DEBUG_EVENTS | G_DEBUG_HANDLERS)) {
+ printf("%s: handled - and pass on! '%s'\n", __func__, kmi->idname);
+ }
+ }
+ else {
+ PRINT("%s: un-handled '%s'\n", __func__, kmi->idname);
+ }
+ }
+ }
+ }
+ }
+ else {
+ PRINT("fail\n");
+ }
+ return action;
+}
+
static int wm_handlers_do_intern(bContext *C, wmEvent *event, ListBase *handlers)
{
const bool do_debug_handler =
(G.debug & G_DEBUG_HANDLERS) &&
/* comment this out to flood the console! (if you really want to test) */
!ELEM(event->type, MOUSEMOVE, INBETWEEN_MOUSEMOVE);
-#define PRINT \
- if (do_debug_handler) \
- printf
wmWindowManager *wm = CTX_wm_manager(C);
int action = WM_HANDLER_CONTINUE;
@@ -2530,50 +2667,8 @@ static int wm_handlers_do_intern(bContext *C, wmEvent *event, ListBase *handlers
if (handler_base->type == WM_HANDLER_TYPE_KEYMAP) {
wmEventHandler_Keymap *handler = (wmEventHandler_Keymap *)handler_base;
wmKeyMap *keymap = WM_event_get_keymap_from_handler(wm, handler);
-
- PRINT("%s: checking '%s' ...", __func__, keymap->idname);
-
- if (keymap == NULL) {
- /* Only callback is allowed to have NULL keymaps. */
- BLI_assert(handler->dynamic.keymap_fn);
- }
- else if (WM_keymap_poll(C, keymap)) {
-
- PRINT("pass\n");
-
- for (wmKeyMapItem *kmi = keymap->items.first; kmi; kmi = kmi->next) {
- if (wm_eventmatch(event, kmi)) {
- struct wmEventHandler_KeymapPost keymap_post = handler->post;
-
- PRINT("%s: item matched '%s'\n", __func__, kmi->idname);
-
- /* weak, but allows interactive callback to not use rawkey */
- event->keymap_idname = kmi->idname;
-
- action |= wm_handler_operator_call(C, handlers, handler_base, event, kmi->ptr);
-
- if (action & WM_HANDLER_BREAK) {
- /* not always_pass here, it denotes removed handler_base */
- CLOG_INFO(WM_LOG_HANDLERS, 2, "handled! '%s'", kmi->idname);
- if (keymap_post.post_fn != NULL) {
- keymap_post.post_fn(keymap, kmi, keymap_post.user_data);
- }
- break;
- }
- else {
- if (action & WM_HANDLER_HANDLED) {
- CLOG_INFO(WM_LOG_HANDLERS, 2, "handled - and pass on! '%s'", kmi->idname);
- }
- else {
- CLOG_INFO(WM_LOG_HANDLERS, 2, "un-handled '%s'", kmi->idname);
- }
- }
- }
- }
- }
- else {
- PRINT("fail\n");
- }
+ action |= wm_handlers_do_keymap_with_keymap_handler(
+ C, event, handlers, handler, keymap, do_debug_handler);
}
else if (handler_base->type == WM_HANDLER_TYPE_UI) {
wmEventHandler_UI *handler = (wmEventHandler_UI *)handler_base;
@@ -2644,8 +2739,27 @@ static int wm_handlers_do_intern(bContext *C, wmEvent *event, ListBase *handlers
wm_gizmomap_handler_context_gizmo(C, handler);
wm_region_mouse_co(C, event);
+ /* Drag events use the previous click location to highlight the gizmos,
+ * Get the highlight again in case the user dragged off the gizmo. */
+ const bool is_event_drag = ISTWEAK(event->type) || (event->val == KM_CLICK_DRAG);
+ const bool is_event_modifier = ISKEYMODIFIER(event->type);
+
+ bool handle_highlight = false;
+ bool handle_keymap = false;
+
/* handle gizmo highlighting */
- if (event->type == MOUSEMOVE && !wm_gizmomap_modal_get(gzmap)) {
+ if (!wm_gizmomap_modal_get(gzmap) &&
+ ((event->type == MOUSEMOVE) || is_event_modifier || is_event_drag)) {
+ handle_highlight = true;
+ if (is_event_modifier || is_event_drag) {
+ handle_keymap = true;
+ }
+ }
+ else {
+ handle_keymap = true;
+ }
+
+ if (handle_highlight) {
int part;
gz = wm_gizmomap_highlight_find(gzmap, C, event, &part);
if (wm_gizmomap_highlight_set(gzmap, C, gz, part) && gz != NULL) {
@@ -2654,98 +2768,35 @@ static int wm_handlers_do_intern(bContext *C, wmEvent *event, ListBase *handlers
}
}
}
- else {
- /* Either we operate on a single highlighted item
- * or groups attached to the selected gizmos.
- * To simplify things both cases loop over an array of items. */
- wmGizmoGroup *gzgroup_first;
- bool is_gzgroup_single;
-
- if (ISMOUSE(event->type)) {
- /* Keep gz set as-is, just fake single selection. */
- if (gz) {
- gzgroup_first = gz->parent_gzgroup;
- }
- else {
- gzgroup_first = NULL;
- }
- is_gzgroup_single = true;
- }
- else {
- if (WM_gizmomap_is_any_selected(gzmap)) {
- const ListBase *groups = WM_gizmomap_group_list(gzmap);
- gzgroup_first = groups->first;
- }
- else {
- gzgroup_first = NULL;
- }
- is_gzgroup_single = false;
+
+ if (handle_keymap) {
+ /* Handle highlight gizmo. */
+ if (gz != NULL) {
+ wmGizmoGroup *gzgroup = gz->parent_gzgroup;
+ wmKeyMap *keymap = WM_keymap_active(wm,
+ gz->keymap ? gz->keymap : gzgroup->type->keymap);
+ action |= wm_handlers_do_keymap_with_gizmo_handler(
+ C, event, handlers, handler, gzgroup, keymap, do_debug_handler);
}
/* Don't use from now on. */
gz = NULL;
- for (wmGizmoGroup *gzgroup = gzgroup_first; gzgroup; gzgroup = gzgroup->next) {
- /* get user customized keymap from default one */
-
- if ((is_gzgroup_single == false) &&
- /* We might want to change the logic here and use some kind of gizmo edit-mode.
- * For now just use keymap when a selection exists. */
- wm_gizmogroup_is_any_selected(gzgroup) == false) {
- continue;
- }
-
- wmKeyMap *keymap = WM_keymap_active(wm, gzgroup->type->keymap);
- wmKeyMapItem *kmi;
-
- PRINT("%s: checking '%s' ...", __func__, keymap->idname);
-
- if (WM_keymap_poll(C, keymap)) {
- PRINT("pass\n");
- for (kmi = keymap->items.first; kmi; kmi = kmi->next) {
- if (wm_eventmatch(event, kmi)) {
- PRINT("%s: item matched '%s'\n", __func__, kmi->idname);
-
- /* weak, but allows interactive callback to not use rawkey */
- event->keymap_idname = kmi->idname;
-
- CTX_wm_gizmo_group_set(C, gzgroup);
-
- /* handler->op is called later, we want keymap op to be triggered here */
- action |= wm_handler_operator_call(C, handlers, handler_base, event, kmi->ptr);
-
- CTX_wm_gizmo_group_set(C, NULL);
-
+ /* Fallback to selected gizmo (when un-handled). */
+ if ((action & WM_HANDLER_BREAK) == 0) {
+ if (WM_gizmomap_is_any_selected(gzmap)) {
+ const ListBase *groups = WM_gizmomap_group_list(gzmap);
+ for (wmGizmoGroup *gzgroup = groups->first; gzgroup; gzgroup = gzgroup->next) {
+ if (wm_gizmogroup_is_any_selected(gzgroup)) {
+ wmKeyMap *keymap = WM_keymap_active(wm, gzgroup->type->keymap);
+ action |= wm_handlers_do_keymap_with_gizmo_handler(
+ C, event, handlers, handler, gzgroup, keymap, do_debug_handler);
if (action & WM_HANDLER_BREAK) {
- if (G.debug & (G_DEBUG_EVENTS | G_DEBUG_HANDLERS)) {
- printf("%s: handled - and pass on! '%s'\n", __func__, kmi->idname);
- }
break;
}
- else {
- if (action & WM_HANDLER_HANDLED) {
- if (G.debug & (G_DEBUG_EVENTS | G_DEBUG_HANDLERS)) {
- printf("%s: handled - and pass on! '%s'\n", __func__, kmi->idname);
- }
- }
- else {
- PRINT("%s: un-handled '%s'\n", __func__, kmi->idname);
- }
- }
}
}
}
- else {
- PRINT("fail\n");
- }
-
- if (action & WM_HANDLER_BREAK) {
- break;
- }
-
- if (is_gzgroup_single) {
- break;
- }
}
}
@@ -2802,11 +2853,11 @@ static int wm_handlers_do_intern(bContext *C, wmEvent *event, ListBase *handlers
wm_cursor_arrow_move(CTX_wm_window(C), event);
}
-#undef PRINT
-
return action;
}
+#undef PRINT
+
/* this calls handlers twice - to solve (double-)click events */
static int wm_handlers_do(bContext *C, wmEvent *event, ListBase *handlers)
{
diff --git a/source/blender/windowmanager/intern/wm_files.c b/source/blender/windowmanager/intern/wm_files.c
index 9e9619c698d..d93d4a618d7 100644
--- a/source/blender/windowmanager/intern/wm_files.c
+++ b/source/blender/windowmanager/intern/wm_files.c
@@ -490,18 +490,21 @@ void wm_file_read_report(bContext *C, Main *bmain)
static void wm_file_read_post(bContext *C,
const bool is_startup_file,
const bool is_factory_startup,
+ const bool use_data,
+ const bool use_userdef,
const bool reset_app_template)
{
bool addons_loaded = false;
wmWindowManager *wm = CTX_wm_manager(C);
- if (!G.background) {
- /* remove windows which failed to be added via WM_check */
- wm_window_ghostwindows_remove_invalid(C, wm);
+ if (use_data) {
+ if (!G.background) {
+ /* remove windows which failed to be added via WM_check */
+ wm_window_ghostwindows_remove_invalid(C, wm);
+ }
+ CTX_wm_window_set(C, wm->windows.first);
}
- CTX_wm_window_set(C, wm->windows.first);
-
#ifdef WITH_PYTHON
if (is_startup_file) {
/* possible python hasn't been initialized */
@@ -515,41 +518,56 @@ static void wm_file_read_post(bContext *C,
/* sync addons, these may have changed from the defaults */
BPY_execute_string(C, (const char *[]){"addon_utils", NULL}, "addon_utils.reset_all()");
}
- BPY_python_reset(C);
+ if (use_data) {
+ BPY_python_reset(C);
+ }
addons_loaded = true;
}
}
else {
/* run any texts that were loaded in and flagged as modules */
- BPY_python_reset(C);
+ if (use_data) {
+ BPY_python_reset(C);
+ }
addons_loaded = true;
}
#else
UNUSED_VARS(is_startup_file, reset_app_template);
#endif /* WITH_PYTHON */
- WM_operatortype_last_properties_clear_all();
-
- /* important to do before NULL'ing the context */
Main *bmain = CTX_data_main(C);
- BLI_callback_exec(bmain, NULL, BLI_CB_EVT_VERSION_UPDATE);
- BLI_callback_exec(bmain, NULL, BLI_CB_EVT_LOAD_POST);
- if (is_factory_startup) {
- BLI_callback_exec(bmain, NULL, BLI_CB_EVT_LOAD_FACTORY_STARTUP_POST);
+
+ if (use_userdef) {
+ if (is_factory_startup) {
+ BLI_callback_exec(bmain, NULL, BLI_CB_EVT_LOAD_FACTORY_USERDEF_POST);
+ }
}
- /* After load post, so for example the driver namespace can be filled
- * before evaluating the depsgraph. */
- DEG_on_visible_update(bmain, true);
- wm_event_do_depsgraph(C);
+ if (use_data) {
+ /* important to do before NULL'ing the context */
+ BLI_callback_exec(bmain, NULL, BLI_CB_EVT_VERSION_UPDATE);
+ BLI_callback_exec(bmain, NULL, BLI_CB_EVT_LOAD_POST);
+ if (is_factory_startup) {
+ BLI_callback_exec(bmain, NULL, BLI_CB_EVT_LOAD_FACTORY_STARTUP_POST);
+ }
+ }
+
+ if (use_data) {
+ WM_operatortype_last_properties_clear_all();
- ED_editors_init(C);
+ /* After load post, so for example the driver namespace can be filled
+ * before evaluating the depsgraph. */
+ DEG_on_visible_update(bmain, true);
+ wm_event_do_depsgraph(C);
+
+ ED_editors_init(C);
#if 1
- WM_event_add_notifier(C, NC_WM | ND_FILEREAD, NULL);
+ WM_event_add_notifier(C, NC_WM | ND_FILEREAD, NULL);
#else
- WM_msg_publish_static(CTX_wm_message_bus(C), WM_MSG_STATICTYPE_FILE_READ);
+ WM_msg_publish_static(CTX_wm_message_bus(C), WM_MSG_STATICTYPE_FILE_READ);
#endif
+ }
/* report any errors.
* currently disabled if addons aren't yet loaded */
@@ -557,25 +575,29 @@ static void wm_file_read_post(bContext *C,
wm_file_read_report(C, bmain);
}
- if (!G.background) {
- if (wm->undo_stack == NULL) {
- wm->undo_stack = BKE_undosys_stack_create();
- }
- else {
- BKE_undosys_stack_clear(wm->undo_stack);
+ if (use_data) {
+ if (!G.background) {
+ if (wm->undo_stack == NULL) {
+ wm->undo_stack = BKE_undosys_stack_create();
+ }
+ else {
+ BKE_undosys_stack_clear(wm->undo_stack);
+ }
+ BKE_undosys_stack_init_from_main(wm->undo_stack, bmain);
+ BKE_undosys_stack_init_from_context(wm->undo_stack, C);
}
- BKE_undosys_stack_init_from_main(wm->undo_stack, bmain);
- BKE_undosys_stack_init_from_context(wm->undo_stack, C);
}
- if (!G.background) {
- /* in background mode this makes it hard to load
- * a blend file and do anything since the screen
- * won't be set to a valid value again */
- CTX_wm_window_set(C, NULL); /* exits queues */
+ if (use_data) {
+ if (!G.background) {
+ /* in background mode this makes it hard to load
+ * a blend file and do anything since the screen
+ * won't be set to a valid value again */
+ CTX_wm_window_set(C, NULL); /* exits queues */
- /* Ensure tools are registered. */
- WM_toolsystem_init(C);
+ /* Ensure tools are registered. */
+ WM_toolsystem_init(C);
+ }
}
}
@@ -602,6 +624,8 @@ bool WM_file_read(bContext *C, const char *filepath, ReportList *reports)
/* we didn't succeed, now try to read Blender file */
if (retval == BKE_READ_EXOTIC_OK_BLEND) {
+ bool use_data = true;
+ bool use_userdef = false;
const int G_f_orig = G.f;
ListBase wmbase;
@@ -640,6 +664,7 @@ bool WM_file_read(bContext *C, const char *filepath, ReportList *reports)
if (retval == BKE_BLENDFILE_READ_OK_USERPREFS) {
/* in case a userdef is read from regular .blend */
wm_init_userdef(bmain, false);
+ use_userdef = true;
}
if (retval != BKE_BLENDFILE_READ_FAIL) {
@@ -648,7 +673,7 @@ bool WM_file_read(bContext *C, const char *filepath, ReportList *reports)
}
}
- wm_file_read_post(C, false, false, false);
+ wm_file_read_post(C, false, false, use_data, use_userdef, false);
success = true;
}
@@ -953,7 +978,7 @@ void wm_homefile_read(bContext *C,
}
}
}
- if (BLI_listbase_is_empty(&wmbase)) {
+ if (use_data && BLI_listbase_is_empty(&wmbase)) {
wm_clear_default_size(C);
}
}
@@ -1041,10 +1066,10 @@ void wm_homefile_read(bContext *C,
/* start with save preference untitled.blend */
G.save_over = 0;
-
- wm_file_read_post(C, true, is_factory_startup, reset_app_template);
}
+ wm_file_read_post(C, true, is_factory_startup, use_data, use_userdef, reset_app_template);
+
if (r_is_factory_startup) {
*r_is_factory_startup = is_factory_startup;
}
@@ -1245,7 +1270,6 @@ static ImBuf *blend_file_thumb(const bContext *C,
BLEN_THUMB_SIZE * 2,
BLEN_THUMB_SIZE * 2,
IB_rect,
- V3D_OFSDRAW_NONE,
R_ALPHAPREMUL,
0,
NULL,
@@ -1653,6 +1677,7 @@ static int wm_userpref_autoexec_add_exec(bContext *UNUSED(C), wmOperator *UNUSED
{
bPathCompare *path_cmp = MEM_callocN(sizeof(bPathCompare), "bPathCompare");
BLI_addtail(&U.autoexec_paths, path_cmp);
+ U.runtime.is_dirty = true;
return OPERATOR_FINISHED;
}
@@ -1673,6 +1698,7 @@ static int wm_userpref_autoexec_remove_exec(bContext *UNUSED(C), wmOperator *op)
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;
}
@@ -1939,7 +1965,7 @@ static void wm_free_operator_properties_callback(void *user_data)
static int wm_homefile_read_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event))
{
if (U.uiflag & USER_SAVE_PROMPT && wm_file_or_image_is_modified(C)) {
- GenericCallback *callback = MEM_callocN(sizeof(*callback), __func__);
+ wmGenericCallback *callback = MEM_callocN(sizeof(*callback), __func__);
callback->exec = wm_homefile_read_after_dialog_callback;
callback->user_data = IDP_CopyProperty(op->properties);
callback->free_user_data = wm_free_operator_properties_callback;
@@ -2105,7 +2131,7 @@ static int wm_open_mainfile__discard_changes(bContext *C, wmOperator *op)
}
if (U.uiflag & USER_SAVE_PROMPT && wm_file_or_image_is_modified(C)) {
- GenericCallback *callback = MEM_callocN(sizeof(*callback), __func__);
+ wmGenericCallback *callback = MEM_callocN(sizeof(*callback), __func__);
callback->exec = wm_open_mainfile_after_dialog_callback;
callback->user_data = IDP_CopyProperty(op->properties);
callback->free_user_data = wm_free_operator_properties_callback;
@@ -2855,7 +2881,7 @@ static void wm_block_file_close_cancel(bContext *C, void *arg_block, void *UNUSE
static void wm_block_file_close_discard(bContext *C, void *arg_block, void *arg_data)
{
- GenericCallback *callback = wm_generic_callback_steal((GenericCallback *)arg_data);
+ wmGenericCallback *callback = WM_generic_callback_steal((wmGenericCallback *)arg_data);
/* Close the popup before executing the callback. Otherwise
* the popup might be closed by the callback, which will lead
@@ -2864,12 +2890,12 @@ static void wm_block_file_close_discard(bContext *C, void *arg_block, void *arg_
UI_popup_block_close(C, win, arg_block);
callback->exec(C, callback->user_data);
- wm_generic_callback_free(callback);
+ WM_generic_callback_free(callback);
}
static void wm_block_file_close_save(bContext *C, void *arg_block, void *arg_data)
{
- GenericCallback *callback = wm_generic_callback_steal((GenericCallback *)arg_data);
+ wmGenericCallback *callback = WM_generic_callback_steal((wmGenericCallback *)arg_data);
bool execute_callback = true;
wmWindow *win = CTX_wm_window(C);
@@ -2897,10 +2923,10 @@ static void wm_block_file_close_save(bContext *C, void *arg_block, void *arg_dat
if (execute_callback) {
callback->exec(C, callback->user_data);
}
- wm_generic_callback_free(callback);
+ WM_generic_callback_free(callback);
}
-static void wm_block_file_close_cancel_button(uiBlock *block, GenericCallback *post_action)
+static void wm_block_file_close_cancel_button(uiBlock *block, wmGenericCallback *post_action)
{
uiBut *but = uiDefIconTextBut(
block, UI_BTYPE_BUT, 0, 0, IFACE_("Cancel"), 0, 0, 0, UI_UNIT_Y, 0, 0, 0, 0, 0, "");
@@ -2908,7 +2934,7 @@ static void wm_block_file_close_cancel_button(uiBlock *block, GenericCallback *p
UI_but_drawflag_disable(but, UI_BUT_TEXT_LEFT);
}
-static void wm_block_file_close_discard_button(uiBlock *block, GenericCallback *post_action)
+static void wm_block_file_close_discard_button(uiBlock *block, wmGenericCallback *post_action)
{
uiBut *but = uiDefIconTextBut(
block, UI_BTYPE_BUT, 0, 0, IFACE_("Discard Changes"), 0, 0, 0, UI_UNIT_Y, 0, 0, 0, 0, 0, "");
@@ -2916,7 +2942,7 @@ static void wm_block_file_close_discard_button(uiBlock *block, GenericCallback *
UI_but_drawflag_disable(but, UI_BUT_TEXT_LEFT);
}
-static void wm_block_file_close_save_button(uiBlock *block, GenericCallback *post_action)
+static void wm_block_file_close_save_button(uiBlock *block, wmGenericCallback *post_action)
{
uiBut *but = uiDefIconTextBut(
block, UI_BTYPE_BUT, 0, 0, IFACE_("Save"), 0, 0, 0, UI_UNIT_Y, 0, 0, 0, 0, 0, "");
@@ -2925,13 +2951,15 @@ static void wm_block_file_close_save_button(uiBlock *block, GenericCallback *pos
UI_but_flag_enable(but, UI_BUT_ACTIVE_DEFAULT);
}
+static const char *close_file_dialog_name = "file_close_popup";
+
static uiBlock *block_create__close_file_dialog(struct bContext *C, struct ARegion *ar, void *arg1)
{
- GenericCallback *post_action = (GenericCallback *)arg1;
+ wmGenericCallback *post_action = (wmGenericCallback *)arg1;
Main *bmain = CTX_data_main(C);
uiStyle *style = UI_style_get();
- uiBlock *block = UI_block_begin(C, ar, "file_close_popup", UI_EMBOSS);
+ uiBlock *block = UI_block_begin(C, ar, close_file_dialog_name, UI_EMBOSS);
UI_block_flag_enable(
block, UI_BLOCK_KEEP_OPEN | UI_BLOCK_LOOP | UI_BLOCK_NO_WIN_CLIP | UI_BLOCK_NUMSELECT);
@@ -3020,13 +3048,13 @@ static uiBlock *block_create__close_file_dialog(struct bContext *C, struct ARegi
else {
/* macOS and Linux standard layout. */
uiLayout *col = uiLayoutColumn(split, false);
- wm_block_file_close_cancel_button(block, post_action);
+ wm_block_file_close_discard_button(block, post_action);
col = uiLayoutColumn(split, false);
uiItemS(col);
col = uiLayoutColumn(split, false);
- wm_block_file_close_discard_button(block, post_action);
+ wm_block_file_close_cancel_button(block, post_action);
col = uiLayoutColumn(split, false);
wm_block_file_close_save_button(block, post_action);
@@ -3038,14 +3066,19 @@ static uiBlock *block_create__close_file_dialog(struct bContext *C, struct ARegi
static void free_post_file_close_action(void *arg)
{
- GenericCallback *action = (GenericCallback *)arg;
- wm_generic_callback_free(action);
+ wmGenericCallback *action = (wmGenericCallback *)arg;
+ WM_generic_callback_free(action);
}
-void wm_close_file_dialog(bContext *C, GenericCallback *post_action)
+void wm_close_file_dialog(bContext *C, wmGenericCallback *post_action)
{
- UI_popup_block_invoke(
- C, block_create__close_file_dialog, post_action, free_post_file_close_action);
+ if (!UI_popup_block_name_exists(C, close_file_dialog_name)) {
+ UI_popup_block_invoke(
+ C, block_create__close_file_dialog, post_action, free_post_file_close_action);
+ }
+ else {
+ WM_generic_callback_free(post_action);
+ }
}
bool wm_file_or_image_is_modified(const bContext *C)
@@ -3054,25 +3087,4 @@ bool wm_file_or_image_is_modified(const bContext *C)
return !wm->file_saved || ED_image_should_save_modified(C);
}
-void wm_generic_callback_free(GenericCallback *callback)
-{
- if (callback->free_user_data) {
- callback->free_user_data(callback->user_data);
- }
- MEM_freeN(callback);
-}
-
-static void do_nothing(bContext *UNUSED(C), void *UNUSED(user_data))
-{
-}
-
-GenericCallback *wm_generic_callback_steal(GenericCallback *callback)
-{
- GenericCallback *new_callback = MEM_dupallocN(callback);
- callback->exec = do_nothing;
- callback->free_user_data = NULL;
- callback->user_data = NULL;
- return new_callback;
-}
-
/** \} */
diff --git a/source/blender/windowmanager/intern/wm_files_link.c b/source/blender/windowmanager/intern/wm_files_link.c
index 0cb3e5e3088..1a46a4550d9 100644
--- a/source/blender/windowmanager/intern/wm_files_link.c
+++ b/source/blender/windowmanager/intern/wm_files_link.c
@@ -729,7 +729,10 @@ static void lib_relocate_do(Main *bmain,
}
if (new_id) {
#ifdef PRINT_DEBUG
- printf("before remap, old_id users: %d, new_id users: %d\n", old_id->us, new_id->us);
+ printf("before remap of %s, old_id users: %d, new_id users: %d\n",
+ old_id->name,
+ old_id->us,
+ new_id->us);
#endif
BKE_libblock_remap_locked(bmain, old_id, new_id, remap_flags);
@@ -739,7 +742,10 @@ static void lib_relocate_do(Main *bmain,
}
#ifdef PRINT_DEBUG
- printf("after remap, old_id users: %d, new_id users: %d\n", old_id->us, new_id->us);
+ printf("after remap of %s, old_id users: %d, new_id users: %d\n",
+ old_id->name,
+ old_id->us,
+ new_id->us);
#endif
/* In some cases, new_id might become direct link, remove parent of library in this case. */
diff --git a/source/blender/windowmanager/intern/wm_gesture.c b/source/blender/windowmanager/intern/wm_gesture.c
index b12bb89ea9f..e117a1bcdfe 100644
--- a/source/blender/windowmanager/intern/wm_gesture.c
+++ b/source/blender/windowmanager/intern/wm_gesture.c
@@ -62,7 +62,7 @@ wmGesture *WM_gesture_new(bContext *C, const wmEvent *event, int type)
gesture->type = type;
gesture->event_type = event->type;
gesture->winrct = ar->winrct;
- gesture->userdata_free = true; /* Free if userdata is set. */
+ gesture->user_data.use_free = true; /* Free if userdata is set. */
gesture->modal_state = GESTURE_MODAL_NOP;
if (ELEM(type,
@@ -106,9 +106,7 @@ void WM_gesture_end(bContext *C, wmGesture *gesture)
}
BLI_remlink(&win->gesture, gesture);
MEM_freeN(gesture->customdata);
- if (gesture->userdata && gesture->userdata_free) {
- MEM_freeN(gesture->userdata);
- }
+ WM_generic_user_data_free(&gesture->user_data);
MEM_freeN(gesture);
}
diff --git a/source/blender/windowmanager/intern/wm_keymap_utils.c b/source/blender/windowmanager/intern/wm_keymap_utils.c
index 626e9e88845..4603f14729d 100644
--- a/source/blender/windowmanager/intern/wm_keymap_utils.c
+++ b/source/blender/windowmanager/intern/wm_keymap_utils.c
@@ -451,6 +451,46 @@ wmKeyMap *WM_keymap_guess_opname(const bContext *C, const char *opname)
return km;
}
+static bool wm_keymap_item_uses_modifier(wmKeyMapItem *kmi, const int event_modifier)
+{
+ if (kmi->ctrl != KM_ANY) {
+ if ((kmi->ctrl == KM_NOTHING) != ((event_modifier & KM_CTRL) == 0)) {
+ return false;
+ }
+ }
+
+ if (kmi->alt != KM_ANY) {
+ if ((kmi->alt == KM_NOTHING) != ((event_modifier & KM_ALT) == 0)) {
+ return false;
+ }
+ }
+
+ if (kmi->shift != KM_ANY) {
+ if ((kmi->shift == KM_NOTHING) != ((event_modifier & KM_SHIFT) == 0)) {
+ return false;
+ }
+ }
+
+ if (kmi->oskey != KM_ANY) {
+ if ((kmi->oskey == KM_NOTHING) != ((event_modifier & KM_OSKEY) == 0)) {
+ return false;
+ }
+ }
+ return true;
+}
+
+bool WM_keymap_uses_event_modifier(wmKeyMap *keymap, const int event_modifier)
+{
+ for (wmKeyMapItem *kmi = keymap->items.first; kmi; kmi = kmi->next) {
+ if ((kmi->flag & KMI_INACTIVE) == 0) {
+ if (wm_keymap_item_uses_modifier(kmi, event_modifier)) {
+ return true;
+ }
+ }
+ }
+ return false;
+}
+
void WM_keymap_fix_linking(void)
{
}
diff --git a/source/blender/windowmanager/intern/wm_operators.c b/source/blender/windowmanager/intern/wm_operators.c
index 0bb2fd58824..4a99c2de6e7 100644
--- a/source/blender/windowmanager/intern/wm_operators.c
+++ b/source/blender/windowmanager/intern/wm_operators.c
@@ -3085,8 +3085,7 @@ static void redraw_timer_step(bContext *C,
{
if (type == eRTDrawRegion) {
if (ar) {
- ED_region_do_draw(C, ar);
- ar->do_draw = false;
+ wm_draw_region_test(C, sa, ar);
}
}
else if (type == eRTDrawRegionSwap) {
@@ -3110,8 +3109,7 @@ static void redraw_timer_step(bContext *C,
for (ar_iter = sa_iter->regionbase.first; ar_iter; ar_iter = ar_iter->next) {
if (ar_iter->visible) {
CTX_wm_region_set(C, ar_iter);
- ED_region_do_draw(C, ar_iter);
- ar_iter->do_draw = false;
+ wm_draw_region_test(C, sa_iter, ar_iter);
}
}
}
@@ -3156,6 +3154,7 @@ static int redraw_timer_exec(bContext *C, wmOperator *op)
wmWindow *win = CTX_wm_window(C);
ScrArea *sa = CTX_wm_area(C);
ARegion *ar = CTX_wm_region(C);
+ wmWindowManager *wm = CTX_wm_manager(C);
double time_start, time_delta;
const int type = RNA_enum_get(op->ptr, "type");
const int iter = RNA_int_get(op->ptr, "iterations");
@@ -3169,6 +3168,8 @@ static int redraw_timer_exec(bContext *C, wmOperator *op)
time_start = PIL_check_seconds_timer();
+ wm_window_make_drawable(wm, win);
+
for (a = 0; a < iter; a++) {
redraw_timer_step(C, bmain, scene, depsgraph, win, sa, ar, type, cfra);
iter_steps += 1;
diff --git a/source/blender/windowmanager/intern/wm_toolsystem.c b/source/blender/windowmanager/intern/wm_toolsystem.c
index 92ef235722b..3ea58d8c4e5 100644
--- a/source/blender/windowmanager/intern/wm_toolsystem.c
+++ b/source/blender/windowmanager/intern/wm_toolsystem.c
@@ -726,7 +726,7 @@ static const char *toolsystem_default_tool(const bToolKey *tkey)
case SPACE_IMAGE:
switch (tkey->mode) {
case SI_MODE_PAINT:
- return "builtin_brush.draw";
+ return "builtin_brush.Draw";
}
break;
case SPACE_NODE: {
diff --git a/source/blender/windowmanager/intern/wm_utils.c b/source/blender/windowmanager/intern/wm_utils.c
new file mode 100644
index 00000000000..c0ee1ec44db
--- /dev/null
+++ b/source/blender/windowmanager/intern/wm_utils.c
@@ -0,0 +1,71 @@
+/*
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+/** \file
+ * \ingroup wm
+ *
+ * Generic helper utilies that aren't assosiated with a particular area.
+ */
+
+#include "WM_types.h"
+#include "WM_api.h"
+
+#include "MEM_guardedalloc.h"
+
+/* -------------------------------------------------------------------- */
+/** \name Generic Callback
+ * \{ */
+
+void WM_generic_callback_free(wmGenericCallback *callback)
+{
+ if (callback->free_user_data) {
+ callback->free_user_data(callback->user_data);
+ }
+ MEM_freeN(callback);
+}
+
+static void do_nothing(struct bContext *UNUSED(C), void *UNUSED(user_data))
+{
+}
+
+wmGenericCallback *WM_generic_callback_steal(wmGenericCallback *callback)
+{
+ wmGenericCallback *new_callback = MEM_dupallocN(callback);
+ callback->exec = do_nothing;
+ callback->free_user_data = NULL;
+ callback->user_data = NULL;
+ return new_callback;
+}
+
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Generic User Data
+ * \{ */
+
+void WM_generic_user_data_free(wmGenericUserData *wm_userdata)
+{
+ if (wm_userdata->data && wm_userdata->use_free) {
+ if (wm_userdata->free_fn) {
+ wm_userdata->free_fn(wm_userdata->data);
+ }
+ else {
+ MEM_freeN(wm_userdata->data);
+ }
+ }
+}
+
+/** \} */
diff --git a/source/blender/windowmanager/intern/wm_window.c b/source/blender/windowmanager/intern/wm_window.c
index 1ac23754972..7ae572e5685 100644
--- a/source/blender/windowmanager/intern/wm_window.c
+++ b/source/blender/windowmanager/intern/wm_window.c
@@ -368,7 +368,7 @@ static void wm_save_file_on_quit_dialog_callback(bContext *C, void *UNUSED(user_
*/
static void wm_confirm_quit(bContext *C)
{
- GenericCallback *action = MEM_callocN(sizeof(*action), __func__);
+ wmGenericCallback *action = MEM_callocN(sizeof(*action), __func__);
action->exec = wm_save_file_on_quit_dialog_callback;
wm_close_file_dialog(C, action);
}
diff --git a/source/blender/windowmanager/wm_draw.h b/source/blender/windowmanager/wm_draw.h
index ede2b3191b9..0a07eb998cf 100644
--- a/source/blender/windowmanager/wm_draw.h
+++ b/source/blender/windowmanager/wm_draw.h
@@ -38,6 +38,7 @@ typedef struct wmDrawBuffer {
} wmDrawBuffer;
struct ARegion;
+struct ScrArea;
struct bContext;
struct wmWindow;
@@ -45,6 +46,7 @@ struct wmWindow;
void wm_draw_update(struct bContext *C);
void wm_draw_region_clear(struct wmWindow *win, struct ARegion *ar);
void wm_draw_region_blend(struct ARegion *ar, int view, bool blend);
+void wm_draw_region_test(struct bContext *C, struct ScrArea *sa, struct ARegion *ar);
struct GPUTexture *wm_draw_region_texture(struct ARegion *ar, int view);
diff --git a/source/blender/windowmanager/wm_files.h b/source/blender/windowmanager/wm_files.h
index 8b3f1ead215..0aa4357a8f4 100644
--- a/source/blender/windowmanager/wm_files.h
+++ b/source/blender/windowmanager/wm_files.h
@@ -25,6 +25,7 @@
#define __WM_FILES_H__
struct Main;
+struct wmGenericCallback;
struct wmOperatorType;
/* wm_files.c */
@@ -40,15 +41,7 @@ void wm_homefile_read(struct bContext *C,
bool *r_is_factory_startup);
void wm_file_read_report(bContext *C, struct Main *bmain);
-typedef struct GenericCallback {
- void (*exec)(bContext *C, void *user_data);
- void *user_data;
- void (*free_user_data)(void *user_data);
-} GenericCallback;
-
-GenericCallback *wm_generic_callback_steal(GenericCallback *callback);
-void wm_generic_callback_free(GenericCallback *callback);
-void wm_close_file_dialog(bContext *C, GenericCallback *post_action);
+void wm_close_file_dialog(bContext *C, struct wmGenericCallback *post_action);
bool wm_file_or_image_is_modified(const struct bContext *C);
void WM_OT_save_homefile(struct wmOperatorType *ot);