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:
Diffstat (limited to 'source/blender')
-rw-r--r--source/blender/alembic/intern/abc_camera.cc16
-rw-r--r--source/blender/alembic/intern/abc_transform.cc2
-rw-r--r--source/blender/blenkernel/BKE_appdir.h4
-rw-r--r--source/blender/blenkernel/BKE_armature.h4
-rw-r--r--source/blender/blenkernel/BKE_blender_version.h2
-rw-r--r--source/blender/blenkernel/BKE_blendfile.h2
-rw-r--r--source/blender/blenkernel/BKE_camera.h2
-rw-r--r--source/blender/blenkernel/BKE_collection.h2
-rw-r--r--source/blender/blenkernel/BKE_context.h15
-rw-r--r--source/blender/blenkernel/BKE_curve.h18
-rw-r--r--source/blender/blenkernel/BKE_displist.h15
-rw-r--r--source/blender/blenkernel/BKE_editmesh.h1
-rw-r--r--source/blender/blenkernel/BKE_fcurve.h1
-rw-r--r--source/blender/blenkernel/BKE_global.h5
-rw-r--r--source/blender/blenkernel/BKE_idprop.h3
-rw-r--r--source/blender/blenkernel/BKE_image.h29
-rw-r--r--source/blender/blenkernel/BKE_mesh.h15
-rw-r--r--source/blender/blenkernel/BKE_object.h11
-rw-r--r--source/blender/blenkernel/BKE_pbvh.h41
-rw-r--r--source/blender/blenkernel/BKE_scene.h5
-rw-r--r--source/blender/blenkernel/BKE_screen.h4
-rw-r--r--source/blender/blenkernel/BKE_sequencer.h4
-rw-r--r--source/blender/blenkernel/BKE_workspace.h2
-rw-r--r--source/blender/blenkernel/BKE_writeavi.h3
-rw-r--r--source/blender/blenkernel/intern/action.c3
-rw-r--r--source/blender/blenkernel/intern/addon.c1
-rw-r--r--source/blender/blenkernel/intern/anim_sys.c28
-rw-r--r--source/blender/blenkernel/intern/appdir.c35
-rw-r--r--source/blender/blenkernel/intern/armature.c53
-rw-r--r--source/blender/blenkernel/intern/armature_update.c60
-rw-r--r--source/blender/blenkernel/intern/blender.c2
-rw-r--r--source/blender/blenkernel/intern/blender_user_menu.c1
-rw-r--r--source/blender/blenkernel/intern/blendfile.c122
-rw-r--r--source/blender/blenkernel/intern/bpath.c5
-rw-r--r--source/blender/blenkernel/intern/brush.c39
-rw-r--r--source/blender/blenkernel/intern/camera.c23
-rw-r--r--source/blender/blenkernel/intern/collection.c34
-rw-r--r--source/blender/blenkernel/intern/constraint.c34
-rw-r--r--source/blender/blenkernel/intern/context.c70
-rw-r--r--source/blender/blenkernel/intern/curve.c261
-rw-r--r--source/blender/blenkernel/intern/data_transfer.c2
-rw-r--r--source/blender/blenkernel/intern/deform.c2
-rw-r--r--source/blender/blenkernel/intern/displist.c230
-rw-r--r--source/blender/blenkernel/intern/dynamicpaint.c6
-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/fcurve.c15
-rw-r--r--source/blender/blenkernel/intern/fmodifier.c1
-rw-r--r--source/blender/blenkernel/intern/gpencil.c3
-rw-r--r--source/blender/blenkernel/intern/idprop.c37
-rw-r--r--source/blender/blenkernel/intern/image.c40
-rw-r--r--source/blender/blenkernel/intern/layer.c39
-rw-r--r--source/blender/blenkernel/intern/library.c4
-rw-r--r--source/blender/blenkernel/intern/library_override.c2
-rw-r--r--source/blender/blenkernel/intern/library_query.c2
-rw-r--r--source/blender/blenkernel/intern/library_remap.c2
-rw-r--r--source/blender/blenkernel/intern/light.c1
-rw-r--r--source/blender/blenkernel/intern/mask.c10
-rw-r--r--source/blender/blenkernel/intern/mesh_convert.c543
-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/node.c5
-rw-r--r--source/blender/blenkernel/intern/object.c33
-rw-r--r--source/blender/blenkernel/intern/object_dupli.c2
-rw-r--r--source/blender/blenkernel/intern/object_update.c6
-rw-r--r--source/blender/blenkernel/intern/paint.c13
-rw-r--r--source/blender/blenkernel/intern/particle.c7
-rw-r--r--source/blender/blenkernel/intern/particle_distribute.c4
-rw-r--r--source/blender/blenkernel/intern/particle_system.c10
-rw-r--r--source/blender/blenkernel/intern/pbvh.c64
-rw-r--r--source/blender/blenkernel/intern/scene.c23
-rw-r--r--source/blender/blenkernel/intern/screen.c16
-rw-r--r--source/blender/blenkernel/intern/seqcache.c21
-rw-r--r--source/blender/blenkernel/intern/sequencer.c17
-rw-r--r--source/blender/blenkernel/intern/tracking_stabilize.c4
-rw-r--r--source/blender/blenkernel/intern/undo_system.c6
-rw-r--r--source/blender/blenkernel/intern/unit.c2
-rw-r--r--source/blender/blenkernel/intern/workspace.c52
-rw-r--r--source/blender/blenkernel/intern/writeavi.c1
-rw-r--r--source/blender/blenkernel/intern/writeffmpeg.c4
-rw-r--r--source/blender/blenlib/BLI_callbacks.h1
-rw-r--r--source/blender/blenlib/BLI_math_matrix.h5
-rw-r--r--source/blender/blenlib/BLI_memblock.h60
-rw-r--r--source/blender/blenlib/BLI_rand.h8
-rw-r--r--source/blender/blenlib/BLI_rect.h4
-rw-r--r--source/blender/blenlib/BLI_system.h4
-rw-r--r--source/blender/blenlib/CMakeLists.txt2
-rw-r--r--source/blender/blenlib/intern/BLI_memarena.c4
-rw-r--r--source/blender/blenlib/intern/BLI_memblock.c182
-rw-r--r--source/blender/blenlib/intern/BLI_memiter.c4
-rw-r--r--source/blender/blenlib/intern/expr_pylike_eval.c6
-rw-r--r--source/blender/blenlib/intern/math_matrix.c127
-rw-r--r--source/blender/blenlib/intern/rct.c19
-rw-r--r--source/blender/blenlib/intern/system.c19
-rw-r--r--source/blender/blenloader/intern/readfile.c113
-rw-r--r--source/blender/blenloader/intern/versioning_250.c12
-rw-r--r--source/blender/blenloader/intern/versioning_260.c1
-rw-r--r--source/blender/blenloader/intern/versioning_280.c184
-rw-r--r--source/blender/blenloader/intern/versioning_cycles.c204
-rw-r--r--source/blender/blenloader/intern/versioning_defaults.c80
-rw-r--r--source/blender/blenloader/intern/versioning_userdef.c76
-rw-r--r--source/blender/blenloader/intern/writefile.c2
-rw-r--r--source/blender/bmesh/intern/bmesh_mesh.c4
-rw-r--r--source/blender/bmesh/intern/bmesh_operators.h7
-rw-r--r--source/blender/bmesh/tools/bmesh_bevel.c9
-rw-r--r--source/blender/collada/AnimationExporter.cpp4
-rw-r--r--source/blender/collada/CameraExporter.cpp2
-rw-r--r--source/blender/collada/DocumentImporter.cpp2
-rw-r--r--source/blender/collada/EffectExporter.cpp11
-rw-r--r--source/blender/collada/GeometryExporter.cpp10
-rw-r--r--source/blender/collada/ImageExporter.cpp2
-rw-r--r--source/blender/collada/collada_utils.cpp13
-rw-r--r--source/blender/collada/collada_utils.h2
-rw-r--r--source/blender/compositor/operations/COM_GlareFogGlowOperation.cpp2
-rw-r--r--source/blender/depsgraph/CMakeLists.txt1
-rw-r--r--source/blender/depsgraph/DEG_depsgraph_debug.h2
-rw-r--r--source/blender/depsgraph/DEG_depsgraph_query.h56
-rw-r--r--source/blender/depsgraph/intern/builder/deg_builder.cc7
-rw-r--r--source/blender/depsgraph/intern/builder/deg_builder.h2
-rw-r--r--source/blender/depsgraph/intern/builder/deg_builder_nodes.cc26
-rw-r--r--source/blender/depsgraph/intern/builder/deg_builder_nodes.h2
-rw-r--r--source/blender/depsgraph/intern/builder/deg_builder_nodes_view_layer.cc4
-rw-r--r--source/blender/depsgraph/intern/builder/deg_builder_relations.cc98
-rw-r--r--source/blender/depsgraph/intern/builder/deg_builder_relations.h2
-rw-r--r--source/blender/depsgraph/intern/builder/deg_builder_relations_rig.cc8
-rw-r--r--source/blender/depsgraph/intern/builder/deg_builder_relations_view_layer.cc2
-rw-r--r--source/blender/depsgraph/intern/builder/deg_builder_rna.cc35
-rw-r--r--source/blender/depsgraph/intern/debug/deg_debug_relations_graphviz.cc1
-rw-r--r--source/blender/depsgraph/intern/depsgraph_query.cc40
-rw-r--r--source/blender/depsgraph/intern/depsgraph_query_filter.cc243
-rw-r--r--source/blender/depsgraph/intern/depsgraph_query_iter.cc8
-rw-r--r--source/blender/depsgraph/intern/depsgraph_tag.cc21
-rw-r--r--source/blender/depsgraph/intern/eval/deg_eval_copy_on_write.cc4
-rw-r--r--source/blender/depsgraph/intern/node/deg_node.cc5
-rw-r--r--source/blender/depsgraph/intern/node/deg_node.h2
-rw-r--r--source/blender/depsgraph/intern/node/deg_node_component.cc3
-rw-r--r--source/blender/depsgraph/intern/node/deg_node_component.h1
-rw-r--r--source/blender/depsgraph/intern/node/deg_node_operation.cc2
-rw-r--r--source/blender/depsgraph/intern/node/deg_node_operation.h1
-rw-r--r--source/blender/draw/CMakeLists.txt1
-rw-r--r--source/blender/draw/DRW_engine.h11
-rw-r--r--source/blender/draw/engines/basic/basic_engine.c14
-rw-r--r--source/blender/draw/engines/eevee/eevee_bloom.c2
-rw-r--r--source/blender/draw/engines/eevee/eevee_data.c1
-rw-r--r--source/blender/draw/engines/eevee/eevee_depth_of_field.c182
-rw-r--r--source/blender/draw/engines/eevee/eevee_effects.c120
-rw-r--r--source/blender/draw/engines/eevee/eevee_engine.c63
-rw-r--r--source/blender/draw/engines/eevee/eevee_lightcache.c21
-rw-r--r--source/blender/draw/engines/eevee/eevee_lightprobes.c231
-rw-r--r--source/blender/draw/engines/eevee/eevee_lights.c148
-rw-r--r--source/blender/draw/engines/eevee/eevee_lookdev.c70
-rw-r--r--source/blender/draw/engines/eevee/eevee_materials.c382
-rw-r--r--source/blender/draw/engines/eevee/eevee_mist.c4
-rw-r--r--source/blender/draw/engines/eevee/eevee_motion_blur.c6
-rw-r--r--source/blender/draw/engines/eevee/eevee_occlusion.c27
-rw-r--r--source/blender/draw/engines/eevee/eevee_private.h87
-rw-r--r--source/blender/draw/engines/eevee/eevee_render.c74
-rw-r--r--source/blender/draw/engines/eevee/eevee_screen_raytrace.c10
-rw-r--r--source/blender/draw/engines/eevee/eevee_shaders.c15
-rw-r--r--source/blender/draw/engines/eevee/eevee_subsurface.c86
-rw-r--r--source/blender/draw/engines/eevee/eevee_temporal_sampling.c102
-rw-r--r--source/blender/draw/engines/eevee/eevee_volumes.c651
-rw-r--r--source/blender/draw/engines/eevee/shaders/bsdf_common_lib.glsl22
-rw-r--r--source/blender/draw/engines/eevee/shaders/default_world_frag.glsl3
-rw-r--r--source/blender/draw/engines/eevee/shaders/lightprobe_planar_downsample_vert.glsl9
-rw-r--r--source/blender/draw/engines/eevee/shaders/lit_surface_frag.glsl5
-rw-r--r--source/blender/draw/engines/eevee/shaders/lit_surface_vert.glsl43
-rw-r--r--source/blender/draw/engines/eevee/shaders/prepass_vert.glsl33
-rw-r--r--source/blender/draw/engines/eevee/shaders/shadow_vert.glsl30
-rw-r--r--source/blender/draw/engines/eevee/shaders/volumetric_frag.glsl5
-rw-r--r--source/blender/draw/engines/external/external_engine.c21
-rw-r--r--source/blender/draw/engines/gpencil/gpencil_draw_cache_impl.c43
-rw-r--r--source/blender/draw/engines/gpencil/gpencil_draw_utils.c100
-rw-r--r--source/blender/draw/engines/gpencil/gpencil_engine.c48
-rw-r--r--source/blender/draw/engines/gpencil/gpencil_engine.h15
-rw-r--r--source/blender/draw/engines/gpencil/gpencil_render.c39
-rw-r--r--source/blender/draw/engines/gpencil/gpencil_shader_fx.c47
-rw-r--r--source/blender/draw/engines/gpencil/shaders/gpencil_edit_point_geom.glsl1
-rw-r--r--source/blender/draw/engines/gpencil/shaders/gpencil_edit_point_vert.glsl3
-rw-r--r--source/blender/draw/engines/gpencil/shaders/gpencil_fill_frag.glsl25
-rw-r--r--source/blender/draw/engines/gpencil/shaders/gpencil_fill_vert.glsl4
-rw-r--r--source/blender/draw/engines/gpencil/shaders/gpencil_paper_frag.glsl2
-rw-r--r--source/blender/draw/engines/gpencil/shaders/gpencil_point_frag.glsl27
-rw-r--r--source/blender/draw/engines/gpencil/shaders/gpencil_point_geom.glsl8
-rw-r--r--source/blender/draw/engines/gpencil/shaders/gpencil_point_vert.glsl6
-rw-r--r--source/blender/draw/engines/gpencil/shaders/gpencil_stroke_frag.glsl25
-rw-r--r--source/blender/draw/engines/gpencil/shaders/gpencil_stroke_geom.glsl1
-rw-r--r--source/blender/draw/engines/gpencil/shaders/gpencil_stroke_vert.glsl4
-rw-r--r--source/blender/draw/engines/workbench/shaders/workbench_common_lib.glsl30
-rw-r--r--source/blender/draw/engines/workbench/shaders/workbench_deferred_composite_frag.glsl3
-rw-r--r--source/blender/draw/engines/workbench/shaders/workbench_effect_fxaa_frag.glsl3
-rw-r--r--source/blender/draw/engines/workbench/shaders/workbench_forward_transparent_accum_frag.glsl5
-rw-r--r--source/blender/draw/engines/workbench/shaders/workbench_prepass_frag.glsl3
-rw-r--r--source/blender/draw/engines/workbench/shaders/workbench_prepass_vert.glsl40
-rw-r--r--source/blender/draw/engines/workbench/shaders/workbench_shadow_vert.glsl6
-rw-r--r--source/blender/draw/engines/workbench/shaders/workbench_volume_frag.glsl12
-rw-r--r--source/blender/draw/engines/workbench/shaders/workbench_volume_vert.glsl3
-rw-r--r--source/blender/draw/engines/workbench/solid_mode.c8
-rw-r--r--source/blender/draw/engines/workbench/transparent_mode.c8
-rw-r--r--source/blender/draw/engines/workbench/workbench_data.c10
-rw-r--r--source/blender/draw/engines/workbench/workbench_deferred.c150
-rw-r--r--source/blender/draw/engines/workbench/workbench_effect_aa.c9
-rw-r--r--source/blender/draw/engines/workbench/workbench_effect_dof.c41
-rw-r--r--source/blender/draw/engines/workbench/workbench_effect_fxaa.c2
-rw-r--r--source/blender/draw/engines/workbench/workbench_effect_taa.c96
-rw-r--r--source/blender/draw/engines/workbench/workbench_forward.c143
-rw-r--r--source/blender/draw/engines/workbench/workbench_materials.c9
-rw-r--r--source/blender/draw/engines/workbench/workbench_private.h62
-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.c14
-rw-r--r--source/blender/draw/intern/DRW_render.h316
-rw-r--r--source/blender/draw/intern/draw_anim_viz.c6
-rw-r--r--source/blender/draw/intern/draw_armature.c222
-rw-r--r--source/blender/draw/intern/draw_cache.c139
-rw-r--r--source/blender/draw/intern/draw_cache_impl.h32
-rw-r--r--source/blender/draw/intern/draw_cache_impl_curve.c8
-rw-r--r--source/blender/draw/intern/draw_cache_impl_displist.c3
-rw-r--r--source/blender/draw/intern/draw_cache_impl_lattice.c6
-rw-r--r--source/blender/draw/intern/draw_cache_impl_mesh.c357
-rw-r--r--source/blender/draw/intern/draw_cache_impl_metaball.c6
-rw-r--r--source/blender/draw/intern/draw_cache_inline.h110
-rw-r--r--source/blender/draw/intern/draw_common.c375
-rw-r--r--source/blender/draw/intern/draw_common.h120
-rw-r--r--source/blender/draw/intern/draw_hair.c8
-rw-r--r--source/blender/draw/intern/draw_instance_data.c343
-rw-r--r--source/blender/draw/intern/draw_instance_data.h23
-rw-r--r--source/blender/draw/intern/draw_manager.c573
-rw-r--r--source/blender/draw/intern/draw_manager.h232
-rw-r--r--source/blender/draw/intern/draw_manager_data.c1340
-rw-r--r--source/blender/draw/intern/draw_manager_exec.c866
-rw-r--r--source/blender/draw/intern/draw_manager_shader.c2
-rw-r--r--source/blender/draw/modes/edit_armature_mode.c2
-rw-r--r--source/blender/draw/modes/edit_curve_mode.c46
-rw-r--r--source/blender/draw/modes/edit_lattice_mode.c16
-rw-r--r--source/blender/draw/modes/edit_mesh_mode.c67
-rw-r--r--source/blender/draw/modes/edit_metaball_mode.c32
-rw-r--r--source/blender/draw/modes/edit_text_mode.c39
-rw-r--r--source/blender/draw/modes/object_mode.c1190
-rw-r--r--source/blender/draw/modes/overlay_mode.c63
-rw-r--r--source/blender/draw/modes/paint_texture_mode.c272
-rw-r--r--source/blender/draw/modes/paint_vertex_mode.c26
-rw-r--r--source/blender/draw/modes/particle_mode.c30
-rw-r--r--source/blender/draw/modes/pose_mode.c6
-rw-r--r--source/blender/draw/modes/sculpt_mode.c118
-rw-r--r--source/blender/draw/modes/shaders/armature_axes_vert.glsl6
-rw-r--r--source/blender/draw/modes/shaders/armature_envelope_outline_vert.glsl5
-rw-r--r--source/blender/draw/modes/shaders/armature_envelope_solid_vert.glsl5
-rw-r--r--source/blender/draw/modes/shaders/armature_shape_outline_geom.glsl1
-rw-r--r--source/blender/draw/modes/shaders/armature_shape_outline_vert.glsl13
-rw-r--r--source/blender/draw/modes/shaders/armature_shape_solid_vert.glsl13
-rw-r--r--source/blender/draw/modes/shaders/armature_stick_vert.glsl5
-rw-r--r--source/blender/draw/modes/shaders/common_fullscreen_vert.glsl9
-rw-r--r--source/blender/draw/modes/shaders/common_hair_lib.glsl4
-rw-r--r--source/blender/draw/modes/shaders/common_view_lib.glsl48
-rw-r--r--source/blender/draw/modes/shaders/edit_curve_overlay_handle_vert.glsl10
-rw-r--r--source/blender/draw/modes/shaders/edit_curve_overlay_loosevert_vert.glsl11
-rw-r--r--source/blender/draw/modes/shaders/edit_curve_overlay_normals_vert.glsl11
-rw-r--r--source/blender/draw/modes/shaders/edit_lattice_overlay_loosevert_vert.glsl10
-rw-r--r--source/blender/draw/modes/shaders/edit_mesh_overlay_facefill_vert.glsl9
-rw-r--r--source/blender/draw/modes/shaders/edit_mesh_overlay_mesh_analysis_vert.glsl9
-rw-r--r--source/blender/draw/modes/shaders/edit_mesh_overlay_vert.glsl23
-rw-r--r--source/blender/draw/modes/shaders/edit_normals_vert.glsl18
-rw-r--r--source/blender/draw/modes/shaders/object_empty_axes_vert.glsl5
-rw-r--r--source/blender/draw/modes/shaders/object_empty_image_frag.glsl23
-rw-r--r--source/blender/draw/modes/shaders/object_empty_image_vert.glsl13
-rw-r--r--source/blender/draw/modes/shaders/object_grid_frag.glsl7
-rw-r--r--source/blender/draw/modes/shaders/object_grid_vert.glsl5
-rw-r--r--source/blender/draw/modes/shaders/object_mball_handles_vert.glsl3
-rw-r--r--source/blender/draw/modes/shaders/object_outline_prepass_geom.glsl2
-rw-r--r--source/blender/draw/modes/shaders/object_outline_prepass_vert.glsl11
-rw-r--r--source/blender/draw/modes/shaders/object_particle_dot_vert.glsl13
-rw-r--r--source/blender/draw/modes/shaders/object_particle_prim_vert.glsl21
-rw-r--r--source/blender/draw/modes/shaders/overlay_face_orientation_vert.glsl7
-rw-r--r--source/blender/draw/modes/shaders/overlay_face_wireframe_vert.glsl49
-rw-r--r--source/blender/draw/modes/shaders/paint_face_vert.glsl9
-rw-r--r--source/blender/draw/modes/shaders/paint_texture_frag.glsl23
-rw-r--r--source/blender/draw/modes/shaders/paint_texture_vert.glsl8
-rw-r--r--source/blender/draw/modes/shaders/paint_vertex_vert.glsl8
-rw-r--r--source/blender/draw/modes/shaders/paint_weight_vert.glsl8
-rw-r--r--source/blender/draw/modes/shaders/paint_wire_vert.glsl8
-rw-r--r--source/blender/draw/modes/shaders/particle_strand_frag.glsl1
-rw-r--r--source/blender/draw/modes/shaders/particle_strand_vert.glsl5
-rw-r--r--source/blender/draw/modes/shaders/sculpt_mask_vert.glsl4
-rw-r--r--source/blender/draw/modes/shaders/volume_velocity_vert.glsl5
-rw-r--r--source/blender/editors/animation/CMakeLists.txt1
-rw-r--r--source/blender/editors/animation/anim_channels_defines.c10
-rw-r--r--source/blender/editors/animation/anim_channels_edit.c51
-rw-r--r--source/blender/editors/animation/anim_filter.c4
-rw-r--r--source/blender/editors/animation/anim_markers.c4
-rw-r--r--source/blender/editors/animation/drivers.c3
-rw-r--r--source/blender/editors/animation/keyframes_general.c3
-rw-r--r--source/blender/editors/animation/keyframing.c11
-rw-r--r--source/blender/editors/animation/time_scrub_ui.c214
-rw-r--r--source/blender/editors/armature/armature_intern.h2
-rw-r--r--source/blender/editors/armature/armature_naming.c10
-rw-r--r--source/blender/editors/armature/armature_ops.c2
-rw-r--r--source/blender/editors/armature/armature_relations.c37
-rw-r--r--source/blender/editors/armature/armature_select.c8
-rw-r--r--source/blender/editors/armature/armature_utils.c6
-rw-r--r--source/blender/editors/armature/pose_edit.c34
-rw-r--r--source/blender/editors/armature/pose_lib.c1
-rw-r--r--source/blender/editors/armature/pose_slide.c255
-rw-r--r--source/blender/editors/armature/pose_transform.c338
-rw-r--r--source/blender/editors/armature/pose_utils.c1
-rw-r--r--source/blender/editors/curve/editcurve.c405
-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_edit.c2
-rw-r--r--source/blender/editors/gpencil/gpencil_fill.c3
-rw-r--r--source/blender/editors/gpencil/gpencil_merge.c2
-rw-r--r--source/blender/editors/gpencil/gpencil_paint.c2
-rw-r--r--source/blender/editors/gpencil/gpencil_primitive.c2
-rw-r--r--source/blender/editors/gpencil/gpencil_utils.c2
-rw-r--r--source/blender/editors/include/ED_anim_api.h15
-rw-r--r--source/blender/editors/include/ED_image.h5
-rw-r--r--source/blender/editors/include/ED_mesh.h52
-rw-r--r--source/blender/editors/include/ED_screen.h17
-rw-r--r--source/blender/editors/include/ED_select_buffer_utils.h43
-rw-r--r--source/blender/editors/include/ED_time_scrub_ui.h43
-rw-r--r--source/blender/editors/include/ED_view3d.h24
-rw-r--r--source/blender/editors/include/UI_icons.h116
-rw-r--r--source/blender/editors/include/UI_interface.h49
-rw-r--r--source/blender/editors/include/UI_interface_icons.h25
-rw-r--r--source/blender/editors/include/UI_resources.h10
-rw-r--r--source/blender/editors/include/UI_view2d.h50
-rw-r--r--source/blender/editors/interface/interface.c39
-rw-r--r--source/blender/editors/interface/interface_anim.c5
-rw-r--r--source/blender/editors/interface/interface_context_menu.c159
-rw-r--r--source/blender/editors/interface/interface_eyedropper_datablock.c2
-rw-r--r--source/blender/editors/interface/interface_handlers.c42
-rw-r--r--source/blender/editors/interface/interface_icons.c549
-rw-r--r--source/blender/editors/interface/interface_intern.h7
-rw-r--r--source/blender/editors/interface/interface_layout.c145
-rw-r--r--source/blender/editors/interface/interface_panel.c244
-rw-r--r--source/blender/editors/interface/interface_region_menu_pie.c2
-rw-r--r--source/blender/editors/interface/interface_region_menu_popup.c25
-rw-r--r--source/blender/editors/interface/interface_region_popover.c10
-rw-r--r--source/blender/editors/interface/interface_region_popup.c8
-rw-r--r--source/blender/editors/interface/interface_region_tooltip.c4
-rw-r--r--source/blender/editors/interface/interface_templates.c46
-rw-r--r--source/blender/editors/interface/interface_widgets.c54
-rw-r--r--source/blender/editors/interface/resources.c42
-rw-r--r--source/blender/editors/interface/view2d.c164
-rw-r--r--source/blender/editors/interface/view2d_draw.c72
-rw-r--r--source/blender/editors/interface/view2d_ops.c4
-rw-r--r--source/blender/editors/io/io_cache.c2
-rw-r--r--source/blender/editors/mask/mask_ops.c8
-rw-r--r--source/blender/editors/mesh/CMakeLists.txt1
-rw-r--r--source/blender/editors/mesh/editface.c68
-rw-r--r--source/blender/editors/mesh/editmesh_add_gizmo.c3
-rw-r--r--source/blender/editors/mesh/editmesh_bevel.c3
-rw-r--r--source/blender/editors/mesh/editmesh_bisect.c6
-rw-r--r--source/blender/editors/mesh/editmesh_extrude.c4
-rw-r--r--source/blender/editors/mesh/editmesh_knife.c6
-rw-r--r--source/blender/editors/mesh/editmesh_loopcut.c69
-rw-r--r--source/blender/editors/mesh/editmesh_path.c83
-rw-r--r--source/blender/editors/mesh/editmesh_select.c648
-rw-r--r--source/blender/editors/mesh/editmesh_tools.c47
-rw-r--r--source/blender/editors/mesh/mesh_ops.c6
-rw-r--r--source/blender/editors/mesh/meshtools.c17
-rw-r--r--source/blender/editors/metaball/mball_edit.c2
-rw-r--r--source/blender/editors/object/object_add.c217
-rw-r--r--source/blender/editors/object/object_bake_api.c26
-rw-r--r--source/blender/editors/object/object_constraint.c45
-rw-r--r--source/blender/editors/object/object_edit.c5
-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/physics/dynamicpaint_ops.c34
-rw-r--r--source/blender/editors/render/render_internal.c49
-rw-r--r--source/blender/editors/render/render_opengl.c36
-rw-r--r--source/blender/editors/render/render_preview.c21
-rw-r--r--source/blender/editors/render/render_shading.c6
-rw-r--r--source/blender/editors/render/render_update.c7
-rw-r--r--source/blender/editors/screen/area.c179
-rw-r--r--source/blender/editors/screen/screen_context.c59
-rw-r--r--source/blender/editors/screen/screen_edit.c18
-rw-r--r--source/blender/editors/screen/screen_ops.c205
-rw-r--r--source/blender/editors/screen/workspace_edit.c16
-rw-r--r--source/blender/editors/sculpt_paint/paint_image.c3
-rw-r--r--source/blender/editors/sculpt_paint/paint_image_proj.c21
-rw-r--r--source/blender/editors/sculpt_paint/paint_image_undo.c2
-rw-r--r--source/blender/editors/sculpt_paint/paint_utils.c4
-rw-r--r--source/blender/editors/sculpt_paint/paint_vertex_weight_ops.c20
-rw-r--r--source/blender/editors/sculpt_paint/sculpt_uv.c2
-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/action_draw.c139
-rw-r--r--source/blender/editors/space_action/action_edit.c15
-rw-r--r--source/blender/editors/space_action/action_select.c25
-rw-r--r--source/blender/editors/space_action/space_action.c26
-rw-r--r--source/blender/editors/space_buttons/buttons_context.c4
-rw-r--r--source/blender/editors/space_buttons/buttons_ops.c5
-rw-r--r--source/blender/editors/space_buttons/space_buttons.c108
-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.c8
-rw-r--r--source/blender/editors/space_clip/space_clip.c48
-rw-r--r--source/blender/editors/space_clip/tracking_ops.c8
-rw-r--r--source/blender/editors/space_file/file_draw.c2
-rw-r--r--source/blender/editors/space_file/file_ops.c5
-rw-r--r--source/blender/editors/space_file/fsmenu.c161
-rw-r--r--source/blender/editors/space_file/fsmenu.h2
-rw-r--r--source/blender/editors/space_file/space_file.c12
-rw-r--r--source/blender/editors/space_graph/graph_draw.c48
-rw-r--r--source/blender/editors/space_graph/graph_edit.c16
-rw-r--r--source/blender/editors/space_graph/graph_select.c2
-rw-r--r--source/blender/editors/space_graph/space_graph.c45
-rw-r--r--source/blender/editors/space_image/image_buttons.c560
-rw-r--r--source/blender/editors/space_image/image_intern.h1
-rw-r--r--source/blender/editors/space_image/image_ops.c619
-rw-r--r--source/blender/editors/space_image/space_image.c20
-rw-r--r--source/blender/editors/space_info/info_ops.c12
-rw-r--r--source/blender/editors/space_nla/nla_channels.c15
-rw-r--r--source/blender/editors/space_nla/nla_draw.c96
-rw-r--r--source/blender/editors/space_nla/nla_edit.c14
-rw-r--r--source/blender/editors/space_nla/nla_select.c12
-rw-r--r--source/blender/editors/space_nla/space_nla.c24
-rw-r--r--source/blender/editors/space_node/drawnode.c17
-rw-r--r--source/blender/editors/space_node/node_add.c2
-rw-r--r--source/blender/editors/space_node/node_edit.c9
-rw-r--r--source/blender/editors/space_node/node_select.c198
-rw-r--r--source/blender/editors/space_node/space_node.c3
-rw-r--r--source/blender/editors/space_outliner/outliner_collections.c24
-rw-r--r--source/blender/editors/space_outliner/outliner_draw.c1653
-rw-r--r--source/blender/editors/space_outliner/outliner_edit.c9
-rw-r--r--source/blender/editors/space_outliner/outliner_intern.h9
-rw-r--r--source/blender/editors/space_outliner/outliner_select.c31
-rw-r--r--source/blender/editors/space_outliner/outliner_tree.c12
-rw-r--r--source/blender/editors/space_outliner/outliner_utils.c39
-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.c45
-rw-r--r--source/blender/editors/space_sequencer/sequencer_edit.c2
-rw-r--r--source/blender/editors/space_sequencer/sequencer_view.c2
-rw-r--r--source/blender/editors/space_sequencer/space_sequencer.c9
-rw-r--r--source/blender/editors/space_text/text_autocomplete.c6
-rw-r--r--source/blender/editors/space_text/text_draw.c8
-rw-r--r--source/blender/editors/space_text/text_ops.c8
-rw-r--r--source/blender/editors/space_topbar/space_topbar.c7
-rw-r--r--source/blender/editors/space_userpref/space_userpref.c2
-rw-r--r--source/blender/editors/space_userpref/userpref_ops.c2
-rw-r--r--source/blender/editors/space_view3d/drawobject.c231
-rw-r--r--source/blender/editors/space_view3d/space_view3d.c114
-rw-r--r--source/blender/editors/space_view3d/view3d_draw.c174
-rw-r--r--source/blender/editors/space_view3d/view3d_draw_legacy.c161
-rw-r--r--source/blender/editors/space_view3d/view3d_gizmo_camera.c6
-rw-r--r--source/blender/editors/space_view3d/view3d_gizmo_preselect_type.c17
-rw-r--r--source/blender/editors/space_view3d/view3d_intern.h7
-rw-r--r--source/blender/editors/space_view3d/view3d_select.c608
-rw-r--r--source/blender/editors/space_view3d/view3d_utils.c15
-rw-r--r--source/blender/editors/space_view3d/view3d_view.c2
-rw-r--r--source/blender/editors/transform/transform.c4
-rw-r--r--source/blender/editors/transform/transform.h33
-rw-r--r--source/blender/editors/transform/transform_conversions.c183
-rw-r--r--source/blender/editors/transform/transform_generics.c81
-rw-r--r--source/blender/editors/transform/transform_gizmo_3d.c11
-rw-r--r--source/blender/editors/transform/transform_ops.c2
-rw-r--r--source/blender/editors/transform/transform_orientations.c2
-rw-r--r--source/blender/editors/undo/ed_undo.c36
-rw-r--r--source/blender/editors/util/CMakeLists.txt3
-rw-r--r--source/blender/editors/util/select_buffer_utils.c303
-rw-r--r--source/blender/editors/uvedit/uvedit_draw.c8
-rw-r--r--source/blender/editors/uvedit/uvedit_unwrap_ops.c4
-rw-r--r--source/blender/freestyle/intern/blender_interface/BlenderFileLoader.cpp8
-rw-r--r--source/blender/freestyle/intern/blender_interface/BlenderStrokeRenderer.cpp8
-rw-r--r--source/blender/freestyle/intern/geometry/Noise.cpp18
-rw-r--r--source/blender/freestyle/intern/system/RandGen.cpp3
-rw-r--r--source/blender/gpu/CMakeLists.txt9
-rw-r--r--source/blender/gpu/GPU_batch.h7
-rw-r--r--source/blender/gpu/GPU_buffers.h7
-rw-r--r--source/blender/gpu/GPU_draw.h8
-rw-r--r--source/blender/gpu/GPU_material.h7
-rw-r--r--source/blender/gpu/GPU_matrix.h5
-rw-r--r--source/blender/gpu/GPU_shader.h9
-rw-r--r--source/blender/gpu/GPU_shader_interface.h8
-rw-r--r--source/blender/gpu/GPU_texture.h5
-rw-r--r--source/blender/gpu/GPU_vertex_buffer.h16
-rw-r--r--source/blender/gpu/GPU_vertex_format.h62
-rw-r--r--source/blender/gpu/GPU_viewport.h16
-rw-r--r--source/blender/gpu/intern/gpu_attr_binding.c3
-rw-r--r--source/blender/gpu/intern/gpu_batch.c133
-rw-r--r--source/blender/gpu/intern/gpu_buffers.c93
-rw-r--r--source/blender/gpu/intern/gpu_codegen.c95
-rw-r--r--source/blender/gpu/intern/gpu_codegen.h2
-rw-r--r--source/blender/gpu/intern/gpu_draw.c495
-rw-r--r--source/blender/gpu/intern/gpu_material.c35
-rw-r--r--source/blender/gpu/intern/gpu_matrix.c32
-rw-r--r--source/blender/gpu/intern/gpu_select.c12
-rw-r--r--source/blender/gpu/intern/gpu_select_sample_query.c7
-rw-r--r--source/blender/gpu/intern/gpu_shader.c119
-rw-r--r--source/blender/gpu/intern/gpu_shader_interface.c4
-rw-r--r--source/blender/gpu/intern/gpu_texture.c4
-rw-r--r--source/blender/gpu/intern/gpu_vertex_buffer.c11
-rw-r--r--source/blender/gpu/intern/gpu_vertex_format.c90
-rw-r--r--source/blender/gpu/intern/gpu_viewport.c104
-rw-r--r--source/blender/gpu/shaders/gpu_shader_edges_front_back_ortho_vert.glsl54
-rw-r--r--source/blender/gpu/shaders/gpu_shader_edges_front_back_persp_geom.glsl60
-rw-r--r--source/blender/gpu/shaders/gpu_shader_edges_front_back_persp_legacy_vert.glsl68
-rw-r--r--source/blender/gpu/shaders/gpu_shader_edges_front_back_persp_vert.glsl44
-rw-r--r--source/blender/gpu/shaders/gpu_shader_edges_overlay_frag.glsl21
-rw-r--r--source/blender/gpu/shaders/gpu_shader_edges_overlay_geom.glsl72
-rw-r--r--source/blender/gpu/shaders/gpu_shader_edges_overlay_simple_geom.glsl56
-rw-r--r--source/blender/gpu/shaders/gpu_shader_edges_overlay_vert.glsl14
-rw-r--r--source/blender/gpu/shaders/gpu_shader_instance_edges_variying_color_vert.glsl14
-rw-r--r--source/blender/gpu/shaders/gpu_shader_instance_objectspace_variying_color_vert.glsl13
-rw-r--r--source/blender/gpu/shaders/gpu_shader_material.glsl142
-rw-r--r--source/blender/imbuf/IMB_colormanagement.h14
-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/IMB_colormanagement_intern.h7
-rw-r--r--source/blender/imbuf/intern/cache.c4
-rw-r--r--source/blender/imbuf/intern/colormanagement.c154
-rw-r--r--source/blender/imbuf/intern/divers.c137
-rw-r--r--source/blender/imbuf/intern/metadata.c1
-rw-r--r--source/blender/imbuf/intern/radiance_hdr.c2
-rw-r--r--source/blender/imbuf/intern/readimage.c18
-rw-r--r--source/blender/makesdna/DNA_ID.h4
-rw-r--r--source/blender/makesdna/DNA_action_types.h6
-rw-r--r--source/blender/makesdna/DNA_anim_types.h3
-rw-r--r--source/blender/makesdna/DNA_armature_types.h10
-rw-r--r--source/blender/makesdna/DNA_camera_types.h25
-rw-r--r--source/blender/makesdna/DNA_collection_types.h4
-rw-r--r--source/blender/makesdna/DNA_constraint_types.h25
-rw-r--r--source/blender/makesdna/DNA_genfile.h11
-rw-r--r--source/blender/makesdna/DNA_gpencil_types.h3
-rw-r--r--source/blender/makesdna/DNA_image_types.h42
-rw-r--r--source/blender/makesdna/DNA_layer_types.h2
-rw-r--r--source/blender/makesdna/DNA_light_types.h3
-rw-r--r--source/blender/makesdna/DNA_material_types.h13
-rw-r--r--source/blender/makesdna/DNA_mesh_types.h10
-rw-r--r--source/blender/makesdna/DNA_node_types.h8
-rw-r--r--source/blender/makesdna/DNA_object_types.h17
-rw-r--r--source/blender/makesdna/DNA_scene_types.h82
-rw-r--r--source/blender/makesdna/DNA_screen_types.h44
-rw-r--r--source/blender/makesdna/DNA_sdna_types.h13
-rw-r--r--source/blender/makesdna/DNA_space_types.h15
-rw-r--r--source/blender/makesdna/DNA_userdef_types.h56
-rw-r--r--source/blender/makesdna/DNA_view2d_types.h8
-rw-r--r--source/blender/makesdna/DNA_view3d_types.h5
-rw-r--r--source/blender/makesdna/intern/dna_genfile.c262
-rw-r--r--source/blender/makesdna/intern/dna_rename_defs.h9
-rw-r--r--source/blender/makesdna/intern/makesdna.c125
-rw-r--r--source/blender/makesrna/RNA_access.h11
-rw-r--r--source/blender/makesrna/RNA_define.h1
-rw-r--r--source/blender/makesrna/RNA_enum_types.h1
-rw-r--r--source/blender/makesrna/intern/makesrna.c10
-rw-r--r--source/blender/makesrna/intern/rna_ID.c51
-rw-r--r--source/blender/makesrna/intern/rna_access.c31
-rw-r--r--source/blender/makesrna/intern/rna_action.c6
-rw-r--r--source/blender/makesrna/intern/rna_animation.c52
-rw-r--r--source/blender/makesrna/intern/rna_animation_api.c27
-rw-r--r--source/blender/makesrna/intern/rna_armature.c65
-rw-r--r--source/blender/makesrna/intern/rna_camera.c115
-rw-r--r--source/blender/makesrna/intern/rna_cloth.c4
-rw-r--r--source/blender/makesrna/intern/rna_collection.c8
-rw-r--r--source/blender/makesrna/intern/rna_color.c30
-rw-r--r--source/blender/makesrna/intern/rna_constraint.c64
-rw-r--r--source/blender/makesrna/intern/rna_context.c29
-rw-r--r--source/blender/makesrna/intern/rna_curve.c12
-rw-r--r--source/blender/makesrna/intern/rna_define.c16
-rw-r--r--source/blender/makesrna/intern/rna_depsgraph.c44
-rw-r--r--source/blender/makesrna/intern/rna_fcurve.c137
-rw-r--r--source/blender/makesrna/intern/rna_gpencil.c59
-rw-r--r--source/blender/makesrna/intern/rna_gpencil_modifier.c7
-rw-r--r--source/blender/makesrna/intern/rna_image.c39
-rw-r--r--source/blender/makesrna/intern/rna_image_api.c95
-rw-r--r--source/blender/makesrna/intern/rna_internal.h26
-rw-r--r--source/blender/makesrna/intern/rna_internal_types.h5
-rw-r--r--source/blender/makesrna/intern/rna_key.c4
-rw-r--r--source/blender/makesrna/intern/rna_layer.c58
-rw-r--r--source/blender/makesrna/intern/rna_light.c10
-rw-r--r--source/blender/makesrna/intern/rna_lightprobe.c2
-rw-r--r--source/blender/makesrna/intern/rna_linestyle.c4
-rw-r--r--source/blender/makesrna/intern/rna_main_api.c61
-rw-r--r--source/blender/makesrna/intern/rna_mask.c16
-rw-r--r--source/blender/makesrna/intern/rna_material.c35
-rw-r--r--source/blender/makesrna/intern/rna_mesh.c6
-rw-r--r--source/blender/makesrna/intern/rna_mesh_utils.h3
-rw-r--r--source/blender/makesrna/intern/rna_modifier.c114
-rw-r--r--source/blender/makesrna/intern/rna_nodetree.c47
-rw-r--r--source/blender/makesrna/intern/rna_object.c39
-rw-r--r--source/blender/makesrna/intern/rna_object_api.c74
-rw-r--r--source/blender/makesrna/intern/rna_object_force.c2
-rw-r--r--source/blender/makesrna/intern/rna_palette.c4
-rw-r--r--source/blender/makesrna/intern/rna_particle.c8
-rw-r--r--source/blender/makesrna/intern/rna_pose.c63
-rw-r--r--source/blender/makesrna/intern/rna_render.c20
-rw-r--r--source/blender/makesrna/intern/rna_rna.c2
-rw-r--r--source/blender/makesrna/intern/rna_scene.c302
-rw-r--r--source/blender/makesrna/intern/rna_scene_api.c22
-rw-r--r--source/blender/makesrna/intern/rna_screen.c2
-rw-r--r--source/blender/makesrna/intern/rna_sequencer.c16
-rw-r--r--source/blender/makesrna/intern/rna_shader_fx.c3
-rw-r--r--source/blender/makesrna/intern/rna_smoke.c2
-rw-r--r--source/blender/makesrna/intern/rna_space.c119
-rw-r--r--source/blender/makesrna/intern/rna_space_api.c2
-rw-r--r--source/blender/makesrna/intern/rna_tracking.c12
-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.c219
-rw-r--r--source/blender/makesrna/intern/rna_wm.c32
-rw-r--r--source/blender/makesrna/intern/rna_wm_gizmo.c7
-rw-r--r--source/blender/modifiers/intern/MOD_multires.c9
-rw-r--r--source/blender/modifiers/intern/MOD_weighted_normal.c2
-rw-r--r--source/blender/nodes/shader/node_shader_util.h4
-rw-r--r--source/blender/nodes/shader/nodes/node_shader_bsdf_principled.c21
-rw-r--r--source/blender/nodes/shader/nodes/node_shader_geometry.c2
-rw-r--r--source/blender/nodes/shader/nodes/node_shader_normal_map.c31
-rw-r--r--source/blender/nodes/shader/nodes/node_shader_object_info.c6
-rw-r--r--source/blender/nodes/shader/nodes/node_shader_tangent.c13
-rw-r--r--source/blender/nodes/shader/nodes/node_shader_tex_coord.c7
-rw-r--r--source/blender/nodes/shader/nodes/node_shader_tex_environment.c23
-rw-r--r--source/blender/nodes/shader/nodes/node_shader_tex_image.c64
-rw-r--r--source/blender/nodes/shader/nodes/node_shader_vector_displacement.c2
-rw-r--r--source/blender/python/generic/idprop_py_api.c3
-rw-r--r--source/blender/python/gpu/gpu_py_offscreen.c1
-rw-r--r--source/blender/python/intern/bpy_app_handlers.c1
-rw-r--r--source/blender/python/intern/bpy_rna.c11
-rw-r--r--source/blender/python/intern/bpy_rna_anim.c12
-rw-r--r--source/blender/python/mathutils/mathutils_Matrix.c29
-rw-r--r--source/blender/render/extern/include/RE_engine.h8
-rw-r--r--source/blender/render/extern/include/RE_pipeline.h25
-rw-r--r--source/blender/render/intern/include/render_types.h3
-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/multires_bake.c3
-rw-r--r--source/blender/render/intern/source/pipeline.c110
-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.h15
-rw-r--r--source/blender/windowmanager/WM_types.h18
-rw-r--r--source/blender/windowmanager/gizmo/WM_gizmo_types.h4
-rw-r--r--source/blender/windowmanager/gizmo/intern/wm_gizmo.c1
-rw-r--r--source/blender/windowmanager/gizmo/intern/wm_gizmo_map.c63
-rw-r--r--source/blender/windowmanager/intern/wm.c1
-rw-r--r--source/blender/windowmanager/intern/wm_dragdrop.c2
-rw-r--r--source/blender/windowmanager/intern/wm_draw.c11
-rw-r--r--source/blender/windowmanager/intern/wm_event_system.c13
-rw-r--r--source/blender/windowmanager/intern/wm_files.c745
-rw-r--r--source/blender/windowmanager/intern/wm_gesture.c6
-rw-r--r--source/blender/windowmanager/intern/wm_init_exit.c15
-rw-r--r--source/blender/windowmanager/intern/wm_keymap.c11
-rw-r--r--source/blender/windowmanager/intern/wm_operator_props.c20
-rw-r--r--source/blender/windowmanager/intern/wm_operator_type.c3
-rw-r--r--source/blender/windowmanager/intern/wm_operators.c36
-rw-r--r--source/blender/windowmanager/intern/wm_playanim.c2
-rw-r--r--source/blender/windowmanager/intern/wm_toolsystem.c16
-rw-r--r--source/blender/windowmanager/intern/wm_utils.c71
-rw-r--r--source/blender/windowmanager/intern/wm_window.c184
-rw-r--r--source/blender/windowmanager/wm_draw.h2
-rw-r--r--source/blender/windowmanager/wm_files.h7
653 files changed, 19179 insertions, 14600 deletions
diff --git a/source/blender/alembic/intern/abc_camera.cc b/source/blender/alembic/intern/abc_camera.cc
index b15608703de..dc7f00b63d9 100644
--- a/source/blender/alembic/intern/abc_camera.cc
+++ b/source/blender/alembic/intern/abc_camera.cc
@@ -80,19 +80,19 @@ void AbcCameraWriter::do_write()
m_camera_sample.setNearClippingPlane(cam->clip_start);
m_camera_sample.setFarClippingPlane(cam->clip_end);
- if (cam->dof_ob) {
- Imath::V3f v(m_object->loc[0] - cam->dof_ob->loc[0],
- m_object->loc[1] - cam->dof_ob->loc[1],
- m_object->loc[2] - cam->dof_ob->loc[2]);
+ if (cam->dof.focus_object) {
+ Imath::V3f v(m_object->loc[0] - cam->dof.focus_object->loc[0],
+ m_object->loc[1] - cam->dof.focus_object->loc[1],
+ m_object->loc[2] - cam->dof.focus_object->loc[2]);
m_camera_sample.setFocusDistance(v.length());
}
else {
- m_camera_sample.setFocusDistance(cam->gpu_dof.focus_distance);
+ m_camera_sample.setFocusDistance(cam->dof.focus_distance);
}
/* Blender camera does not have an fstop param, so try to find a custom prop
* instead. */
- m_camera_sample.setFStop(cam->gpu_dof.fstop);
+ m_camera_sample.setFStop(cam->dof.aperture_fstop);
m_camera_sample.setLensSqueezeRatio(1.0);
m_camera_schema.set(m_camera_sample);
@@ -166,8 +166,8 @@ void AbcCameraReader::readObjectData(Main *bmain, const ISampleSelector &sample_
bcam->shifty = v_film_offset / apperture_y / film_aspect;
bcam->clip_start = max_ff(0.1f, static_cast<float>(cam_sample.getNearClippingPlane()));
bcam->clip_end = static_cast<float>(cam_sample.getFarClippingPlane());
- bcam->gpu_dof.focus_distance = static_cast<float>(cam_sample.getFocusDistance());
- bcam->gpu_dof.fstop = static_cast<float>(cam_sample.getFStop());
+ bcam->dof.focus_distance = static_cast<float>(cam_sample.getFocusDistance());
+ bcam->dof.aperture_fstop = static_cast<float>(cam_sample.getFStop());
m_object = BKE_object_add_only_object(bmain, OB_CAMERA, m_object_name.c_str());
m_object->data = bcam;
diff --git a/source/blender/alembic/intern/abc_transform.cc b/source/blender/alembic/intern/abc_transform.cc
index 8b8ed6c5c4b..08f8eb8bd8f 100644
--- a/source/blender/alembic/intern/abc_transform.cc
+++ b/source/blender/alembic/intern/abc_transform.cc
@@ -86,7 +86,7 @@ void AbcTransformWriter::do_write()
m_xform, m_xform.getSchema().getTimeSampling());
}
- m_visibility.set(!(ob_eval->restrictflag & OB_RESTRICT_VIEW));
+ m_visibility.set(!(ob_eval->restrictflag & OB_RESTRICT_VIEWPORT));
if (!m_first_frame && !m_is_animated) {
return;
diff --git a/source/blender/blenkernel/BKE_appdir.h b/source/blender/blenkernel/BKE_appdir.h
index 7ff8514f675..e55cb69a5c6 100644
--- a/source/blender/blenkernel/BKE_appdir.h
+++ b/source/blender/blenkernel/BKE_appdir.h
@@ -36,6 +36,7 @@ const char *BKE_appdir_folder_id_version(const int folder_id, const int ver, con
bool BKE_appdir_app_is_portable_install(void);
bool BKE_appdir_app_template_any(void);
bool BKE_appdir_app_template_id_search(const char *app_template, char *path, size_t path_len);
+bool BKE_appdir_app_template_has_userpref(const char *app_template);
void BKE_appdir_app_templates(struct ListBase *templates);
/* Initialize path to program executable */
@@ -44,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_armature.h b/source/blender/blenkernel/BKE_armature.h
index b5da30e725d..6839e13ffe1 100644
--- a/source/blender/blenkernel/BKE_armature.h
+++ b/source/blender/blenkernel/BKE_armature.h
@@ -84,7 +84,9 @@ bool BKE_pose_minmax(
int bone_autoside_name(char name[64], int strip_number, short axis, float head, float tail);
struct Bone *BKE_armature_find_bone_name(struct bArmature *arm, const char *name);
-struct GHash *BKE_armature_bone_from_name_map(struct bArmature *arm);
+
+void BKE_armature_bone_hash_make(struct bArmature *arm);
+void BKE_armature_bone_hash_free(struct bArmature *arm);
bool BKE_armature_bone_flag_test_recursive(const struct Bone *bone, int flag);
diff --git a/source/blender/blenkernel/BKE_blender_version.h b/source/blender/blenkernel/BKE_blender_version.h
index e01f6a6b751..3fae40d6c7b 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 60
+#define BLENDER_SUBVERSION 71
/** Several breakages with 280, e.g. collections vs layers. */
#define BLENDER_MINVERSION 280
#define BLENDER_MINSUBVERSION 0
diff --git a/source/blender/blenkernel/BKE_blendfile.h b/source/blender/blenkernel/BKE_blendfile.h
index 216bef0d1e3..76c05b0411a 100644
--- a/source/blender/blenkernel/BKE_blendfile.h
+++ b/source/blender/blenkernel/BKE_blendfile.h
@@ -62,6 +62,8 @@ struct UserDef *BKE_blendfile_userdef_read_from_memory(const void *filebuf,
bool BKE_blendfile_userdef_write(const char *filepath, struct ReportList *reports);
bool BKE_blendfile_userdef_write_app_template(const char *filepath, struct ReportList *reports);
+bool BKE_blendfile_userdef_write_all(struct ReportList *reports);
+
struct WorkspaceConfigFileData *BKE_blendfile_workspace_config_read(const char *filepath,
const void *filebuf,
int filelength,
diff --git a/source/blender/blenkernel/BKE_camera.h b/source/blender/blenkernel/BKE_camera.h
index 10cd129fbf9..caed4959eff 100644
--- a/source/blender/blenkernel/BKE_camera.h
+++ b/source/blender/blenkernel/BKE_camera.h
@@ -139,8 +139,6 @@ bool BKE_camera_view_frame_fit_to_coords(const struct Depsgraph *depsgraph,
float r_co[3],
float *r_scale);
-void BKE_camera_to_gpu_dof(struct Object *camera, struct GPUFXSettings *r_fx_settings);
-
/* Camera multi-view API */
struct Object *BKE_camera_multiview_render(struct Scene *scene,
diff --git a/source/blender/blenkernel/BKE_collection.h b/source/blender/blenkernel/BKE_collection.h
index 47786629aed..0e093bb086b 100644
--- a/source/blender/blenkernel/BKE_collection.h
+++ b/source/blender/blenkernel/BKE_collection.h
@@ -161,6 +161,8 @@ bool BKE_collection_move(struct Main *bmain,
bool BKE_collection_find_cycle(struct Collection *new_ancestor, struct Collection *collection);
+bool BKE_collection_has_collection(struct Collection *parent, struct Collection *collection);
+
/* Iteration callbacks. */
typedef void (*BKE_scene_objects_Cb)(struct Object *ob, void *data);
diff --git a/source/blender/blenkernel/BKE_context.h b/source/blender/blenkernel/BKE_context.h
index 8be43a50be6..0d2998cc51e 100644
--- a/source/blender/blenkernel/BKE_context.h
+++ b/source/blender/blenkernel/BKE_context.h
@@ -311,8 +311,23 @@ int CTX_data_visible_gpencil_layers(const bContext *C, ListBase *list);
int CTX_data_editable_gpencil_layers(const bContext *C, ListBase *list);
int CTX_data_editable_gpencil_strokes(const bContext *C, ListBase *list);
+/* Gets pointer to the dependency graph.
+ * If it doesn't exist yet, it will be allocated.
+ *
+ * The result dependency graph is NOT guaranteed to be up-to-date neither from relation nor from
+ * evaluated data points of view.
+ *
+ * NOTE: Can not be used if access to a fully evaluated datablock is needed. */
struct Depsgraph *CTX_data_depsgraph(const bContext *C);
+/* Gets fully updated and evaluated dependency graph.
+ *
+ * All the relations and evaluated objects are guaranteed to be up to date.
+ *
+ * NOTE: Will be expensive if there are relations or objects tagged for update.
+ * NOTE: If there are pending updates depsgraph hooks will be invoked. */
+struct Depsgraph *CTX_data_evaluated_depsgraph(const bContext *C);
+
/* Will Return NULL if depsgraph is not allocated yet.
* Only used by handful of operators which are run on file load.
*/
diff --git a/source/blender/blenkernel/BKE_curve.h b/source/blender/blenkernel/BKE_curve.h
index 4eaa0fbe057..df1e7a7baea 100644
--- a/source/blender/blenkernel/BKE_curve.h
+++ b/source/blender/blenkernel/BKE_curve.h
@@ -134,21 +134,11 @@ void BKE_curve_editNurb_keyIndex_free(struct GHash **keyindex);
void BKE_curve_editNurb_free(struct Curve *cu);
struct ListBase *BKE_curve_editNurbs_get(struct Curve *cu);
-float *BKE_curve_make_orco(struct Depsgraph *depsgraph,
- struct Scene *scene,
- struct Object *ob,
- int *r_numVerts);
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,
- const bool use_render_resolution,
- 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);
@@ -212,9 +202,9 @@ void BKE_nurb_knot_calc_u(struct Nurb *nu);
void BKE_nurb_knot_calc_v(struct Nurb *nu);
/* nurb checks if they can be drawn, also clamp order func */
-bool BKE_nurb_check_valid_u(struct Nurb *nu);
-bool BKE_nurb_check_valid_v(struct Nurb *nu);
-bool BKE_nurb_check_valid_uv(struct Nurb *nu);
+bool BKE_nurb_check_valid_u(const struct Nurb *nu);
+bool BKE_nurb_check_valid_v(const struct Nurb *nu);
+bool BKE_nurb_check_valid_uv(const struct Nurb *nu);
bool BKE_nurb_order_clamp_u(struct Nurb *nu);
bool BKE_nurb_order_clamp_v(struct Nurb *nu);
diff --git a/source/blender/blenkernel/BKE_displist.h b/source/blender/blenkernel/BKE_displist.h
index 9bf5a2f9971..c57639a8193 100644
--- a/source/blender/blenkernel/BKE_displist.h
+++ b/source/blender/blenkernel/BKE_displist.h
@@ -85,27 +85,18 @@ void BKE_displist_make_surf(struct Depsgraph *depsgraph,
struct ListBase *dispbase,
struct Mesh **r_final,
const bool for_render,
- const bool for_orco,
- const bool use_render_resolution);
+ const bool for_orco);
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,
- const bool use_render_resolution,
- struct LinkNode *ob_cyclic_list);
-void BKE_displist_make_curveTypes_forOrco(struct Depsgraph *depsgraph,
- struct Scene *scene,
- struct Object *ob,
- struct ListBase *dispbase,
- 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_fcurve.h b/source/blender/blenkernel/BKE_fcurve.h
index c1232addee3..4c1a115eb23 100644
--- a/source/blender/blenkernel/BKE_fcurve.h
+++ b/source/blender/blenkernel/BKE_fcurve.h
@@ -340,6 +340,7 @@ float evaluate_fcurve_driver(struct PathResolvedRNA *anim_rna,
struct FCurve *fcu,
struct ChannelDriver *driver_orig,
float evaltime);
+bool BKE_fcurve_is_empty(struct FCurve *fcu);
/* evaluate fcurve and store value */
float calculate_fcurve(struct PathResolvedRNA *anim_rna, struct FCurve *fcu, float evaltime);
diff --git a/source/blender/blenkernel/BKE_global.h b/source/blender/blenkernel/BKE_global.h
index 2c19c1e2006..9fe8fc3880f 100644
--- a/source/blender/blenkernel/BKE_global.h
+++ b/source/blender/blenkernel/BKE_global.h
@@ -107,10 +107,10 @@ 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),
+ G_FLAG_USERPREF_NO_SAVE_ON_EXIT = (1 << 4),
G_FLAG_SCRIPT_AUTOEXEC = (1 << 13),
/** When this flag is set ignore the prefs #USER_SCRIPT_AUTOEXEC_DISABLE. */
@@ -121,7 +121,8 @@ enum {
/** Don't overwrite these flags when reading a file. */
#define G_FLAG_ALL_RUNTIME \
- (G_FLAG_SCRIPT_AUTOEXEC | G_FLAG_SCRIPT_OVERRIDE_PREF | G_FLAG_EVENT_SIMULATE)
+ (G_FLAG_SCRIPT_AUTOEXEC | G_FLAG_SCRIPT_OVERRIDE_PREF | G_FLAG_EVENT_SIMULATE | \
+ G_FLAG_USERPREF_NO_SAVE_ON_EXIT)
/** Flags to read from blend file. */
#define G_FLAG_ALL_READFILE 0
diff --git a/source/blender/blenkernel/BKE_idprop.h b/source/blender/blenkernel/BKE_idprop.h
index e6f3d7b4a99..0eb8df1b19d 100644
--- a/source/blender/blenkernel/BKE_idprop.h
+++ b/source/blender/blenkernel/BKE_idprop.h
@@ -134,7 +134,8 @@ struct IDProperty *IDP_New(const char type,
const IDPropertyTemplate *val,
const char *name) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
-void IDP_FreeProperty_ex(struct IDProperty *prop, const bool do_id_user);
+void IDP_FreePropertyContent_ex(struct IDProperty *prop, const bool do_id_user);
+void IDP_FreePropertyContent(struct IDProperty *prop);
void IDP_FreeProperty(struct IDProperty *prop);
void IDP_ClearProperty(IDProperty *prop);
diff --git a/source/blender/blenkernel/BKE_image.h b/source/blender/blenkernel/BKE_image.h
index 28886a5a195..b9f2123b2bd 100644
--- a/source/blender/blenkernel/BKE_image.h
+++ b/source/blender/blenkernel/BKE_image.h
@@ -153,29 +153,6 @@ struct RenderData;
struct RenderPass;
struct RenderResult;
-/* ima->source; where image comes from */
-#define IMA_SRC_CHECK 0
-#define IMA_SRC_FILE 1
-#define IMA_SRC_SEQUENCE 2
-#define IMA_SRC_MOVIE 3
-#define IMA_SRC_GENERATED 4
-#define IMA_SRC_VIEWER 5
-
-/* ima->type, how to handle/generate it */
-#define IMA_TYPE_IMAGE 0
-#define IMA_TYPE_MULTILAYER 1
-/* generated */
-#define IMA_TYPE_UV_TEST 2
-/* viewers */
-#define IMA_TYPE_R_RESULT 4
-#define IMA_TYPE_COMPOSITE 5
-
-enum {
- IMA_GENTYPE_BLANK = 0,
- IMA_GENTYPE_GRID = 1,
- IMA_GENTYPE_GRID_COLOR = 2,
-};
-
/* ima->ok */
#define IMA_OK 1
#define IMA_OK_LOADED 2
@@ -340,12 +317,16 @@ void BKE_image_buf_fill_checker_color(unsigned char *rect,
unsigned char *BKE_image_get_pixels_for_frame(struct Image *image, int frame);
float *BKE_image_get_float_pixels_for_frame(struct Image *image, int frame);
+/* Image modifications */
+bool BKE_image_is_dirty(struct Image *image);
+void BKE_image_mark_dirty(struct Image *image, struct ImBuf *ibuf);
+
/* Guess offset for the first frame in the sequence */
int BKE_image_sequence_guess_offset(struct Image *image);
bool BKE_image_has_anim(struct Image *image);
bool BKE_image_has_packedfile(struct Image *image);
+bool BKE_image_has_filepath(struct Image *ima);
bool BKE_image_is_animated(struct Image *image);
-bool BKE_image_is_dirty(struct Image *image);
void BKE_image_file_format_set(struct Image *image,
int ftype,
const struct ImbFormatOptions *options);
diff --git a/source/blender/blenkernel/BKE_mesh.h b/source/blender/blenkernel/BKE_mesh.h
index ecee00b1b3f..c410946f438 100644
--- a/source/blender/blenkernel/BKE_mesh.h
+++ b/source/blender/blenkernel/BKE_mesh.h
@@ -208,12 +208,13 @@ 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);
-struct Mesh *BKE_mesh_new_from_object(struct Depsgraph *depsgraph,
- struct Main *bmain,
- struct Scene *sce,
- struct Object *ob,
- const bool apply_modifiers,
- const bool calc_undeformed);
+/* 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);
+
+/* 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_create_derived_for_modifier(struct Depsgraph *depsgraph,
struct Scene *scene,
struct Object *ob_eval,
@@ -671,11 +672,9 @@ void BKE_mesh_eval_geometry(struct Depsgraph *depsgraph, struct Mesh *mesh);
/* Draw Cache */
enum {
BKE_MESH_BATCH_DIRTY_ALL = 0,
- BKE_MESH_BATCH_DIRTY_MAYBE_ALL,
BKE_MESH_BATCH_DIRTY_SELECT,
BKE_MESH_BATCH_DIRTY_SELECT_PAINT,
BKE_MESH_BATCH_DIRTY_SHADING,
- BKE_MESH_BATCH_DIRTY_SCULPT_COORDS,
BKE_MESH_BATCH_DIRTY_UVEDIT_ALL,
BKE_MESH_BATCH_DIRTY_UVEDIT_SELECT,
};
diff --git a/source/blender/blenkernel/BKE_object.h b/source/blender/blenkernel/BKE_object.h
index 49b35bfccc1..aa4d9696527 100644
--- a/source/blender/blenkernel/BKE_object.h
+++ b/source/blender/blenkernel/BKE_object.h
@@ -100,6 +100,8 @@ bool BKE_object_is_mode_compat(const struct Object *ob, eObjectMode object_mode)
bool BKE_object_data_is_in_editmode(const struct ID *id);
+void BKE_object_update_select_id(struct Main *bmain);
+
typedef enum eObjectVisibilityResult {
OB_VISIBLE_SELF = 1,
OB_VISIBLE_PARTICLES = 2,
@@ -394,6 +396,15 @@ bool BKE_object_empty_image_frame_is_visible_in_view3d(const struct Object *ob,
bool BKE_object_empty_image_data_is_visible_in_view3d(const struct Object *ob,
const struct RegionView3D *rv3d);
+/* This is an utility function for Python's object.to_mesh() (the naming is not very clear though).
+ * 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);
+
+void BKE_object_to_mesh_clear(struct Object *object);
+
#ifdef __cplusplus
}
#endif
diff --git a/source/blender/blenkernel/BKE_pbvh.h b/source/blender/blenkernel/BKE_pbvh.h
index f59288f54bd..315c0224b11 100644
--- a/source/blender/blenkernel/BKE_pbvh.h
+++ b/source/blender/blenkernel/BKE_pbvh.h
@@ -34,6 +34,7 @@ struct CCGKey;
struct CustomData;
struct DMFlagMat;
struct GPUBatch;
+struct GPU_PBVH_Buffers;
struct MLoop;
struct MLoopTri;
struct MPoly;
@@ -48,6 +49,21 @@ typedef struct {
float (*co)[3];
} PBVHProxyNode;
+typedef enum {
+ PBVH_Leaf = 1,
+
+ PBVH_UpdateNormals = 2,
+ PBVH_UpdateBB = 4,
+ PBVH_UpdateOriginalBB = 8,
+ PBVH_UpdateDrawBuffers = 16,
+ PBVH_UpdateRedraw = 32,
+
+ PBVH_RebuildDrawBuffers = 64,
+ PBVH_FullyHidden = 128,
+
+ PBVH_UpdateTopology = 256,
+} PBVHNodeFlags;
+
/* Callbacks */
/* returns 1 if the search should continue from this node, 0 otherwise */
@@ -151,13 +167,15 @@ bool BKE_pbvh_node_find_nearest_to_ray(PBVH *bvh,
void BKE_pbvh_draw_cb(PBVH *bvh,
float (*planes)[4],
float (*fnors)[3],
- bool fast,
- bool wires,
- bool only_mask,
bool show_vcol,
- void (*draw_fn)(void *user_data, struct GPUBatch *batch),
+ void (*draw_fn)(void *user_data, struct GPU_PBVH_Buffers *buffers),
void *user_data);
+void BKE_pbvh_draw_debug_cb(
+ PBVH *bvh,
+ void (*draw_fn)(void *user_data, const float bmin[3], const float bmax[3], PBVHNodeFlags flag),
+ void *user_data);
+
/* PBVH Access */
typedef enum {
PBVH_FACES,
@@ -202,21 +220,6 @@ bool BKE_pbvh_bmesh_update_topology(PBVH *bvh,
/* Node Access */
-typedef enum {
- PBVH_Leaf = 1,
-
- PBVH_UpdateNormals = 2,
- PBVH_UpdateBB = 4,
- PBVH_UpdateOriginalBB = 8,
- PBVH_UpdateDrawBuffers = 16,
- PBVH_UpdateRedraw = 32,
-
- PBVH_RebuildDrawBuffers = 64,
- PBVH_FullyHidden = 128,
-
- PBVH_UpdateTopology = 256,
-} PBVHNodeFlags;
-
void BKE_pbvh_node_mark_update(PBVHNode *node);
void BKE_pbvh_node_mark_rebuild_draw(PBVHNode *node);
void BKE_pbvh_node_mark_redraw(PBVHNode *node);
diff --git a/source/blender/blenkernel/BKE_scene.h b/source/blender/blenkernel/BKE_scene.h
index 75ff5eace3c..581df648add 100644
--- a/source/blender/blenkernel/BKE_scene.h
+++ b/source/blender/blenkernel/BKE_scene.h
@@ -240,6 +240,11 @@ void BKE_scene_cursor_quat_to_rot(struct View3DCursor *cursor,
const float quat[4],
bool use_compat);
+void BKE_scene_cursor_to_mat4(const struct View3DCursor *cursor, float mat[4][4]);
+void BKE_scene_cursor_from_mat4(struct View3DCursor *cursor,
+ const float mat[4][4],
+ bool use_compat);
+
#ifdef __cplusplus
}
#endif
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 017c15ebe41..170ab657388 100644
--- a/source/blender/blenkernel/BKE_sequencer.h
+++ b/source/blender/blenkernel/BKE_sequencer.h
@@ -100,8 +100,8 @@ typedef struct SeqRenderData {
/* special case for OpenGL render */
struct GPUOffScreen *gpu_offscreen;
- int gpu_samples;
- bool gpu_full_samples;
+ // int gpu_samples;
+ // bool gpu_full_samples;
} SeqRenderData;
void BKE_sequencer_new_render_data(struct Main *bmain,
diff --git a/source/blender/blenkernel/BKE_workspace.h b/source/blender/blenkernel/BKE_workspace.h
index 0a4ad4cd994..133cf2d6cf5 100644
--- a/source/blender/blenkernel/BKE_workspace.h
+++ b/source/blender/blenkernel/BKE_workspace.h
@@ -110,6 +110,8 @@ void BKE_workspace_hook_layout_for_workspace_set(struct WorkSpaceInstanceHook *h
bool BKE_workspace_owner_id_check(const struct WorkSpace *workspace, const char *owner_id)
ATTR_NONNULL();
+void BKE_workspace_id_tag_all_visible(struct Main *bmain, int tag) ATTR_NONNULL();
+
#undef GETTER_ATTRS
#undef SETTER_ATTRS
diff --git a/source/blender/blenkernel/BKE_writeavi.h b/source/blender/blenkernel/BKE_writeavi.h
index 72817217a0a..3212bad75cb 100644
--- a/source/blender/blenkernel/BKE_writeavi.h
+++ b/source/blender/blenkernel/BKE_writeavi.h
@@ -53,9 +53,6 @@ typedef struct bMovieHandle {
const char *suffix,
struct ReportList *reports);
void (*end_movie)(void *context_v);
- int (*get_next_frame)(void *context_v,
- struct RenderData *rd,
- struct ReportList *reports); /* optional */
void (*get_movie_path)(char *string,
struct RenderData *rd,
bool preview,
diff --git a/source/blender/blenkernel/intern/action.c b/source/blender/blenkernel/intern/action.c
index 9b321ff4e44..65b837048cb 100644
--- a/source/blender/blenkernel/intern/action.c
+++ b/source/blender/blenkernel/intern/action.c
@@ -822,7 +822,6 @@ void BKE_pose_channel_free_ex(bPoseChannel *pchan, bool do_id_user)
if (pchan->prop) {
IDP_FreeProperty(pchan->prop);
- MEM_freeN(pchan->prop);
}
/* Cached data, for new draw manager rendering code. */
@@ -964,7 +963,6 @@ void BKE_pose_channel_copy_data(bPoseChannel *pchan, const bPoseChannel *pchan_f
if (pchan->prop) {
/* unlikely but possible it exists */
IDP_FreeProperty(pchan->prop);
- MEM_freeN(pchan->prop);
pchan->prop = NULL;
}
if (pchan_from->prop) {
@@ -978,6 +976,7 @@ void BKE_pose_channel_copy_data(bPoseChannel *pchan, const bPoseChannel *pchan_f
}
pchan->custom_scale = pchan_from->custom_scale;
+ pchan->drawflag = pchan_from->drawflag;
}
/* checks for IK constraint, Spline IK, and also for Follow-Path constraint.
diff --git a/source/blender/blenkernel/intern/addon.c b/source/blender/blenkernel/intern/addon.c
index 486da61fe68..99ef38722f5 100644
--- a/source/blender/blenkernel/intern/addon.c
+++ b/source/blender/blenkernel/intern/addon.c
@@ -81,7 +81,6 @@ void BKE_addon_free(bAddon *addon)
{
if (addon->prop) {
IDP_FreeProperty(addon->prop);
- MEM_freeN(addon->prop);
}
MEM_freeN(addon);
}
diff --git a/source/blender/blenkernel/intern/anim_sys.c b/source/blender/blenkernel/intern/anim_sys.c
index cc5cd3b03ae..4a939180fb0 100644
--- a/source/blender/blenkernel/intern/anim_sys.c
+++ b/source/blender/blenkernel/intern/anim_sys.c
@@ -1893,6 +1893,10 @@ static void animsys_evaluate_fcurves(Depsgraph *depsgraph,
if ((fcu->flag & (FCURVE_MUTED | FCURVE_DISABLED))) {
continue;
}
+ /* Skip empty curves, as if muted. */
+ if (BKE_fcurve_is_empty(fcu)) {
+ continue;
+ }
PathResolvedRNA anim_rna;
if (animsys_store_rna_setting(ptr, fcu->rna_path, fcu->array_index, &anim_rna)) {
const float curval = calculate_fcurve(&anim_rna, fcu, ctime);
@@ -2005,7 +2009,7 @@ void animsys_evaluate_action_group(PointerRNA *ptr, bAction *act, bActionGroup *
/* calculate then execute each curve */
for (fcu = agrp->channels.first; (fcu) && (fcu->grp == agrp); fcu = fcu->next) {
/* check if this curve should be skipped */
- if ((fcu->flag & (FCURVE_MUTED | FCURVE_DISABLED)) == 0) {
+ if ((fcu->flag & (FCURVE_MUTED | FCURVE_DISABLED)) == 0 && !BKE_fcurve_is_empty(fcu)) {
PathResolvedRNA anim_rna;
if (animsys_store_rna_setting(ptr, fcu->rna_path, fcu->array_index, &anim_rna)) {
const float curval = calculate_fcurve(&anim_rna, fcu, ctime);
@@ -3101,6 +3105,9 @@ static void nlastrip_evaluate_actionclip(PointerRNA *ptr,
if ((fcu->grp) && (fcu->grp->flag & AGRP_MUTED)) {
continue;
}
+ if (BKE_fcurve_is_empty(fcu)) {
+ continue;
+ }
/* evaluate the F-Curve's value for the time given in the strip
* NOTE: we use the modified time here, since strip's F-Curve Modifiers
@@ -3327,6 +3334,9 @@ static void nla_eval_domain_action(PointerRNA *ptr,
if ((fcu->grp) && (fcu->grp->flag & AGRP_MUTED)) {
continue;
}
+ if (BKE_fcurve_is_empty(fcu)) {
+ continue;
+ }
NlaEvalChannel *nec = nlaevalchan_verify(ptr, channels, fcu->rna_path);
@@ -3608,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,
@@ -3652,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 2b4123c74e2..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 */
@@ -838,6 +839,26 @@ bool BKE_appdir_app_template_id_search(const char *app_template, char *path, siz
return false;
}
+bool BKE_appdir_app_template_has_userpref(const char *app_template)
+{
+ /* Test if app template provides a userpref.blend.
+ * If not, we will share user preferences with the rest of Blender. */
+ if (!app_template && app_template[0]) {
+ return false;
+ }
+
+ char app_template_path[FILE_MAX];
+ if (!BKE_appdir_app_template_id_search(
+ app_template, app_template_path, sizeof(app_template_path))) {
+ return false;
+ }
+
+ char userpref_path[FILE_MAX];
+ BLI_path_join(
+ userpref_path, sizeof(userpref_path), app_template_path, BLENDER_USERPREF_FILE, NULL);
+ return BLI_exists(userpref_path);
+}
+
void BKE_appdir_app_templates(ListBase *templates)
{
BLI_listbase_clear(templates);
@@ -1004,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/armature.c b/source/blender/blenkernel/intern/armature.c
index 60446bf60b6..df22aa1dcfb 100644
--- a/source/blender/blenkernel/intern/armature.c
+++ b/source/blender/blenkernel/intern/armature.c
@@ -112,7 +112,6 @@ void BKE_armature_bonelist_free(ListBase *lb)
for (bone = lb->first; bone; bone = bone->next) {
if (bone->prop) {
IDP_FreeProperty(bone->prop);
- MEM_freeN(bone->prop);
}
BKE_armature_bonelist_free(&bone->childbase);
}
@@ -125,6 +124,7 @@ void BKE_armature_free(bArmature *arm)
{
BKE_animdata_free(&arm->id, false);
+ BKE_armature_bone_hash_free(arm);
BKE_armature_bonelist_free(&arm->bonebase);
/* free editmode data */
@@ -169,25 +169,20 @@ static void copy_bonechildren(Bone *bone_dst,
}
}
-static void copy_bonechildren_custom_handles(Bone *bone_dst, bArmature *arm_dst, GHash **bone_hash)
+static void copy_bonechildren_custom_handles(Bone *bone_dst, bArmature *arm_dst)
{
Bone *bone_dst_child;
- /* Lazily create the name -> bone hashtable. */
- if ((bone_dst->bbone_prev || bone_dst->bbone_next) && *bone_hash == NULL) {
- *bone_hash = BKE_armature_bone_from_name_map(arm_dst);
- }
-
if (bone_dst->bbone_prev) {
- bone_dst->bbone_prev = BLI_ghash_lookup(*bone_hash, bone_dst->bbone_prev->name);
+ bone_dst->bbone_prev = BKE_armature_find_bone_name(arm_dst, bone_dst->bbone_prev->name);
}
if (bone_dst->bbone_next) {
- bone_dst->bbone_next = BLI_ghash_lookup(*bone_hash, bone_dst->bbone_next->name);
+ bone_dst->bbone_next = BKE_armature_find_bone_name(arm_dst, bone_dst->bbone_next->name);
}
for (bone_dst_child = bone_dst->childbase.first; bone_dst_child;
bone_dst_child = bone_dst_child->next) {
- copy_bonechildren_custom_handles(bone_dst_child, arm_dst, bone_hash);
+ copy_bonechildren_custom_handles(bone_dst_child, arm_dst);
}
}
@@ -212,6 +207,8 @@ void BKE_armature_copy_data(Main *UNUSED(bmain),
/* We never handle usercount here for own data. */
const int flag_subdata = flag | LIB_ID_CREATE_NO_USER_REFCOUNT;
+ arm_dst->bonehash = NULL;
+
BLI_duplicatelist(&arm_dst->bonebase, &arm_src->bonebase);
/* Duplicate the childrens' lists */
@@ -224,15 +221,11 @@ void BKE_armature_copy_data(Main *UNUSED(bmain),
arm_dst->act_bone = bone_dst_act;
- /* Fix custom handle references. */
- GHash *bone_hash = NULL; /* lazily created */
+ BKE_armature_bone_hash_make(arm_dst);
+ /* Fix custom handle references. */
for (bone_dst = arm_dst->bonebase.first; bone_dst; bone_dst = bone_dst->next) {
- copy_bonechildren_custom_handles(bone_dst, arm_dst, &bone_hash);
- }
-
- if (bone_hash) {
- BLI_ghash_free(bone_hash, NULL, NULL);
+ copy_bonechildren_custom_handles(bone_dst, arm_dst);
}
arm_dst->edbo = NULL;
@@ -274,6 +267,10 @@ Bone *BKE_armature_find_bone_name(bArmature *arm, const char *name)
return NULL;
}
+ if (arm->bonehash) {
+ return BLI_ghash_lookup(arm->bonehash, name);
+ }
+
return get_named_bone_bonechildren(&arm->bonebase, name);
}
@@ -291,7 +288,7 @@ static void armature_bone_from_name_insert_recursive(GHash *bone_hash, ListBase
* \note typically #bPose.chanhash us used via #BKE_pose_channel_find_name
* this is for the cases we can't use pose channels.
*/
-GHash *BKE_armature_bone_from_name_map(bArmature *arm)
+static GHash *armature_bone_from_name_map(bArmature *arm)
{
const int bones_count = BKE_armature_bonelist_count(&arm->bonebase);
GHash *bone_hash = BLI_ghash_str_new_ex(__func__, bones_count);
@@ -299,6 +296,21 @@ GHash *BKE_armature_bone_from_name_map(bArmature *arm)
return bone_hash;
}
+void BKE_armature_bone_hash_make(bArmature *arm)
+{
+ if (!arm->bonehash) {
+ arm->bonehash = armature_bone_from_name_map(arm);
+ }
+}
+
+void BKE_armature_bone_hash_free(bArmature *arm)
+{
+ if (arm->bonehash) {
+ BLI_ghash_free(arm->bonehash, NULL, NULL);
+ arm->bonehash = NULL;
+ }
+}
+
bool BKE_armature_bone_flag_test_recursive(const Bone *bone, int flag)
{
if (bone->flag & flag) {
@@ -2417,7 +2429,6 @@ static void pose_proxy_synchronize(Object *ob, Object *from, int layer_protected
}
if (prop_orig) {
IDP_FreeProperty(prop_orig);
- MEM_freeN(prop_orig);
}
}
}
@@ -2458,11 +2469,9 @@ void BKE_pose_clear_pointers(bPose *pose)
void BKE_pose_remap_bone_pointers(bArmature *armature, bPose *pose)
{
- GHash *bone_hash = BKE_armature_bone_from_name_map(armature);
for (bPoseChannel *pchan = pose->chanbase.first; pchan; pchan = pchan->next) {
- pchan->bone = BLI_ghash_lookup(bone_hash, pchan->name);
+ pchan->bone = BKE_armature_find_bone_name(armature, pchan->name);
}
- BLI_ghash_free(bone_hash, NULL, NULL);
}
/** Find the matching pose channel using the bone name, if not NULL. */
diff --git a/source/blender/blenkernel/intern/armature_update.c b/source/blender/blenkernel/intern/armature_update.c
index c71c2dc86cf..bf7d81e5d63 100644
--- a/source/blender/blenkernel/intern/armature_update.c
+++ b/source/blender/blenkernel/intern/armature_update.c
@@ -273,11 +273,12 @@ static void splineik_evaluate_bone(
/* first, adjust the point positions on the curve */
float curveLen = tree->points[index] - tree->points[index + 1];
float pointStart = state->curve_position;
+ float poseScale = len_v3v3(poseHead, poseTail) / pchan->bone->length;
float baseScale = 1.0f;
if (ikData->yScaleMode == CONSTRAINT_SPLINEIK_YS_ORIGINAL) {
/* Carry over the bone Y scale to the curve range. */
- baseScale = len_v3v3(poseHead, poseTail) / pchan->bone->length;
+ baseScale = poseScale;
}
float pointEnd = pointStart + curveLen * baseScale * state->curve_scale;
@@ -339,8 +340,8 @@ static void splineik_evaluate_bone(
sub_v3_v3v3(splineVec, poseTail, poseHead);
scaleFac = len_v3(splineVec) / pchan->bone->length;
- /* Adjust the scale factor towards the neutral state when rolling off the curve end. */
- scaleFac = interpf(scaleFac, baseScale, tailBlendFac);
+ /* Extrapolate the full length of the bone as it rolls off the end of the curve. */
+ scaleFac = (tailBlendFac < 1e-5f) ? baseScale : scaleFac / tailBlendFac;
/* Step 3: compute the shortest rotation needed
* to map from the bone rotation to the current axis.
@@ -394,24 +395,31 @@ static void splineik_evaluate_bone(
}
/* step 4: set the scaling factors for the axes */
- {
- /* only multiply the y-axis by the scaling factor to get nice volume-preservation */
- mul_v3_fl(poseMat[1], scaleFac);
- /* set the scaling factors of the x and z axes from... */
- switch (ikData->xzScaleMode) {
- case CONSTRAINT_SPLINEIK_XZS_ORIGINAL: {
- /* original scales get used */
- float scale;
+ /* Always multiply the y-axis by the scaling factor to get the correct length. */
+ mul_v3_fl(poseMat[1], scaleFac);
+
+ /* After that, apply x/z scaling modes. */
+ if (ikData->xzScaleMode != CONSTRAINT_SPLINEIK_XZS_NONE) {
+ /* First, apply the original scale if enabled. */
+ if (ikData->xzScaleMode == CONSTRAINT_SPLINEIK_XZS_ORIGINAL ||
+ (ikData->flag & CONSTRAINT_SPLINEIK_USE_ORIGINAL_SCALE) != 0) {
+ float scale;
+
+ /* x-axis scale */
+ scale = len_v3(pchan->pose_mat[0]);
+ mul_v3_fl(poseMat[0], scale);
+ /* z-axis scale */
+ scale = len_v3(pchan->pose_mat[2]);
+ mul_v3_fl(poseMat[2], scale);
+
+ /* Adjust the scale factor used for volume preservation
+ * to consider the pre-IK scaling as the initial volume. */
+ scaleFac /= poseScale;
+ }
- /* x-axis scale */
- scale = len_v3(pchan->pose_mat[0]);
- mul_v3_fl(poseMat[0], scale);
- /* z-axis scale */
- scale = len_v3(pchan->pose_mat[2]);
- mul_v3_fl(poseMat[2], scale);
- break;
- }
+ /* Apply volume preservation. */
+ switch (ikData->xzScaleMode) {
case CONSTRAINT_SPLINEIK_XZS_INVERSE: {
/* old 'volume preservation' method using the inverse scale */
float scale;
@@ -483,14 +491,14 @@ static void splineik_evaluate_bone(
break;
}
}
+ }
- /* finally, multiply the x and z scaling by the radius of the curve too,
- * to allow automatic scales to get tweaked still
- */
- if ((ikData->flag & CONSTRAINT_SPLINEIK_NO_CURVERAD) == 0) {
- mul_v3_fl(poseMat[0], radius);
- mul_v3_fl(poseMat[2], radius);
- }
+ /* Finally, multiply the x and z scaling by the radius of the curve too,
+ * to allow automatic scales to get tweaked still.
+ */
+ if ((ikData->flag & CONSTRAINT_SPLINEIK_NO_CURVERAD) == 0) {
+ mul_v3_fl(poseMat[0], radius);
+ mul_v3_fl(poseMat[2], radius);
}
/* Blend the scaling of the matrix according to the influence. */
diff --git a/source/blender/blenkernel/intern/blender.c b/source/blender/blenkernel/intern/blender.c
index 48b271cf277..9fd3c24092c 100644
--- a/source/blender/blenkernel/intern/blender.c
+++ b/source/blender/blenkernel/intern/blender.c
@@ -155,7 +155,6 @@ static void keymap_item_free(wmKeyMapItem *kmi)
{
if (kmi->properties) {
IDP_FreeProperty(kmi->properties);
- MEM_freeN(kmi->properties);
}
if (kmi->ptr) {
MEM_freeN(kmi->ptr);
@@ -212,7 +211,6 @@ static void userdef_free_keyconfig_prefs(UserDef *userdef)
kpt = kpt_next) {
kpt_next = kpt->next;
IDP_FreeProperty(kpt->prop);
- MEM_freeN(kpt->prop);
MEM_freeN(kpt);
}
BLI_listbase_clear(&userdef->user_keyconfig_prefs);
diff --git a/source/blender/blenkernel/intern/blender_user_menu.c b/source/blender/blenkernel/intern/blender_user_menu.c
index 911f3fdc7b2..ad34ef03e04 100644
--- a/source/blender/blenkernel/intern/blender_user_menu.c
+++ b/source/blender/blenkernel/intern/blender_user_menu.c
@@ -97,7 +97,6 @@ void BKE_blender_user_menu_item_free(bUserMenuItem *umi)
bUserMenuItem_Op *umi_op = (bUserMenuItem_Op *)umi;
if (umi_op->prop) {
IDP_FreeProperty(umi_op->prop);
- MEM_freeN(umi_op->prop);
}
}
MEM_freeN(umi);
diff --git a/source/blender/blenkernel/intern/blendfile.c b/source/blender/blenkernel/intern/blendfile.c
index d1a3045a829..570c1b9bd4c 100644
--- a/source/blender/blenkernel/intern/blendfile.c
+++ b/source/blender/blenkernel/intern/blendfile.c
@@ -98,6 +98,25 @@ static bool wm_scene_is_visible(wmWindowManager *wm, Scene *scene)
return false;
}
+static void setup_app_userdef(BlendFileData *bfd)
+{
+ if (bfd->user) {
+ /* only here free userdef themes... */
+ BKE_blender_userdef_data_set_and_free(bfd->user);
+ bfd->user = NULL;
+
+ /* Security issue: any blend file could include a USER block.
+ *
+ * Currently we load prefs from BLENDER_STARTUP_FILE and later on load BLENDER_USERPREF_FILE,
+ * to load the preferences defined in the users home dir.
+ *
+ * This means we will never accidentally (or maliciously)
+ * enable scripts auto-execution by loading a '.blend' file.
+ */
+ U.flag |= USER_SCRIPT_AUTOEXEC_DISABLE;
+ }
+}
+
/**
* Context matching, handle no-ui case
*
@@ -235,26 +254,10 @@ static void setup_app_data(bContext *C,
RNA_property_update_cache_free();
bmain = G_MAIN = bfd->main;
+ bfd->main = NULL;
CTX_data_main_set(C, bmain);
- if (bfd->user) {
-
- /* only here free userdef themes... */
- BKE_blender_userdef_data_set_and_free(bfd->user);
- bfd->user = NULL;
-
- /* Security issue: any blend file could include a USER block.
- *
- * Currently we load prefs from BLENDER_STARTUP_FILE and later on load BLENDER_USERPREF_FILE,
- * to load the preferences defined in the users home dir.
- *
- * This means we will never accidentally (or maliciously)
- * enable scripts auto-execution by loading a '.blend' file.
- */
- U.flag |= USER_SCRIPT_AUTOEXEC_DISABLE;
- }
-
/* case G_FILE_NO_UI or no screens in file */
if (mode != LOAD_UI) {
/* leave entire context further unaltered? */
@@ -356,8 +359,20 @@ static void setup_app_data(bContext *C,
/* TODO(sergey): Can this be also move above? */
RE_FreeAllPersistentData();
}
+}
- MEM_freeN(bfd);
+static void setup_app_blend_file_data(bContext *C,
+ BlendFileData *bfd,
+ const char *filepath,
+ const struct BlendFileReadParams *params,
+ ReportList *reports)
+{
+ if ((params->skip_flags & BLO_READ_SKIP_USERDEF) == 0) {
+ setup_app_userdef(bfd);
+ }
+ if ((params->skip_flags & BLO_READ_SKIP_DATA) == 0) {
+ setup_app_data(C, bfd, filepath, params->is_startup, reports);
+ }
}
static int handle_subversion_warning(Main *main, ReportList *reports)
@@ -400,7 +415,8 @@ int BKE_blendfile_read(bContext *C,
retval = BKE_BLENDFILE_READ_FAIL;
}
else {
- setup_app_data(C, bfd, filepath, params->is_startup, reports);
+ setup_app_blend_file_data(C, bfd, filepath, params, reports);
+ BLO_blendfiledata_free(bfd);
}
}
else {
@@ -422,9 +438,13 @@ bool BKE_blendfile_read_from_memory(bContext *C,
bfd = BLO_read_from_memory(filebuf, filelength, params->skip_flags, reports);
if (bfd) {
if (update_defaults) {
- BLO_update_defaults_startup_blend(bfd->main, NULL);
+ if ((params->skip_flags & BLO_READ_SKIP_DATA) == 0) {
+ BLO_update_defaults_startup_blend(bfd->main, NULL);
+ }
}
- setup_app_data(C, bfd, "<memory2>", params->is_startup, reports);
+
+ setup_app_blend_file_data(C, bfd, "<memory2>", params, reports);
+ BLO_blendfiledata_free(bfd);
}
else {
BKE_reports_prepend(reports, "Loading failed: ");
@@ -453,7 +473,8 @@ bool BKE_blendfile_read_from_memfile(bContext *C,
BKE_id_free(bfd->main, bfd->main->screens.first);
}
- setup_app_data(C, bfd, "<memory1>", params->is_startup, reports);
+ setup_app_blend_file_data(C, bfd, "<memory1>", params, reports);
+ BLO_blendfiledata_free(bfd);
}
else {
BKE_reports_prepend(reports, "Loading failed: ");
@@ -566,6 +587,63 @@ bool BKE_blendfile_userdef_write_app_template(const char *filepath, ReportList *
return ok;
}
+bool BKE_blendfile_userdef_write_all(ReportList *reports)
+{
+ char filepath[FILE_MAX];
+ const char *cfgdir;
+ bool ok = true;
+ const bool use_template_userpref = BKE_appdir_app_template_has_userpref(U.app_template);
+
+ if ((cfgdir = BKE_appdir_folder_id_create(BLENDER_USER_CONFIG, NULL))) {
+ bool ok_write;
+ BLI_path_join(filepath, sizeof(filepath), cfgdir, BLENDER_USERPREF_FILE, NULL);
+
+ printf("Writing userprefs: '%s' ", filepath);
+ if (use_template_userpref) {
+ ok_write = BKE_blendfile_userdef_write_app_template(filepath, reports);
+ }
+ else {
+ ok_write = BKE_blendfile_userdef_write(filepath, reports);
+ }
+
+ if (ok_write) {
+ printf("ok\n");
+ }
+ else {
+ printf("fail\n");
+ ok = false;
+ }
+ }
+ else {
+ BKE_report(reports, RPT_ERROR, "Unable to create userpref path");
+ }
+
+ if (use_template_userpref) {
+ if ((cfgdir = BKE_appdir_folder_id_create(BLENDER_USER_CONFIG, U.app_template))) {
+ /* Also save app-template prefs */
+ BLI_path_join(filepath, sizeof(filepath), cfgdir, BLENDER_USERPREF_FILE, NULL);
+
+ printf("Writing userprefs app-template: '%s' ", filepath);
+ if (BKE_blendfile_userdef_write(filepath, reports) != 0) {
+ printf("ok\n");
+ }
+ else {
+ printf("fail\n");
+ ok = false;
+ }
+ }
+ else {
+ BKE_report(reports, RPT_ERROR, "Unable to create app-template userpref path");
+ ok = false;
+ }
+ }
+
+ if (ok) {
+ U.runtime.is_dirty = false;
+ }
+ return ok;
+}
+
WorkspaceConfigFileData *BKE_blendfile_workspace_config_read(const char *filepath,
const void *filebuf,
int filelength,
diff --git a/source/blender/blenkernel/intern/bpath.c b/source/blender/blenkernel/intern/bpath.c
index 6f0c1891b05..fa7af53df2d 100644
--- a/source/blender/blenkernel/intern/bpath.c
+++ b/source/blender/blenkernel/intern/bpath.c
@@ -450,7 +450,10 @@ void BKE_bpath_traverse_id(
Image *ima;
ima = (Image *)id;
if (BKE_image_has_packedfile(ima) == false || (flag & BKE_BPATH_TRAVERSE_SKIP_PACKED) == 0) {
- if (ELEM(ima->source, IMA_SRC_FILE, IMA_SRC_MOVIE, IMA_SRC_SEQUENCE)) {
+ /* Skip empty file paths, these are typically from generated images and
+ * don't make sense to add directories to until the image has been saved
+ * once to give it a meaningful value. */
+ if (ELEM(ima->source, IMA_SRC_FILE, IMA_SRC_MOVIE, IMA_SRC_SEQUENCE) && ima->name[0]) {
if (rewrite_path_fixed(ima->name, visit_cb, absbase, bpath_user_data)) {
if (flag & BKE_BPATH_TRAVERSE_RELOAD_EDITED) {
if (!BKE_image_has_packedfile(ima) &&
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 25399d342e1..a8f38c3c4ce 100644
--- a/source/blender/blenkernel/intern/camera.c
+++ b/source/blender/blenkernel/intern/camera.c
@@ -66,8 +66,9 @@ void BKE_camera_init(Camera *cam)
cam->flag |= CAM_SHOWPASSEPARTOUT;
cam->passepartalpha = 0.5f;
- cam->gpu_dof.fstop = 128.0f;
- cam->gpu_dof.ratio = 1.0f;
+ cam->dof.aperture_fstop = 2.8f;
+ cam->dof.aperture_ratio = 1.0f;
+ cam->dof.focus_distance = 10.0f;
/* stereoscopy 3d */
cam->stereo.interocular_distance = 0.065f;
@@ -134,13 +135,13 @@ float BKE_camera_object_dof_distance(Object *ob)
if (ob->type != OB_CAMERA) {
return 0.0f;
}
- if (cam->dof_ob) {
+ if (cam->dof.focus_object) {
float view_dir[3], dof_dir[3];
normalize_v3_v3(view_dir, ob->obmat[2]);
- sub_v3_v3v3(dof_dir, ob->obmat[3], cam->dof_ob->obmat[3]);
+ sub_v3_v3v3(dof_dir, ob->obmat[3], cam->dof.focus_object->obmat[3]);
return fabsf(dot_v3v3(view_dir, dof_dir));
}
- return cam->dof_distance;
+ return cam->dof.focus_distance;
}
float BKE_camera_sensor_size(int sensor_fit, float sensor_x, float sensor_y)
@@ -1016,18 +1017,6 @@ void BKE_camera_multiview_params(RenderData *rd,
}
}
-void BKE_camera_to_gpu_dof(struct Object *camera, struct GPUFXSettings *r_fx_settings)
-{
- if (camera->type == OB_CAMERA) {
- Camera *cam = camera->data;
- r_fx_settings->dof = &cam->gpu_dof;
- r_fx_settings->dof->focal_length = cam->lens;
- r_fx_settings->dof->sensor = BKE_camera_sensor_size(
- cam->sensor_fit, cam->sensor_x, cam->sensor_y);
- r_fx_settings->dof->focus_distance = BKE_camera_object_dof_distance(camera);
- }
-}
-
CameraBGImage *BKE_camera_background_image_new(Camera *cam)
{
CameraBGImage *bgpic = MEM_callocN(sizeof(CameraBGImage), "Background Image");
diff --git a/source/blender/blenkernel/intern/collection.c b/source/blender/blenkernel/intern/collection.c
index d33d4e344b5..d2ca304e973 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,
@@ -434,8 +434,8 @@ static void collection_object_cache_fill(ListBase *lb, Collection *collection, i
int object_restrict = base->object->restrictflag;
- if (((child_restrict & COLLECTION_RESTRICT_VIEW) == 0) &&
- ((object_restrict & OB_RESTRICT_VIEW) == 0)) {
+ if (((child_restrict & COLLECTION_RESTRICT_VIEWPORT) == 0) &&
+ ((object_restrict & OB_RESTRICT_VIEWPORT) == 0)) {
base->flag |= BASE_ENABLED_VIEWPORT;
}
@@ -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);
}
@@ -966,6 +975,11 @@ static bool collection_find_child_recursive(Collection *parent, Collection *coll
return false;
}
+bool BKE_collection_has_collection(Collection *parent, Collection *collection)
+{
+ return collection_find_child_recursive(parent, collection);
+}
+
static CollectionParent *collection_find_parent(Collection *child, Collection *collection)
{
return BLI_findptr(&child->parents, collection, offsetof(CollectionParent, collection));
diff --git a/source/blender/blenkernel/intern/constraint.c b/source/blender/blenkernel/intern/constraint.c
index 0e29f165992..04789adea2f 100644
--- a/source/blender/blenkernel/intern/constraint.c
+++ b/source/blender/blenkernel/intern/constraint.c
@@ -1882,6 +1882,7 @@ static void sizelike_new_data(void *cdata)
bSizeLikeConstraint *data = (bSizeLikeConstraint *)cdata;
data->flag = SIZELIKE_X | SIZELIKE_Y | SIZELIKE_Z | SIZELIKE_MULTIPLY;
+ data->power = 1.0f;
}
static void sizelike_id_looper(bConstraint *con, ConstraintIDFunc func, void *userdata)
@@ -1929,6 +1930,10 @@ static void sizelike_evaluate(bConstraint *con, bConstraintOb *cob, ListBase *ta
mat4_to_size(size, ct->matrix);
mat4_to_size(obsize, cob->matrix);
+ for (int i = 0; i < 3; i++) {
+ size[i] = powf(size[i], data->power);
+ }
+
if (data->flag & SIZELIKE_OFFSET) {
/* Scale is a multiplicative quantity, so adding it makes no sense.
* However, the additive mode has to stay for backward compatibility. */
@@ -2037,7 +2042,7 @@ static void samevolume_new_data(void *cdata)
{
bSameVolumeConstraint *data = (bSameVolumeConstraint *)cdata;
- data->flag = SAMEVOL_Y;
+ data->free_axis = SAMEVOL_Y;
data->volume = 1.0f;
}
@@ -2046,19 +2051,30 @@ static void samevolume_evaluate(bConstraint *con, bConstraintOb *cob, ListBase *
bSameVolumeConstraint *data = con->data;
float volume = data->volume;
- float fac = 1.0f, total_scale;
+ float fac = 1.0f, total_scale = 1.0f;
float obsize[3];
mat4_to_size(obsize, cob->matrix);
/* calculate normalizing scale factor for non-essential values */
- total_scale = obsize[0] * obsize[1] * obsize[2];
+ switch (data->mode) {
+ case SAMEVOL_STRICT:
+ total_scale = obsize[0] * obsize[1] * obsize[2];
+ break;
+ case SAMEVOL_UNIFORM:
+ total_scale = pow3f(obsize[data->free_axis]);
+ break;
+ case SAMEVOL_SINGLE_AXIS:
+ total_scale = obsize[data->free_axis];
+ break;
+ }
+
if (total_scale != 0) {
fac = sqrtf(volume / total_scale);
}
/* apply scaling factor to the channels not being kept */
- switch (data->flag) {
+ switch (data->free_axis) {
case SAMEVOL_X:
mul_v3_fl(cob->matrix[1], fac);
mul_v3_fl(cob->matrix[2], fac);
@@ -2097,7 +2113,6 @@ static void pycon_free(bConstraint *con)
/* id-properties */
IDP_FreeProperty(data->prop);
- MEM_freeN(data->prop);
/* multiple targets */
BLI_freelistN(&data->targets);
@@ -2406,7 +2421,8 @@ static void armdef_evaluate(bConstraint *con, bConstraintOb *cob, ListBase *targ
copy_v3_v3(input_co, cob->matrix[3]);
}
- /* Process all targets. */
+ /* Process all targets. This can't use ct->matrix, as armdef_get_tarmat is not
+ * called in solve for efficiency because the constraint needs bone data anyway. */
for (bConstraintTarget *ct = targets->first; ct; ct = ct->next) {
if (ct->weight <= 0.0f) {
continue;
@@ -4224,6 +4240,7 @@ static void splineik_new_data(void *cdata)
data->bulge_min = 1.0f;
data->yScaleMode = CONSTRAINT_SPLINEIK_YS_FIT_CURVE;
+ data->flag = CONSTRAINT_SPLINEIK_USE_ORIGINAL_SCALE;
}
static void splineik_id_looper(bConstraint *con, ConstraintIDFunc func, void *userdata)
@@ -5600,6 +5617,11 @@ void BKE_constraint_targets_for_solving_get(struct Depsgraph *depsgraph,
*/
cti->get_constraint_targets(con, targets);
+ /* The Armature constraint doesn't need ct->matrix for evaluate at all. */
+ if (ELEM(cti->type, CONSTRAINT_TYPE_ARMATURE)) {
+ return;
+ }
+
/* set matrices
* - calculate if possible, otherwise just initialize as identity matrix
*/
diff --git a/source/blender/blenkernel/intern/context.c b/source/blender/blenkernel/intern/context.c
index 4383b6a1f9b..9d753319cfa 100644
--- a/source/blender/blenkernel/intern/context.c
+++ b/source/blender/blenkernel/intern/context.c
@@ -399,6 +399,41 @@ 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)) {
+ return 0;
+ }
+
+ if (BLI_listbase_is_empty(&ctx_object_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 +1185,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 +1195,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 +1205,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 +1215,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 +1225,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 +1235,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)
@@ -1312,7 +1354,21 @@ Depsgraph *CTX_data_depsgraph(const bContext *C)
{
Scene *scene = CTX_data_scene(C);
ViewLayer *view_layer = CTX_data_view_layer(C);
- return BKE_scene_get_depsgraph(scene, view_layer, true);
+ Depsgraph *depsgraph = BKE_scene_get_depsgraph(scene, view_layer, true);
+ /* Dependency graph might have been just allocated, and hence it will not be marked.
+ * This confuses redo system due to the lack of flushing changes back to the original data.
+ * In the future we would need to check whether the CTX_wm_window(C) is in editing mode (as an
+ * opposite of playback-preview-only) and set active flag based on that. */
+ DEG_make_active(depsgraph);
+ return depsgraph;
+}
+
+Depsgraph *CTX_data_evaluated_depsgraph(const bContext *C)
+{
+ Depsgraph *depsgraph = CTX_data_depsgraph(C);
+ Main *bmain = CTX_data_main(C);
+ BKE_scene_graph_update_tagged(depsgraph, bmain);
+ return depsgraph;
}
Depsgraph *CTX_data_depsgraph_on_load(const bContext *C)
diff --git a/source/blender/blenkernel/intern/curve.c b/source/blender/blenkernel/intern/curve.c
index dc677449a4c..5945fa4bf33 100644
--- a/source/blender/blenkernel/intern/curve.c
+++ b/source/blender/blenkernel/intern/curve.c
@@ -1737,241 +1737,9 @@ static void forward_diff_bezier_cotangent(const float p0[3],
}
}
-/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
-
-float *BKE_curve_surf_make_orco(Object *ob)
-{
- /* Note: this function is used in convertblender only atm, so
- * suppose nonzero curve's render resolution should always be used */
- Curve *cu = ob->data;
- Nurb *nu;
- int a, b, tot = 0;
- int sizeu, sizev;
- int resolu, resolv;
- float *fp, *coord_array;
-
- /* first calculate the size of the datablock */
- nu = cu->nurb.first;
- while (nu) {
- /* as we want to avoid the seam in a cyclic nurbs
- * texture wrapping, reserve extra orco data space to save these extra needed
- * vertex based UV coordinates for the meridian vertices.
- * Vertices on the 0/2pi boundary are not duplicated inside the displist but later in
- * the renderface/vert construction.
- *
- * See also convertblender.c: init_render_surf()
- */
-
- resolu = cu->resolu_ren ? cu->resolu_ren : nu->resolu;
- resolv = cu->resolv_ren ? cu->resolv_ren : nu->resolv;
-
- sizeu = nu->pntsu * resolu;
- sizev = nu->pntsv * resolv;
- if (nu->flagu & CU_NURB_CYCLIC) {
- sizeu++;
- }
- if (nu->flagv & CU_NURB_CYCLIC) {
- sizev++;
- }
- if (nu->pntsv > 1) {
- tot += sizeu * sizev;
- }
-
- nu = nu->next;
- }
- /* makeNurbfaces wants zeros */
- fp = coord_array = MEM_calloc_arrayN(tot, 3 * sizeof(float), "make_orco");
-
- nu = cu->nurb.first;
- while (nu) {
- resolu = cu->resolu_ren ? cu->resolu_ren : nu->resolu;
- resolv = cu->resolv_ren ? cu->resolv_ren : nu->resolv;
-
- if (nu->pntsv > 1) {
- sizeu = nu->pntsu * resolu;
- sizev = nu->pntsv * resolv;
-
- if (nu->flagu & CU_NURB_CYCLIC) {
- sizeu++;
- }
- if (nu->flagv & CU_NURB_CYCLIC) {
- sizev++;
- }
-
- if (cu->flag & CU_UV_ORCO) {
- for (b = 0; b < sizeu; b++) {
- for (a = 0; a < sizev; a++) {
-
- if (sizev < 2) {
- fp[0] = 0.0f;
- }
- else {
- fp[0] = -1.0f + 2.0f * ((float)a) / (sizev - 1);
- }
-
- if (sizeu < 2) {
- fp[1] = 0.0f;
- }
- else {
- fp[1] = -1.0f + 2.0f * ((float)b) / (sizeu - 1);
- }
-
- fp[2] = 0.0;
-
- fp += 3;
- }
- }
- }
- else {
- int size = (nu->pntsu * resolu) * (nu->pntsv * resolv) * 3 * sizeof(float);
- float *_tdata = MEM_mallocN(size, "temp data");
- float *tdata = _tdata;
-
- BKE_nurb_makeFaces(nu, tdata, 0, resolu, resolv);
-
- for (b = 0; b < sizeu; b++) {
- int use_b = b;
- if (b == sizeu - 1 && (nu->flagu & CU_NURB_CYCLIC)) {
- use_b = false;
- }
-
- for (a = 0; a < sizev; a++) {
- int use_a = a;
- if (a == sizev - 1 && (nu->flagv & CU_NURB_CYCLIC)) {
- use_a = false;
- }
-
- tdata = _tdata + 3 * (use_b * (nu->pntsv * resolv) + use_a);
-
- fp[0] = (tdata[0] - cu->loc[0]) / cu->size[0];
- fp[1] = (tdata[1] - cu->loc[1]) / cu->size[1];
- fp[2] = (tdata[2] - cu->loc[2]) / cu->size[2];
- fp += 3;
- }
- }
-
- MEM_freeN(_tdata);
- }
- }
- nu = nu->next;
- }
-
- return coord_array;
-}
-
-/* NOTE: This routine is tied to the order of vertex
- * built by displist and as passed to the renderer.
- */
-float *BKE_curve_make_orco(Depsgraph *depsgraph, Scene *scene, Object *ob, int *r_numVerts)
-{
- Curve *cu = ob->data;
- DispList *dl;
- int u, v, numVerts;
- float *fp, *coord_array;
- ListBase disp = {NULL, NULL};
-
- BKE_displist_make_curveTypes_forOrco(depsgraph, scene, ob, &disp, NULL);
-
- numVerts = 0;
- for (dl = disp.first; dl; dl = dl->next) {
- if (dl->type == DL_INDEX3) {
- numVerts += dl->nr;
- }
- else if (dl->type == DL_SURF) {
- /* convertblender.c uses the Surface code for creating renderfaces when cyclic U only
- * (closed circle beveling)
- */
- if (dl->flag & DL_CYCL_U) {
- if (dl->flag & DL_CYCL_V) {
- numVerts += (dl->parts + 1) * (dl->nr + 1);
- }
- else {
- numVerts += dl->parts * (dl->nr + 1);
- }
- }
- else if (dl->flag & DL_CYCL_V) {
- numVerts += (dl->parts + 1) * dl->nr;
- }
- else {
- numVerts += dl->parts * dl->nr;
- }
- }
- }
-
- if (r_numVerts) {
- *r_numVerts = numVerts;
- }
-
- fp = coord_array = MEM_malloc_arrayN(numVerts, 3 * sizeof(float), "cu_orco");
- for (dl = disp.first; dl; dl = dl->next) {
- if (dl->type == DL_INDEX3) {
- for (u = 0; u < dl->nr; u++, fp += 3) {
- if (cu->flag & CU_UV_ORCO) {
- fp[0] = 2.0f * u / (dl->nr - 1) - 1.0f;
- fp[1] = 0.0;
- fp[2] = 0.0;
- }
- else {
- copy_v3_v3(fp, &dl->verts[u * 3]);
-
- fp[0] = (fp[0] - cu->loc[0]) / cu->size[0];
- fp[1] = (fp[1] - cu->loc[1]) / cu->size[1];
- fp[2] = (fp[2] - cu->loc[2]) / cu->size[2];
- }
- }
- }
- else if (dl->type == DL_SURF) {
- int sizeu = dl->nr, sizev = dl->parts;
-
- /* exception as handled in convertblender.c too */
- if (dl->flag & DL_CYCL_U) {
- sizeu++;
- if (dl->flag & DL_CYCL_V) {
- sizev++;
- }
- }
- else if (dl->flag & DL_CYCL_V) {
- sizev++;
- }
-
- for (u = 0; u < sizev; u++) {
- for (v = 0; v < sizeu; v++, fp += 3) {
- if (cu->flag & CU_UV_ORCO) {
- fp[0] = 2.0f * u / (sizev - 1) - 1.0f;
- fp[1] = 2.0f * v / (sizeu - 1) - 1.0f;
- fp[2] = 0.0;
- }
- else {
- const float *vert;
- int realv = v % dl->nr;
- int realu = u % dl->parts;
-
- vert = dl->verts + 3 * (dl->nr * realu + realv);
- copy_v3_v3(fp, vert);
-
- fp[0] = (fp[0] - cu->loc[0]) / cu->size[0];
- fp[1] = (fp[1] - cu->loc[1]) / cu->size[1];
- fp[2] = (fp[2] - cu->loc[2]) / cu->size[2];
- }
- }
- }
- }
- }
-
- BKE_displist_free(&disp);
-
- return coord_array;
-}
-
/* ***************** BEVEL ****************** */
-void BKE_curve_bevel_make(Depsgraph *depsgraph,
- Scene *scene,
- Object *ob,
- ListBase *disp,
- const bool for_render,
- const bool use_render_resolution,
- LinkNode *ob_cyclic_list)
+void BKE_curve_bevel_make(Object *ob, ListBase *disp)
{
DispList *dl, *dlnew;
Curve *bevcu, *cu;
@@ -1995,26 +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,
- use_render_resolution,
- &(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 {
@@ -4980,7 +4729,7 @@ void BKE_curve_nurbs_keyVertexTilts_apply(ListBase *lb, float *key)
}
}
-bool BKE_nurb_check_valid_u(struct Nurb *nu)
+bool BKE_nurb_check_valid_u(const Nurb *nu)
{
if (nu->pntsu <= 1) {
return false;
@@ -5007,7 +4756,7 @@ bool BKE_nurb_check_valid_u(struct Nurb *nu)
}
return true;
}
-bool BKE_nurb_check_valid_v(struct Nurb *nu)
+bool BKE_nurb_check_valid_v(const Nurb *nu)
{
if (nu->pntsv <= 1) {
return false;
@@ -5035,7 +4784,7 @@ bool BKE_nurb_check_valid_v(struct Nurb *nu)
return true;
}
-bool BKE_nurb_check_valid_uv(struct Nurb *nu)
+bool BKE_nurb_check_valid_uv(const Nurb *nu)
{
if (!BKE_nurb_check_valid_u(nu)) {
return false;
diff --git a/source/blender/blenkernel/intern/data_transfer.c b/source/blender/blenkernel/intern/data_transfer.c
index 5d9ba1bcdc7..98c6d519d17 100644
--- a/source/blender/blenkernel/intern/data_transfer.c
+++ b/source/blender/blenkernel/intern/data_transfer.c
@@ -585,7 +585,7 @@ static bool data_transfer_layersmapping_cdlayers_multisrc_to_dst(ListBase *r_map
/* Find last source actually used! */
while (idx_src-- && !use_layers_src[idx_src]) {
- ;
+ /* pass */
}
idx_src++;
diff --git a/source/blender/blenkernel/intern/deform.c b/source/blender/blenkernel/intern/deform.c
index e83e9560b02..a964cab3fa5 100644
--- a/source/blender/blenkernel/intern/deform.c
+++ b/source/blender/blenkernel/intern/deform.c
@@ -1124,7 +1124,7 @@ static bool data_transfer_layersmapping_vgroups_multisrc_to_dst(ListBase *r_map,
/* Find last source actually used! */
idx_src = num_layers_src;
while (idx_src-- && !use_layers_src[idx_src]) {
- ;
+ /* pass */
}
idx_src++;
diff --git a/source/blender/blenkernel/intern/displist.c b/source/blender/blenkernel/intern/displist.c
index c228595b6e8..c8d6f7ae313 100644
--- a/source/blender/blenkernel/intern/displist.c
+++ b/source/blender/blenkernel/intern/displist.c
@@ -315,8 +315,7 @@ bool BKE_displist_surfindex_get(DispList *dl, int a, int *b, int *p1, int *p2, i
static void curve_to_displist(Curve *cu,
ListBase *nubase,
ListBase *dispbase,
- const bool for_render,
- const bool use_render_resolution)
+ const bool for_render)
{
Nurb *nu;
DispList *dl;
@@ -329,7 +328,7 @@ static void curve_to_displist(Curve *cu,
nu = nubase->first;
while (nu) {
if (nu->hide == 0 || editmode == false) {
- if (use_render_resolution && cu->resolu_ren != 0) {
+ if (for_render && cu->resolu_ren != 0) {
resolu = cu->resolu_ren;
}
else {
@@ -724,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) {
@@ -801,7 +800,7 @@ void BKE_displist_make_mball_forRender(Depsgraph *depsgraph,
static ModifierData *curve_get_tessellate_point(Scene *scene,
Object *ob,
- const bool use_render_resolution,
+ const bool for_render,
const bool editmode)
{
VirtualModifierData virtualModifierData;
@@ -809,7 +808,7 @@ static ModifierData *curve_get_tessellate_point(Scene *scene,
ModifierData *pretessellatePoint;
int required_mode;
- if (use_render_resolution) {
+ if (for_render) {
required_mode = eModifierMode_Render;
}
else {
@@ -848,12 +847,8 @@ static ModifierData *curve_get_tessellate_point(Scene *scene,
return pretessellatePoint;
}
-static void curve_calc_modifiers_pre(Depsgraph *depsgraph,
- Scene *scene,
- Object *ob,
- ListBase *nurb,
- const bool for_render,
- const bool use_render_resolution)
+static void curve_calc_modifiers_pre(
+ Depsgraph *depsgraph, Scene *scene, Object *ob, ListBase *nurb, const bool for_render)
{
VirtualModifierData virtualModifierData;
ModifierData *md = modifiers_getVirtualModifierList(ob, &virtualModifierData);
@@ -871,7 +866,7 @@ static void curve_calc_modifiers_pre(Depsgraph *depsgraph,
if (editmode) {
app_flag |= MOD_APPLY_USECACHE;
}
- if (use_render_resolution) {
+ if (for_render) {
app_flag |= MOD_APPLY_RENDER;
required_mode = eModifierMode_Render;
}
@@ -881,7 +876,7 @@ static void curve_calc_modifiers_pre(Depsgraph *depsgraph,
const ModifierEvalContext mectx = {depsgraph, ob, app_flag};
- pretessellatePoint = curve_get_tessellate_point(scene, ob, use_render_resolution, editmode);
+ pretessellatePoint = curve_get_tessellate_point(scene, ob, for_render, editmode);
if (editmode) {
required_mode |= eModifierMode_Editmode;
@@ -979,8 +974,7 @@ static void curve_calc_modifiers_post(Depsgraph *depsgraph,
ListBase *nurb,
ListBase *dispbase,
Mesh **r_final,
- const bool for_render,
- const bool use_render_resolution)
+ const bool for_render)
{
VirtualModifierData virtualModifierData;
ModifierData *md = modifiers_getVirtualModifierList(ob, &virtualModifierData);
@@ -993,7 +987,7 @@ static void curve_calc_modifiers_post(Depsgraph *depsgraph,
int useCache = !for_render;
ModifierApplyFlag app_flag = 0;
- if (use_render_resolution) {
+ if (for_render) {
app_flag |= MOD_APPLY_RENDER;
required_mode = eModifierMode_Render;
}
@@ -1006,7 +1000,7 @@ static void curve_calc_modifiers_post(Depsgraph *depsgraph,
const ModifierEvalContext mectx_apply = {
depsgraph, ob, useCache ? app_flag | MOD_APPLY_USECACHE : app_flag};
- pretessellatePoint = curve_get_tessellate_point(scene, ob, use_render_resolution, editmode);
+ pretessellatePoint = curve_get_tessellate_point(scene, ob, for_render, editmode);
if (editmode) {
required_mode |= eModifierMode_Editmode;
@@ -1199,144 +1193,13 @@ static void displist_surf_indices(DispList *dl)
}
}
-/* XXX2.8(Sybren): unused function; impossible to test after porting to Mesh */
-#ifdef WITH_DERIVEDMESH_DEPRECATED_FUNCS
-static DerivedMesh *create_orco_dm(Depsgraph *depsgraph, Scene *scene, Object *ob)
-{
- DerivedMesh *dm;
- ListBase disp = {NULL, NULL};
-
- /* OrcoDM should be created from underformed disp lists */
- BKE_displist_make_curveTypes_forOrco(depsgraph, scene, ob, &disp);
- dm = CDDM_from_curve_displist(ob, &disp);
-
- BKE_displist_free(&disp);
-
- return dm;
-}
-
-static void add_orco_dm(Object *ob, DerivedMesh *dm, DerivedMesh *orcodm)
-{
- float(*orco)[3], (*layerorco)[3];
- int totvert, a;
- Curve *cu = ob->data;
-
- totvert = dm->getNumVerts(dm);
-
- orco = MEM_callocN(sizeof(float) * 3 * totvert, "dm orco");
-
- if (orcodm->getNumVerts(orcodm) == totvert) {
- orcodm->getVertCos(orcodm, orco);
- }
- else {
- dm->getVertCos(dm, orco);
- }
-
- for (a = 0; a < totvert; a++) {
- float *co = orco[a];
- co[0] = (co[0] - cu->loc[0]) / cu->size[0];
- co[1] = (co[1] - cu->loc[1]) / cu->size[1];
- co[2] = (co[2] - cu->loc[2]) / cu->size[2];
- }
-
- if ((layerorco = DM_get_vert_data_layer(dm, CD_ORCO))) {
- memcpy(layerorco, orco, sizeof(float) * totvert);
- MEM_freeN(orco);
- }
- else {
- DM_add_vert_layer(dm, CD_ORCO, CD_ASSIGN, orco);
- }
-}
-#endif
-
-/* XXX2.8(Sybren): unused function; impossible to test after porting to Mesh */
-#ifdef WITH_DERIVEDMESH_DEPRECATED_FUNCS
-static void curve_calc_orcodm(Depsgraph *depsgraph,
- Scene *scene,
- Object *ob,
- DerivedMesh *dm_final,
- const bool for_render,
- const bool use_render_resolution)
-{
- /* this function represents logic of mesh's orcodm calculation
- * for displist-based objects
- */
- VirtualModifierData virtualModifierData;
- ModifierData *md = modifiers_getVirtualModifierList(ob, &virtualModifierData);
- ModifierData *pretessellatePoint;
- Curve *cu = ob->data;
- int required_mode;
- const bool editmode = (!for_render && (cu->editnurb || cu->editfont));
- DerivedMesh *ndm, *orcodm = NULL;
- ModifierApplyFlag app_flag = MOD_APPLY_ORCO;
-
- if (use_render_resolution) {
- app_flag |= MOD_APPLY_RENDER;
- required_mode = eModifierMode_Render;
- }
- else {
- required_mode = eModifierMode_Realtime;
- }
-
- const ModifierEvalContext mectx = {depsgraph, ob, app_flag};
-
- pretessellatePoint = curve_get_tessellate_point(scene, ob, use_render_resolution, editmode);
-
- if (editmode) {
- required_mode |= eModifierMode_Editmode;
- }
-
- if (pretessellatePoint) {
- md = pretessellatePoint->next;
- }
-
- /* If modifiers are disabled, we wouldn't be here because
- * this function is only called if there're enabled constructive
- * modifiers applied on the curve.
- *
- * This means we can create ORCO DM in advance and assume it's
- * never NULL.
- */
- orcodm = create_orco_dm(depsgraph, scene, ob);
-
- for (; md; md = md->next) {
- const ModifierTypeInfo *mti = modifierType_getInfo(md->type);
-
- md->scene = scene;
-
- if (!modifier_isEnabled(scene, md, required_mode)) {
- continue;
- }
- if (mti->type != eModifierTypeType_Constructive) {
- continue;
- }
-
- ndm = modwrap_applyModifier(md, &mectx, orcodm);
-
- if (ndm) {
- /* if the modifier returned a new dm, release the old one */
- if (orcodm && orcodm != ndm) {
- orcodm->release(orcodm);
- }
- orcodm = ndm;
- }
- }
-
- /* add an orco layer if needed */
- add_orco_dm(ob, dm_final, orcodm);
-
- orcodm->release(orcodm);
-}
-#endif
-
void BKE_displist_make_surf(Depsgraph *depsgraph,
Scene *scene,
Object *ob,
ListBase *dispbase,
Mesh **r_final,
const bool for_render,
- const bool for_orco,
- const bool use_render_resolution)
+ const bool for_orco)
{
ListBase nubase = {NULL, NULL};
Nurb *nu;
@@ -1353,14 +1216,14 @@ void BKE_displist_make_surf(Depsgraph *depsgraph,
}
if (!for_orco) {
- curve_calc_modifiers_pre(depsgraph, scene, ob, &nubase, for_render, use_render_resolution);
+ curve_calc_modifiers_pre(depsgraph, scene, ob, &nubase, for_render);
}
for (nu = nubase.first; nu; nu = nu->next) {
if ((for_render || nu->hide == 0) && BKE_nurb_check_valid_uv(nu)) {
int resolu = nu->resolu, resolv = nu->resolv;
- if (use_render_resolution) {
+ if (for_render) {
if (cu->resolu_ren) {
resolu = cu->resolu_ren;
}
@@ -1431,8 +1294,7 @@ void BKE_displist_make_surf(Depsgraph *depsgraph,
if (!for_orco) {
BKE_nurbList_duplicate(&ob->runtime.curve_cache->deformed_nurbs, &nubase);
- curve_calc_modifiers_post(
- depsgraph, scene, ob, &nubase, dispbase, r_final, for_render, use_render_resolution);
+ curve_calc_modifiers_post(depsgraph, scene, ob, &nubase, dispbase, r_final, for_render);
}
BKE_nurbList_free(&nubase);
@@ -1665,8 +1527,6 @@ static void do_makeDispListCurveTypes(Depsgraph *depsgraph,
ListBase *dispbase,
const bool for_render,
const bool for_orco,
- const bool use_render_resolution,
- LinkNode *ob_cyclic_list,
Mesh **r_final)
{
Curve *cu = ob->data;
@@ -1677,8 +1537,7 @@ static void do_makeDispListCurveTypes(Depsgraph *depsgraph,
}
if (ob->type == OB_SURF) {
- BKE_displist_make_surf(
- depsgraph, scene, ob, dispbase, r_final, for_render, for_orco, use_render_resolution);
+ BKE_displist_make_surf(depsgraph, scene, ob, dispbase, r_final, for_render, for_orco);
}
else if (ELEM(ob->type, OB_CURVE, OB_FONT)) {
ListBase dlbev;
@@ -1705,18 +1564,17 @@ static void do_makeDispListCurveTypes(Depsgraph *depsgraph,
}
if (!for_orco) {
- curve_calc_modifiers_pre(depsgraph, scene, ob, &nubase, for_render, use_render_resolution);
+ curve_calc_modifiers_pre(depsgraph, scene, ob, &nubase, for_render);
}
- BKE_curve_bevelList_make(ob, &nubase, use_render_resolution);
+ 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, use_render_resolution, ob_cyclic_list);
+ BKE_curve_bevel_make(ob, &dlbev);
/* no bevel or extrude, and no width correction? */
if (!dlbev.first && cu->width == 1.0f) {
- curve_to_displist(cu, &nubase, dispbase, for_render, use_render_resolution);
+ curve_to_displist(cu, &nubase, dispbase, for_render);
}
else {
float widfac = cu->width - 1.0f;
@@ -1916,8 +1774,7 @@ static void do_makeDispListCurveTypes(Depsgraph *depsgraph,
if (!for_orco) {
BKE_nurbList_duplicate(&ob->runtime.curve_cache->deformed_nurbs, &nubase);
- curve_calc_modifiers_post(
- depsgraph, scene, ob, &nubase, dispbase, r_final, for_render, use_render_resolution);
+ curve_calc_modifiers_post(depsgraph, scene, ob, &nubase, dispbase, r_final, for_render);
}
if (cu->flag & CU_DEFORM_FILL && !ob->runtime.mesh_eval) {
@@ -1928,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;
@@ -1952,15 +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,
- false,
- 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);
}
@@ -1970,33 +1816,13 @@ void BKE_displist_make_curveTypes_forRender(Depsgraph *depsgraph,
Object *ob,
ListBase *dispbase,
Mesh **r_final,
- const bool for_orco,
- const bool use_render_resolution,
- LinkNode *ob_cyclic_list)
-{
- 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,
- use_render_resolution,
- ob_cyclic_list,
- r_final);
-}
-
-void BKE_displist_make_curveTypes_forOrco(
- Depsgraph *depsgraph, Scene *scene, Object *ob, ListBase *dispbase, 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, 1, 1, 1, ob_cyclic_list, NULL);
+ 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/dynamicpaint.c b/source/blender/blenkernel/intern/dynamicpaint.c
index 0ee32af336d..b5242d00ee0 100644
--- a/source/blender/blenkernel/intern/dynamicpaint.c
+++ b/source/blender/blenkernel/intern/dynamicpaint.c
@@ -2066,7 +2066,7 @@ static Mesh *dynamicPaint_Modifier_apply(DynamicPaintModifierData *pmd, Object *
}
if (update_normals) {
- // result->dirty |= DM_DIRTY_NORMALS;
+ result->runtime.cd_dirty_vert |= CD_MASK_NORMAL;
}
}
/* make a copy of mesh to use as brush data */
@@ -5393,7 +5393,7 @@ static void dynamic_paint_effect_drip_cb(void *__restrict userdata,
const uint8_t epointlock_bitmask = 1 << (n_trgt & 7); /* 7 == 0b111 */
while (atomic_fetch_and_or_uint8(&point_locks[epointlock_idx], epointlock_bitmask) &
epointlock_bitmask) {
- ;
+ /* pass */
}
PaintPoint *ePoint = &((PaintPoint *)sData->type_data)[n_trgt];
@@ -5440,7 +5440,7 @@ static void dynamic_paint_effect_drip_cb(void *__restrict userdata,
const uint8_t ppointlock_bitmask = 1 << (index & 7); /* 7 == 0b111 */
while (atomic_fetch_and_or_uint8(&point_locks[ppointlock_idx], ppointlock_bitmask) &
ppointlock_bitmask) {
- ;
+ /* pass */
}
pPoint->wetness -= ppoint_wetness_diff;
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/fcurve.c b/source/blender/blenkernel/intern/fcurve.c
index 8c95e4c7ff3..3bca77c5b51 100644
--- a/source/blender/blenkernel/intern/fcurve.c
+++ b/source/blender/blenkernel/intern/fcurve.c
@@ -1707,6 +1707,11 @@ static float dvar_eval_transChan(ChannelDriver *driver, DriverVar *dvar)
/* not valid channel */
return 0.0f;
}
+ else if (dtar->transChan == DTAR_TRANSCHAN_SCALE_AVG) {
+ /* Cubic root of the change in volume, equal to the geometric mean
+ * of scale over all three axes unless the matrix includes shear. */
+ return cbrtf(mat4_to_volume_scale(mat));
+ }
else if (dtar->transChan >= DTAR_TRANSCHAN_SCALEX) {
/* Extract scale, and choose the right axis,
* inline 'mat4_to_size'. */
@@ -3065,14 +3070,20 @@ float evaluate_fcurve_driver(PathResolvedRNA *anim_rna,
return evaluate_fcurve_ex(fcu, evaltime, cvalue);
}
+/* Checks if the curve has valid keys, drivers or modifiers that produce an actual curve. */
+bool BKE_fcurve_is_empty(FCurve *fcu)
+{
+ return (fcu->totvert == 0) && (fcu->driver == NULL) &&
+ !list_has_suitable_fmodifier(&fcu->modifiers, 0, FMI_TYPE_GENERATE_CURVE);
+}
+
/* Calculate the value of the given F-Curve at the given frame, and set its curval */
float calculate_fcurve(PathResolvedRNA *anim_rna, FCurve *fcu, float evaltime)
{
/* only calculate + set curval (overriding the existing value) if curve has
* any data which warrants this...
*/
- if ((fcu->totvert) || (fcu->driver && !(fcu->driver->flag & DRIVER_FLAG_INVALID)) ||
- list_has_suitable_fmodifier(&fcu->modifiers, 0, FMI_TYPE_GENERATE_CURVE)) {
+ if (!BKE_fcurve_is_empty(fcu)) {
/* calculate and set curval (evaluates driver too if necessary) */
float curval;
if (fcu->driver) {
diff --git a/source/blender/blenkernel/intern/fmodifier.c b/source/blender/blenkernel/intern/fmodifier.c
index c6188642e41..794d07203af 100644
--- a/source/blender/blenkernel/intern/fmodifier.c
+++ b/source/blender/blenkernel/intern/fmodifier.c
@@ -867,7 +867,6 @@ static void fcm_python_free(FModifier *fcm)
/* id-properties */
IDP_FreeProperty(data->prop);
- MEM_freeN(data->prop);
}
static void fcm_python_new_data(void *mdata)
diff --git a/source/blender/blenkernel/intern/gpencil.c b/source/blender/blenkernel/intern/gpencil.c
index c82b2c377fa..439005ca1b4 100644
--- a/source/blender/blenkernel/intern/gpencil.c
+++ b/source/blender/blenkernel/intern/gpencil.c
@@ -1109,7 +1109,8 @@ Material *BKE_gpencil_object_material_new(Main *bmain, Object *ob, const char *n
/* Returns the material for a brush with respect to its pinned state. */
Material *BKE_gpencil_object_material_get_from_brush(Object *ob, Brush *brush)
{
- if ((brush) && (brush->gpencil_settings->flag & GP_BRUSH_MATERIAL_PINNED)) {
+ if ((brush) && (brush->gpencil_settings) &&
+ (brush->gpencil_settings->flag & GP_BRUSH_MATERIAL_PINNED)) {
Material *ma = BKE_gpencil_brush_material_get(brush);
return ma;
}
diff --git a/source/blender/blenkernel/intern/idprop.c b/source/blender/blenkernel/intern/idprop.c
index 39e72d7e3a8..016da52252a 100644
--- a/source/blender/blenkernel/intern/idprop.c
+++ b/source/blender/blenkernel/intern/idprop.c
@@ -121,7 +121,7 @@ static void IDP_FreeIDPArray(IDProperty *prop, const bool do_id_user)
BLI_assert(prop->type == IDP_IDPARRAY);
for (i = 0; i < prop->len; i++) {
- IDP_FreeProperty_ex(GETPROP(prop, i), do_id_user);
+ IDP_FreePropertyContent_ex(GETPROP(prop, i), do_id_user);
}
if (prop->data.pointer) {
@@ -142,7 +142,7 @@ void IDP_SetIndexArray(IDProperty *prop, int index, IDProperty *item)
old = GETPROP(prop, index);
if (item != old) {
- IDP_FreeProperty(old);
+ IDP_FreePropertyContent(old);
memcpy(old, item, sizeof(IDProperty));
}
@@ -175,7 +175,7 @@ void IDP_ResizeIDPArray(IDProperty *prop, int newlen)
int i;
for (i = newlen; i < prop->len; i++) {
- IDP_FreeProperty(GETPROP(prop, i));
+ IDP_FreePropertyContent(GETPROP(prop, i));
}
prop->len = newlen;
@@ -192,7 +192,7 @@ void IDP_ResizeIDPArray(IDProperty *prop, int newlen)
/* newlen is smaller */
int i;
for (i = newlen; i < prop->len; i++) {
- IDP_FreeProperty(GETPROP(prop, i));
+ IDP_FreePropertyContent(GETPROP(prop, i));
}
}
@@ -236,7 +236,6 @@ static void idp_resize_group_array(IDProperty *prop, int newlen, void *newarr)
for (a = newlen; a < prop->len; a++) {
IDP_FreeProperty(array[a]);
- MEM_freeN(array[a]);
}
}
}
@@ -513,7 +512,6 @@ void IDP_SyncGroupValues(IDProperty *dest, const IDProperty *src)
default: {
BLI_insertlinkreplace(&dest->data.group, other, IDP_CopyProperty(prop));
IDP_FreeProperty(other);
- MEM_freeN(other);
break;
}
}
@@ -535,7 +533,6 @@ void IDP_SyncGroupTypes(IDProperty *dst, const IDProperty *src, const bool do_ar
(prop_src->len != prop_dst->len))) {
BLI_insertlinkreplace(&dst->data.group, prop_dst, IDP_CopyProperty(prop_src));
IDP_FreeProperty(prop_dst);
- MEM_freeN(prop_dst);
}
else if (prop_dst->type == IDP_GROUP) {
IDP_SyncGroupTypes(prop_dst, prop_src, do_arraylen);
@@ -562,7 +559,6 @@ void IDP_ReplaceGroupInGroup(IDProperty *dest, const IDProperty *src)
if (STREQ(loop->name, prop->name)) {
BLI_insertlinkreplace(&dest->data.group, loop, IDP_CopyProperty(prop));
IDP_FreeProperty(loop);
- MEM_freeN(loop);
break;
}
}
@@ -588,7 +584,6 @@ void IDP_ReplaceInGroup_ex(IDProperty *group, IDProperty *prop, IDProperty *prop
if (prop_exist != NULL) {
BLI_insertlinkreplace(&group->data.group, prop_exist, prop);
IDP_FreeProperty(prop_exist);
- MEM_freeN(prop_exist);
}
else {
group->len++;
@@ -668,12 +663,6 @@ void IDP_MergeGroup(IDProperty *dest, const IDProperty *src, const bool do_overw
* (the function that adds new properties to groups, #IDP_AddToGroup,
* returns false if a property can't be added to the group, and true if it can)
* and free the property.
- *
- * Currently the code to free ID properties is designed to leave the actual struct
- * you pass it un-freed, this is needed for how the system works. This means
- * to free an ID property, you first call #IDP_FreeProperty then #MEM_freeN the struct.
- * In the future this will just be #IDP_FreeProperty and the code will
- * be reorganized to work properly.
*/
bool IDP_AddToGroup(IDProperty *group, IDProperty *prop)
{
@@ -709,8 +698,7 @@ bool IDP_InsertToGroup(IDProperty *group, IDProperty *previous, IDProperty *pnew
* \note this does not free the property!!
*
* To free the property, you have to do:
- * IDP_FreeProperty(prop); //free all subdata
- * MEM_freeN(prop); //free property struct itself
+ * IDP_FreeProperty(prop);
*/
void IDP_RemoveFromGroup(IDProperty *group, IDProperty *prop)
{
@@ -727,7 +715,6 @@ void IDP_FreeFromGroup(IDProperty *group, IDProperty *prop)
{
IDP_RemoveFromGroup(group, prop);
IDP_FreeProperty(prop);
- MEM_freeN(prop);
}
IDProperty *IDP_GetPropertyFromGroup(IDProperty *prop, const char *name)
@@ -753,7 +740,7 @@ static void IDP_FreeGroup(IDProperty *prop, const bool do_id_user)
BLI_assert(prop->type == IDP_GROUP);
for (loop = prop->data.group.first; loop; loop = loop->next) {
- IDP_FreeProperty_ex(loop, do_id_user);
+ IDP_FreePropertyContent_ex(loop, do_id_user);
}
BLI_freelistN(&prop->data.group);
}
@@ -1070,7 +1057,7 @@ IDProperty *IDP_New(const char type, const IDPropertyTemplate *val, const char *
* \note This will free allocated data, all child properties of arrays and groups, and unlink IDs!
* But it does not free the actual IDProperty struct itself.
*/
-void IDP_FreeProperty_ex(IDProperty *prop, const bool do_id_user)
+void IDP_FreePropertyContent_ex(IDProperty *prop, const bool do_id_user)
{
switch (prop->type) {
case IDP_ARRAY:
@@ -1093,14 +1080,20 @@ void IDP_FreeProperty_ex(IDProperty *prop, const bool do_id_user)
}
}
+void IDP_FreePropertyContent(IDProperty *prop)
+{
+ IDP_FreePropertyContent_ex(prop, true);
+}
+
void IDP_FreeProperty(IDProperty *prop)
{
- IDP_FreeProperty_ex(prop, true);
+ IDP_FreePropertyContent(prop);
+ MEM_freeN(prop);
}
void IDP_ClearProperty(IDProperty *prop)
{
- IDP_FreeProperty(prop);
+ IDP_FreePropertyContent(prop);
prop->data.pointer = NULL;
prop->len = prop->totallen = 0;
}
diff --git a/source/blender/blenkernel/intern/image.c b/source/blender/blenkernel/intern/image.c
index f23c58befdf..9960994400f 100644
--- a/source/blender/blenkernel/intern/image.c
+++ b/source/blender/blenkernel/intern/image.c
@@ -470,7 +470,7 @@ bool BKE_image_scale(Image *image, int width, int height)
if (ibuf) {
IMB_scaleImBuf(ibuf, width, height);
- ibuf->userflags |= IB_BITMAPDIRTY;
+ BKE_image_mark_dirty(image, ibuf);
}
BKE_image_release_ibuf(image, ibuf, lock);
@@ -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;
}
@@ -646,7 +652,6 @@ static ImBuf *add_ibuf_size(unsigned int width,
}
STRNCPY(ibuf->name, name);
- ibuf->userflags |= IB_BITMAPDIRTY;
switch (gen_type) {
case IMA_GENTYPE_GRID:
@@ -3593,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 */
@@ -5081,12 +5088,20 @@ bool BKE_image_has_packedfile(Image *ima)
return (BLI_listbase_is_empty(&ima->packedfiles) == false);
}
+bool BKE_image_has_filepath(Image *ima)
+{
+ /* This could be improved to detect cases like //../../, currently path
+ * remapping empty file paths empty. */
+ return ima->name[0] != '\0';
+}
+
/* Checks the image buffer changes with time (not keyframed values). */
bool BKE_image_is_animated(Image *image)
{
return ELEM(image->source, IMA_SRC_MOVIE, IMA_SRC_SEQUENCE);
}
+/* Image modifications */
bool BKE_image_is_dirty(Image *image)
{
bool is_dirty = false;
@@ -5110,6 +5125,11 @@ bool BKE_image_is_dirty(Image *image)
return is_dirty;
}
+void BKE_image_mark_dirty(Image *UNUSED(image), ImBuf *ibuf)
+{
+ ibuf->userflags |= IB_BITMAPDIRTY;
+}
+
void BKE_image_file_format_set(Image *image, int ftype, const ImbFormatOptions *options)
{
BLI_spin_lock(&image_spin);
diff --git a/source/blender/blenkernel/intern/layer.c b/source/blender/blenkernel/intern/layer.c
index fc349e62809..60c00160e6d 100644
--- a/source/blender/blenkernel/intern/layer.c
+++ b/source/blender/blenkernel/intern/layer.c
@@ -235,7 +235,6 @@ void BKE_view_layer_free_ex(ViewLayer *view_layer, const bool do_id_user)
if (view_layer->id_properties) {
IDP_FreeProperty(view_layer->id_properties);
- MEM_freeN(view_layer->id_properties);
}
MEM_SAFE_FREE(view_layer->object_bases_array);
@@ -693,8 +692,8 @@ static short layer_collection_sync(ViewLayer *view_layer,
lc->runtime_flag = child_runtime_flag;
}
- if (((child_restrict & COLLECTION_RESTRICT_VIEW) == 0) &&
- ((child_layer_restrict & LAYER_COLLECTION_RESTRICT_VIEW) == 0)) {
+ if (((child_restrict & COLLECTION_RESTRICT_VIEWPORT) == 0) &&
+ ((child_layer_restrict & LAYER_COLLECTION_HIDE) == 0)) {
lc->runtime_flag |= LAYER_COLLECTION_VISIBLE;
}
@@ -723,9 +722,9 @@ static short layer_collection_sync(ViewLayer *view_layer,
BLI_addtail(new_object_bases, base);
}
- if ((child_restrict & COLLECTION_RESTRICT_VIEW) == 0) {
+ if ((child_restrict & COLLECTION_RESTRICT_VIEWPORT) == 0) {
base->flag_from_collection |= BASE_ENABLED_VIEWPORT;
- if ((child_layer_restrict & LAYER_COLLECTION_RESTRICT_VIEW) == 0) {
+ if ((child_layer_restrict & LAYER_COLLECTION_HIDE) == 0) {
base->flag_from_collection |= BASE_VISIBLE;
if (((child_restrict & COLLECTION_RESTRICT_SELECT) == 0)) {
base->flag_from_collection |= BASE_SELECTABLE;
@@ -1014,8 +1013,8 @@ bool BKE_layer_collection_isolate(Scene *scene,
bool hide_it = extend && (lc->runtime_flag & LAYER_COLLECTION_VISIBLE);
if ((!ID_IS_LINKED(lc->collection) && !hide_it)) {
- if (lc->collection->flag & COLLECTION_RESTRICT_VIEW) {
- lc->collection->flag &= ~COLLECTION_RESTRICT_VIEW;
+ if (lc->collection->flag & COLLECTION_RESTRICT_VIEWPORT) {
+ lc->collection->flag &= ~COLLECTION_RESTRICT_VIEWPORT;
depsgraph_need_update = true;
}
}
@@ -1024,13 +1023,13 @@ bool BKE_layer_collection_isolate(Scene *scene,
/* Hide all collections . */
for (LayerCollection *lc_iter = lc_master->layer_collections.first; lc_iter;
lc_iter = lc_iter->next) {
- layer_collection_flag_set_recursive(lc_iter, LAYER_COLLECTION_RESTRICT_VIEW);
+ layer_collection_flag_set_recursive(lc_iter, LAYER_COLLECTION_HIDE);
}
}
/* Make all the direct parents visible. */
if (hide_it) {
- lc->flag |= LAYER_COLLECTION_RESTRICT_VIEW;
+ lc->flag |= LAYER_COLLECTION_HIDE;
}
else {
LayerCollection *lc_parent = lc;
@@ -1044,13 +1043,13 @@ bool BKE_layer_collection_isolate(Scene *scene,
while (lc_parent != lc) {
if (!ID_IS_LINKED(lc_parent->collection)) {
- if (lc_parent->collection->flag & COLLECTION_RESTRICT_VIEW) {
- lc_parent->collection->flag &= ~COLLECTION_RESTRICT_VIEW;
+ if (lc_parent->collection->flag & COLLECTION_RESTRICT_VIEWPORT) {
+ lc_parent->collection->flag &= ~COLLECTION_RESTRICT_VIEWPORT;
depsgraph_need_update = true;
}
}
- lc_parent->flag &= ~LAYER_COLLECTION_RESTRICT_VIEW;
+ lc_parent->flag &= ~LAYER_COLLECTION_HIDE;
for (LayerCollection *lc_iter = lc_parent->layer_collections.first; lc_iter;
lc_iter = lc_iter->next) {
@@ -1062,7 +1061,7 @@ bool BKE_layer_collection_isolate(Scene *scene,
}
/* Make all the children visible, but respect their disable state. */
- layer_collection_flag_unset_recursive(lc, LAYER_COLLECTION_RESTRICT_VIEW);
+ layer_collection_flag_unset_recursive(lc, LAYER_COLLECTION_HIDE);
BKE_layer_collection_activate(view_layer, lc);
}
@@ -1109,27 +1108,27 @@ bool BKE_layer_collection_set_visible(ViewLayer *view_layer,
bool depsgraph_changed = false;
if (visible && (!ID_IS_LINKED(lc->collection)) &&
- ((lc->collection->flag & COLLECTION_RESTRICT_VIEW) != 0)) {
- lc->collection->flag &= ~COLLECTION_RESTRICT_VIEW;
+ ((lc->collection->flag & COLLECTION_RESTRICT_VIEWPORT) != 0)) {
+ lc->collection->flag &= ~COLLECTION_RESTRICT_VIEWPORT;
depsgraph_changed = true;
}
if (hierarchy) {
if (visible) {
- layer_collection_flag_unset_recursive(lc, LAYER_COLLECTION_RESTRICT_VIEW);
+ layer_collection_flag_unset_recursive(lc, LAYER_COLLECTION_HIDE);
layer_collection_bases_show_recursive(view_layer, lc);
}
else {
- layer_collection_flag_set_recursive(lc, LAYER_COLLECTION_RESTRICT_VIEW);
+ layer_collection_flag_set_recursive(lc, LAYER_COLLECTION_HIDE);
layer_collection_bases_hide_recursive(view_layer, lc);
}
}
else {
if (visible) {
- lc->flag &= ~LAYER_COLLECTION_RESTRICT_VIEW;
+ lc->flag &= ~LAYER_COLLECTION_HIDE;
}
else {
- lc->flag |= LAYER_COLLECTION_RESTRICT_VIEW;
+ lc->flag |= LAYER_COLLECTION_HIDE;
}
}
return depsgraph_changed;
@@ -1491,7 +1490,7 @@ void BKE_base_eval_flags(Base *base)
/* Apply object restrictions. */
const int object_restrict = base->object->restrictflag;
- if (object_restrict & OB_RESTRICT_VIEW) {
+ if (object_restrict & OB_RESTRICT_VIEWPORT) {
base->flag &= ~BASE_ENABLED_VIEWPORT;
}
if (object_restrict & OB_RESTRICT_RENDER) {
diff --git a/source/blender/blenkernel/intern/library.c b/source/blender/blenkernel/intern/library.c
index ad0c405ab28..8b08c189270 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(ptr, prop, idptr);
+ RNA_property_pointer_set(ptr, prop, idptr, NULL);
RNA_property_update(C, ptr, prop);
/* tag grease pencil datablock and disable onion */
@@ -1860,7 +1860,7 @@ static void library_make_local_copying_check(ID *id,
* (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...
+ * 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
diff --git a/source/blender/blenkernel/intern/library_override.c b/source/blender/blenkernel/intern/library_override.c
index 5ed6577e90a..231e0b8ee60 100644
--- a/source/blender/blenkernel/intern/library_override.c
+++ b/source/blender/blenkernel/intern/library_override.c
@@ -81,7 +81,7 @@ IDOverrideStatic *BKE_override_static_init(ID *local_id, ID *reference_id)
for (ancestor_id = reference_id; ancestor_id != NULL && ancestor_id->override_static != NULL &&
ancestor_id->override_static->reference != NULL;
ancestor_id = ancestor_id->override_static->reference) {
- ;
+ /* pass */
}
if (ancestor_id != NULL && ancestor_id->override_static != NULL) {
diff --git a/source/blender/blenkernel/intern/library_query.c b/source/blender/blenkernel/intern/library_query.c
index d0515d8783d..a95069a2af9 100644
--- a/source/blender/blenkernel/intern/library_query.c
+++ b/source/blender/blenkernel/intern/library_query.c
@@ -755,7 +755,7 @@ static void library_foreach_ID_link(Main *bmain,
case ID_CA: {
Camera *camera = (Camera *)id;
- CALLBACK_INVOKE(camera->dof_ob, IDWALK_CB_NOP);
+ CALLBACK_INVOKE(camera->dof.focus_object, IDWALK_CB_NOP);
for (CameraBGImage *bgpic = camera->bg_images.first; bgpic; bgpic = bgpic->next) {
if (bgpic->source == CAM_BGIMG_SOURCE_IMAGE) {
CALLBACK_INVOKE(bgpic->ima, IDWALK_CB_USER);
diff --git a/source/blender/blenkernel/intern/library_remap.c b/source/blender/blenkernel/intern/library_remap.c
index 3b6f11935d1..4e5eac7924b 100644
--- a/source/blender/blenkernel/intern/library_remap.c
+++ b/source/blender/blenkernel/intern/library_remap.c
@@ -740,7 +740,7 @@ void BKE_libblock_relink_to_newid(ID *id)
void BKE_libblock_free_data(ID *id, const bool do_id_user)
{
if (id->properties) {
- IDP_FreeProperty_ex(id->properties, do_id_user);
+ IDP_FreePropertyContent_ex(id->properties, do_id_user);
MEM_freeN(id->properties);
}
diff --git a/source/blender/blenkernel/intern/light.c b/source/blender/blenkernel/intern/light.c
index 05b2eb82daf..1c3acb6a73a 100644
--- a/source/blender/blenkernel/intern/light.c
+++ b/source/blender/blenkernel/intern/light.c
@@ -80,6 +80,7 @@ void BKE_light_init(Light *la)
la->contact_thickness = 0.2f;
la->spec_fac = 1.0f;
la->att_dist = 40.0f;
+ la->sun_angle = DEG2RADF(0.526f);
curvemapping_initialize(la->curfalloff);
}
diff --git a/source/blender/blenkernel/intern/mask.c b/source/blender/blenkernel/intern/mask.c
index 9a9b3757ef2..43fc8152c7b 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 */
diff --git a/source/blender/blenkernel/intern/mesh_convert.c b/source/blender/blenkernel/intern/mesh_convert.c
index 3f4e504867c..461adc823b9 100644
--- a/source/blender/blenkernel/intern/mesh_convert.c
+++ b/source/blender/blenkernel/intern/mesh_convert.c
@@ -34,10 +34,13 @@
#include "BLI_math.h"
#include "BLI_listbase.h"
#include "BLI_edgehash.h"
+#include "BLI_string.h"
#include "BKE_main.h"
#include "BKE_DerivedMesh.h"
+#include "BKE_editmesh.h"
#include "BKE_key.h"
+#include "BKE_library_query.h"
#include "BKE_mesh.h"
#include "BKE_mesh_runtime.h"
#include "BKE_modifier.h"
@@ -612,7 +615,13 @@ void BKE_mesh_from_nurbs_displist(Main *bmain,
}
/* make mesh */
- me = BKE_mesh_add(bmain, obdata_name);
+ if (bmain != NULL) {
+ me = BKE_mesh_add(bmain, obdata_name);
+ }
+ else {
+ me = BKE_id_new_nomain(ID_ME, obdata_name);
+ }
+
me->totvert = totvert;
me->totedge = totedge;
me->totloop = totloop;
@@ -632,7 +641,13 @@ void BKE_mesh_from_nurbs_displist(Main *bmain,
BKE_mesh_calc_normals(me);
}
else {
- me = BKE_mesh_add(bmain, obdata_name);
+ if (bmain != NULL) {
+ me = BKE_mesh_add(bmain, obdata_name);
+ }
+ else {
+ me = BKE_id_new_nomain(ID_ME, obdata_name);
+ }
+
ob->runtime.mesh_eval = NULL;
BKE_mesh_nomain_to_mesh(me_eval, me, ob, &CD_MASK_MESH, true);
}
@@ -662,16 +677,18 @@ void BKE_mesh_from_nurbs_displist(Main *bmain,
ob->type = OB_MESH;
/* other users */
- ob1 = bmain->objects.first;
- while (ob1) {
- if (ob1->data == cu) {
- ob1->type = OB_MESH;
-
- id_us_min((ID *)ob1->data);
- ob1->data = ob->data;
- id_us_plus((ID *)ob1->data);
+ if (bmain != NULL) {
+ ob1 = bmain->objects.first;
+ while (ob1) {
+ if (ob1->data == cu) {
+ ob1->type = OB_MESH;
+
+ id_us_min((ID *)ob1->data);
+ ob1->data = ob->data;
+ id_us_plus((ID *)ob1->data);
+ }
+ ob1 = ob1->id.next;
}
- ob1 = ob1->id.next;
}
if (temporary) {
@@ -892,302 +909,280 @@ void BKE_mesh_to_curve(Main *bmain, Depsgraph *depsgraph, Scene *UNUSED(scene),
}
}
-/* settings: 1 - preview, 2 - render
- *
- * The convention goes as following:
- *
- * - Passing original object with apply_modifiers=false will give a
- * non-modified non-deformed mesh.
- * The result mesh will point to datablocks from the original "domain". For
- * example, materials will be original.
- *
- * - Passing original object with apply_modifiers=true will give a mesh which
- * has all modifiers applied.
- * The result mesh will point to datablocks from the original "domain". For
- * example, materials will be original.
+/* Create a temporary object to be used for nurbs-to-mesh conversion.
*
- * - Passing evaluated object will ignore apply_modifiers argument, and the
- * result always contains all modifiers applied.
- * The result mesh will point to an evaluated datablocks. For example,
- * materials will be an evaluated IDs from the dependency graph.
- */
-Mesh *BKE_mesh_new_from_object(Depsgraph *depsgraph,
- Main *bmain,
- Scene *sce,
- Object *ob,
- const bool apply_modifiers,
- const bool calc_undeformed)
+ * This is more complex that it should be because BKE_mesh_from_nurbs_displist() will do more than
+ * simply conversion and will attempt to take over ownership of evaluated result and will also
+ * modify the input object. */
+static Object *object_for_curve_to_mesh_create(Object *object)
{
- Mesh *tmpmesh;
- Curve *tmpcu = NULL, *copycu;
- int i;
- const bool render = (DEG_get_mode(depsgraph) == DAG_EVAL_RENDER);
- bool effective_apply_modifiers = apply_modifiers;
- bool do_mat_id_data_us = true;
-
- Object *object_input = ob;
- Object *object_eval = DEG_get_evaluated_object(depsgraph, object_input);
- Object object_for_eval;
-
- if (object_eval == object_input) {
- /* Evaluated mesh contains all modifiers applied already.
- * The other types of object has them applied, but are stored in other
- * data structures than a mesh. So need to apply modifiers again on a
- * temporary copy before converting result to mesh. */
- if (object_input->type == OB_MESH) {
- effective_apply_modifiers = false;
- }
- else {
- effective_apply_modifiers = true;
- }
- object_for_eval = *object_eval;
+ Curve *curve = (Curve *)object->data;
+
+ /* Create object itself. */
+ Object *temp_object;
+ BKE_id_copy_ex(NULL, &object->id, (ID **)&temp_object, LIB_ID_COPY_LOCALIZE);
+
+ /* Remove all modifiers, since we don't want them to be applied. */
+ BKE_object_free_modifiers(temp_object, LIB_ID_CREATE_NO_USER_REFCOUNT);
+
+ /* Copy relevant evaluated fields of curve cache.
+ *
+ * Note that there are extra fields in there like bevel and path, but those are not needed during
+ * conversion, so they are not copied to save unnecessary allocations. */
+ if (object->runtime.curve_cache != NULL) {
+ temp_object->runtime.curve_cache = MEM_callocN(sizeof(CurveCache),
+ "CurveCache for curve types");
+ BKE_displist_copy(&temp_object->runtime.curve_cache->disp, &object->runtime.curve_cache->disp);
}
- else {
- if (apply_modifiers) {
- object_for_eval = *object_eval;
- if (object_for_eval.runtime.mesh_orig != NULL) {
- object_for_eval.data = object_for_eval.runtime.mesh_orig;
- }
- }
- else {
- object_for_eval = *object_input;
- }
+ /* Constructive modifiers will use mesh to store result. */
+ if (object->runtime.mesh_eval != NULL) {
+ BKE_id_copy_ex(NULL,
+ &object->runtime.mesh_eval->id,
+ (ID **)&temp_object->runtime.mesh_eval,
+ LIB_ID_COPY_LOCALIZE);
}
- const bool cage = !effective_apply_modifiers;
+ /* Need to create copy of curve itself as well, it will be freed by underlying conversion
+ * functions.
+ *
+ * NOTE: Copies the data, but not the shapekeys. */
+ BKE_id_copy_ex(NULL, object->data, (ID **)&temp_object->data, LIB_ID_COPY_LOCALIZE);
+ Curve *temp_curve = (Curve *)temp_object->data;
- /* perform the mesh extraction based on type */
- switch (object_for_eval.type) {
- case OB_FONT:
- case OB_CURVE:
- case OB_SURF: {
- ListBase dispbase = {NULL, NULL};
- Mesh *me_eval_final = NULL;
- int uv_from_orco;
-
- /* copies object and modifiers (but not the data) */
- Object *tmpobj;
- BKE_id_copy_ex(NULL, &object_for_eval.id, (ID **)&tmpobj, LIB_ID_COPY_LOCALIZE);
- tmpcu = (Curve *)tmpobj->data;
-
- /* Copy cached display list, it might be needed by the stack evaluation.
- * Ideally stack should be able to use render-time display list, but doing
- * so is quite tricky and not safe so close to the release.
- *
- * TODO(sergey): Look into more proper solution.
- */
- if (object_for_eval.runtime.curve_cache != NULL) {
- if (tmpobj->runtime.curve_cache == NULL) {
- tmpobj->runtime.curve_cache = MEM_callocN(sizeof(CurveCache),
- "CurveCache for curve types");
- }
- BKE_displist_copy(&tmpobj->runtime.curve_cache->disp,
- &object_for_eval.runtime.curve_cache->disp);
- }
+ /* Make sure texture space is calculated for a copy of curve, it will be used for the final
+ * result. */
+ BKE_curve_texspace_calc(temp_curve);
- /* if getting the original caged mesh, delete object modifiers */
- if (cage) {
- BKE_object_free_modifiers(tmpobj, LIB_ID_CREATE_NO_USER_REFCOUNT);
- }
+ /* Temporarily set edit so we get updates from edit mode, but also because for text datablocks
+ * copying it while in edit mode gives invalid data structures. */
+ temp_curve->editfont = curve->editfont;
+ temp_curve->editnurb = curve->editnurb;
- /* copies the data, but *not* the shapekeys. */
- BKE_id_copy_ex(NULL, object_for_eval.data, (ID **)&copycu, LIB_ID_COPY_LOCALIZE);
- tmpobj->data = copycu;
-
- /* make sure texture space is calculated for a copy of curve,
- * it will be used for the final result.
- */
- BKE_curve_texspace_calc(copycu);
-
- /* temporarily set edit so we get updates from edit mode, but
- * also because for text datablocks copying it while in edit
- * mode gives invalid data structures */
- copycu->editfont = tmpcu->editfont;
- copycu->editnurb = tmpcu->editnurb;
-
- /* get updated display list, and convert to a mesh */
- BKE_displist_make_curveTypes_forRender(
- depsgraph, sce, tmpobj, &dispbase, &me_eval_final, false, render, NULL);
-
- copycu->editfont = NULL;
- copycu->editnurb = NULL;
-
- tmpobj->runtime.mesh_eval = me_eval_final;
-
- /* convert object type to mesh */
- uv_from_orco = (tmpcu->flag & CU_UV_ORCO) != 0;
- BKE_mesh_from_nurbs_displist(
- bmain, tmpobj, &dispbase, uv_from_orco, tmpcu->id.name + 2, true);
- /* Function above also frees copycu (aka tmpobj->data), make this obvious here. */
- copycu = NULL;
-
- tmpmesh = tmpobj->data;
- id_us_min(
- &tmpmesh->id); /* Gets one user from its creation in BKE_mesh_from_nurbs_displist(). */
-
- BKE_displist_free(&dispbase);
-
- /* BKE_mesh_from_nurbs changes the type to a mesh, check it worked.
- * if it didn't the curve did not have any segments or otherwise
- * would have generated an empty mesh */
- if (tmpobj->type != OB_MESH) {
- BKE_id_free(NULL, tmpobj);
- return NULL;
- }
+ return temp_object;
+}
- BKE_id_free(NULL, tmpobj);
+static void curve_to_mesh_eval_ensure(Object *object)
+{
+ if (object->runtime.curve_cache == NULL) {
+ object->runtime.curve_cache = MEM_callocN(sizeof(CurveCache), "CurveCache for Curve");
+ }
+ Curve *curve = (Curve *)object->data;
+ Curve remapped_curve = *curve;
+ Object remapped_object = *object;
+ remapped_object.data = &remapped_curve;
- /* XXX The curve to mesh conversion is convoluted...
- * But essentially, BKE_mesh_from_nurbs_displist()
- * already transfers the ownership of materials from the temp copy of the Curve ID to the
- * new Mesh ID, so we do not want to increase materials' usercount later. */
- do_mat_id_data_us = false;
+ /* Clear all modifiers for the bevel object.
+ *
+ * This is because they can not be reliably evaluated for an original object (at least because
+ * the state of dependencies is not know).
+ *
+ * So we create temporary copy of the object which will use same data as the original bevel, but
+ * will have no modifiers. */
+ Object bevel_object = {NULL};
+ if (remapped_curve.bevobj != NULL) {
+ bevel_object = *remapped_curve.bevobj;
+ BLI_listbase_clear(&bevel_object.modifiers);
+ remapped_curve.bevobj = &bevel_object;
+ }
- break;
- }
+ /* Same thing for taper. */
+ Object taper_object = {NULL};
+ if (remapped_curve.taperobj != NULL) {
+ taper_object = *remapped_curve.taperobj;
+ BLI_listbase_clear(&taper_object.modifiers);
+ remapped_curve.taperobj = &taper_object;
+ }
- case OB_MBALL: {
- /* metaballs don't have modifiers, so just convert to mesh */
- Object *basis_ob = BKE_mball_basis_find(sce, object_input);
- /* todo, re-generatre for render-res */
- /* metaball_polygonize(scene, ob) */
+ /* NOTE: We don't have dependency graph or scene here, so we pass NULL. This is all fine since
+ * they are only used for modifier stack, which we have explicitly disabled for all objects.
+ *
+ * TODO(sergey): This is a very fragile logic, but proper solution requires re-writing quite a
+ * bit of internal functions (BKE_mesh_from_nurbs_displist, BKE_mesh_nomain_to_mesh) and also
+ * Mesh From Curve operator.
+ * Brecht says hold off with that. */
+ BKE_displist_make_curveTypes_forRender(NULL,
+ NULL,
+ &remapped_object,
+ &remapped_object.runtime.curve_cache->disp,
+ &remapped_object.runtime.mesh_eval,
+ false);
+
+ BKE_object_free_curve_cache(&bevel_object);
+ BKE_object_free_curve_cache(&taper_object);
+}
- if (basis_ob != object_input) {
- /* Only do basis metaball. */
- return NULL;
- }
+static Mesh *mesh_new_from_curve_type_object(Object *object)
+{
+ Curve *curve = object->data;
+ const bool uv_from_orco = (curve->flag & CU_UV_ORCO) != 0;
- tmpmesh = BKE_mesh_add(bmain, ((ID *)object_for_eval.data)->name + 2);
- /* BKE_mesh_add gives us a user count we don't need */
- id_us_min(&tmpmesh->id);
+ Object *temp_object = object_for_curve_to_mesh_create(object);
+ Curve *temp_curve = (Curve *)temp_object->data;
- if (render) {
- ListBase disp = {NULL, NULL};
- BKE_displist_make_mball_forRender(depsgraph, sce, &object_for_eval, &disp);
- BKE_mesh_from_metaball(&disp, tmpmesh);
- BKE_displist_free(&disp);
- }
- else {
- ListBase disp = {NULL, NULL};
- if (object_for_eval.runtime.curve_cache) {
- disp = object_for_eval.runtime.curve_cache->disp;
- }
- BKE_mesh_from_metaball(&disp, tmpmesh);
- }
+ /* When input object is an original one, we don't have evaluated curve cache yet, so need to
+ * create it in the temporary object. */
+ if (!DEG_is_evaluated_object(object)) {
+ curve_to_mesh_eval_ensure(temp_object);
+ }
- BKE_mesh_texspace_copy_from_object(tmpmesh, &object_for_eval);
+ /* Reset pointers before conversion. */
+ temp_curve->editfont = NULL;
+ temp_curve->editnurb = NULL;
+
+ /* Convert to mesh. */
+ BKE_mesh_from_nurbs_displist(NULL,
+ temp_object,
+ &temp_object->runtime.curve_cache->disp,
+ uv_from_orco,
+ curve->id.name + 2,
+ true);
+
+ /* BKE_mesh_from_nurbs changes the type to a mesh, check it worked. If it didn't the curve did
+ * not have any segments or otherwise would have generated an empty mesh. */
+ if (temp_object->type != OB_MESH) {
+ BKE_id_free(NULL, temp_object);
+ return NULL;
+ }
- break;
- }
- case OB_MESH:
- /* copies object and modifiers (but not the data) */
- if (cage) {
- /* copies the data (but *not* the shapekeys). */
- Mesh *mesh = object_for_eval.data;
- BKE_id_copy_ex(bmain, &mesh->id, (ID **)&tmpmesh, 0);
- /* XXX BKE_mesh_copy() already handles materials usercount. */
- do_mat_id_data_us = false;
- }
- /* if not getting the original caged mesh, get final derived mesh */
- else {
- /* Make a dummy mesh, saves copying */
- Mesh *me_eval;
- CustomData_MeshMasks mask = CD_MASK_MESH; /* this seems more suitable, exporter,
- * for example, needs CD_MASK_MDEFORMVERT */
+ Mesh *mesh_result = temp_object->data;
- if (calc_undeformed) {
- mask.vmask |= CD_MASK_ORCO;
- }
+ BKE_id_free(NULL, temp_object);
- if (render) {
- me_eval = mesh_create_eval_final_render(depsgraph, sce, &object_for_eval, &mask);
- }
- else {
- me_eval = mesh_create_eval_final_view(depsgraph, sce, &object_for_eval, &mask);
- }
+ /* NOTE: Materials are copied in BKE_mesh_from_nurbs_displist(). */
- tmpmesh = BKE_mesh_add(bmain, ((ID *)object_for_eval.data)->name + 2);
- BKE_mesh_nomain_to_mesh(me_eval, tmpmesh, &object_for_eval, &mask, true);
+ return mesh_result;
+}
- /* Copy autosmooth settings from original mesh. */
- Mesh *me = (Mesh *)object_for_eval.data;
- tmpmesh->flag |= (me->flag & ME_AUTOSMOOTH);
- tmpmesh->smoothresh = me->smoothresh;
- }
+static Mesh *mesh_new_from_mball_object(Object *object)
+{
+ MetaBall *mball = (MetaBall *)object->data;
- /* BKE_mesh_add/copy gives us a user count we don't need */
- id_us_min(&tmpmesh->id);
+ /* NOTE: We can only create mesh for a polygonized meta ball. This figures out all original meta
+ * balls and all evaluated child meta balls (since polygonization is only stored in the mother
+ * ball).
+ *
+ * We create empty mesh so scripters don't run into None objects. */
+ if (!DEG_is_evaluated_object(object) || object->runtime.curve_cache == NULL ||
+ BLI_listbase_is_empty(&object->runtime.curve_cache->disp)) {
+ return BKE_id_new_nomain(ID_ME, ((ID *)object->data)->name + 2);
+ }
- break;
- default:
- /* "Object does not have geometry data") */
- return NULL;
+ Mesh *mesh_result = BKE_id_new_nomain(ID_ME, ((ID *)object->data)->name + 2);
+ BKE_mesh_from_metaball(&object->runtime.curve_cache->disp, mesh_result);
+
+ /* Copy materials. */
+ mesh_result->totcol = mball->totcol;
+ mesh_result->mat = MEM_dupallocN(mball->mat);
+ if (mball->mat != NULL) {
+ for (int i = mball->totcol; i-- > 0;) {
+ mesh_result->mat[i] = give_current_material(object, i + 1);
+ }
}
- /* Copy materials to new mesh */
- switch (object_for_eval.type) {
- case OB_SURF:
- case OB_FONT:
- case OB_CURVE:
- tmpmesh->totcol = tmpcu->totcol;
+ return mesh_result;
+}
- /* free old material list (if it exists) and adjust user counts */
- if (tmpcu->mat) {
- for (i = tmpcu->totcol; i-- > 0;) {
- /* are we an object material or data based? */
- tmpmesh->mat[i] = give_current_material(object_input, i + 1);
+static Mesh *mesh_new_from_mesh_object(Object *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;
+ }
+ Mesh *mesh_result = NULL;
+ BKE_id_copy_ex(NULL,
+ &mesh_input->id,
+ (ID **)&mesh_result,
+ LIB_ID_CREATE_NO_MAIN | LIB_ID_CREATE_NO_USER_REFCOUNT);
+ /* NOTE: Materials should already be copied. */
+ /* Copy original mesh name. This is because edit meshes might not have one properly set name. */
+ BLI_strncpy(mesh_result->id.name, ((ID *)object->data)->name, sizeof(mesh_result->id.name));
+ return mesh_result;
+}
- if (((object_for_eval.matbits && object_for_eval.matbits[i]) || do_mat_id_data_us) &&
- tmpmesh->mat[i]) {
- id_us_plus(&tmpmesh->mat[i]->id);
- }
- }
- }
+Mesh *BKE_mesh_new_from_object(Object *object)
+{
+ Mesh *new_mesh = NULL;
+ switch (object->type) {
+ case OB_FONT:
+ case OB_CURVE:
+ case OB_SURF:
+ new_mesh = mesh_new_from_curve_type_object(object);
+ break;
+ case OB_MBALL:
+ new_mesh = mesh_new_from_mball_object(object);
break;
+ case OB_MESH:
+ new_mesh = mesh_new_from_mesh_object(object);
+ break;
+ default:
+ /* Object does not have geometry data. */
+ return NULL;
+ }
+ if (new_mesh == NULL) {
+ /* Happens in special cases like request of mesh for non-mother meta ball. */
+ return NULL;
+ }
+ /* The result must have 0 users, since it's just a mesh which is free-dangling data-block.
+ * All the conversion functions are supposed to ensure mesh is not counted. */
+ BLI_assert(new_mesh->id.us == 0);
+ return new_mesh;
+}
- case OB_MBALL: {
- MetaBall *tmpmb = (MetaBall *)object_for_eval.data;
- tmpmesh->mat = MEM_dupallocN(tmpmb->mat);
- tmpmesh->totcol = tmpmb->totcol;
+static int foreach_libblock_make_original_and_usercount_callback(void *user_data_v,
+ ID *id_self,
+ ID **id_p,
+ int cb_flag)
+{
+ UNUSED_VARS(user_data_v, id_self, cb_flag);
+ if (*id_p == NULL) {
+ return IDWALK_RET_NOP;
+ }
+ *id_p = DEG_get_original_id(*id_p);
+ id_us_plus(*id_p);
+ return IDWALK_RET_NOP;
+}
- /* free old material list (if it exists) and adjust user counts */
- if (tmpmb->mat) {
- for (i = tmpmb->totcol; i-- > 0;) {
- /* are we an object material or data based? */
- tmpmesh->mat[i] = give_current_material(object_input, i + 1);
+Mesh *BKE_mesh_new_from_object_to_bmain(Main *bmain, Object *object)
+{
+ Mesh *mesh = BKE_mesh_new_from_object(object);
- if (((object_for_eval.matbits && object_for_eval.matbits[i]) || do_mat_id_data_us) &&
- tmpmesh->mat[i]) {
- id_us_plus(&tmpmesh->mat[i]->id);
- }
- }
- }
- break;
- }
+ /* Make sure mesh only points original datablocks, also increase users of materials and other
+ * possibly referenced data-blocks.
+ *
+ * Going to original data-blocks is required to have bmain in a consistent state, where
+ * everything is only allowed to reference original data-blocks.
+ *
+ * user-count is required is because so far mesh was in a limbo, where library management does
+ * not perform any user management (i.e. copy of a mesh will not increase users of materials). */
+ BKE_library_foreach_ID_link(
+ NULL, &mesh->id, foreach_libblock_make_original_and_usercount_callback, NULL, IDWALK_NOP);
+
+ /* Append the mesh to bmain.
+ * We do it a bit longer way since there is no simple and clear way of adding existing datablock
+ * to the bmain. So we allocate new empty mesh in the bmain (which guarantess all the naming and
+ * orders and flags) and move the temporary mesh in place there. */
+ Mesh *mesh_in_bmain = BKE_mesh_add(bmain, mesh->id.name + 2);
+
+ /* NOTE: BKE_mesh_nomain_to_mesh() does not copy materials and instead it preserves them in the
+ * destinaion mesh .So we "steal" all related fields before calling it.
+ *
+ * TODO(sergey): We really better have a function which gets and ID and accepts it for the bmain.
+ */
+ mesh_in_bmain->mat = mesh->mat;
+ mesh_in_bmain->totcol = mesh->totcol;
+ mesh_in_bmain->flag = mesh->flag;
+ mesh_in_bmain->smoothresh = mesh->smoothresh;
+ mesh->mat = NULL;
- case OB_MESH:
- if (!cage) {
- Mesh *origmesh = object_for_eval.data;
- tmpmesh->flag = origmesh->flag;
- tmpmesh->mat = MEM_dupallocN(origmesh->mat);
- tmpmesh->totcol = origmesh->totcol;
- tmpmesh->smoothresh = origmesh->smoothresh;
- if (origmesh->mat) {
- for (i = origmesh->totcol; i-- > 0;) {
- /* are we an object material or data based? */
- tmpmesh->mat[i] = give_current_material(object_input, i + 1);
-
- if (((object_for_eval.matbits && object_for_eval.matbits[i]) || do_mat_id_data_us) &&
- tmpmesh->mat[i]) {
- id_us_plus(&tmpmesh->mat[i]->id);
- }
- }
- }
- }
- break;
- } /* end copy materials */
+ BKE_mesh_nomain_to_mesh(mesh, mesh_in_bmain, NULL, &CD_MASK_MESH, true);
+
+ /* Make sure user count from BKE_mesh_add() is the one we expect here and bring it down to 0. */
+ BLI_assert(mesh_in_bmain->id.us == 1);
+ id_us_min(&mesh_in_bmain->id);
- return tmpmesh;
+ return mesh_in_bmain;
}
static void add_shapekey_layers(Mesh *mesh_dest, Mesh *mesh_src)
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/node.c b/source/blender/blenkernel/intern/node.c
index 3adb6cfe960..b7db434e234 100644
--- a/source/blender/blenkernel/intern/node.c
+++ b/source/blender/blenkernel/intern/node.c
@@ -787,7 +787,7 @@ static void node_socket_free(bNodeTree *UNUSED(ntree),
const bool do_id_user)
{
if (sock->prop) {
- IDP_FreeProperty_ex(sock->prop, do_id_user);
+ IDP_FreePropertyContent_ex(sock->prop, do_id_user);
MEM_freeN(sock->prop);
}
@@ -1850,7 +1850,7 @@ static void node_free_node(bNodeTree *ntree, bNode *node)
if (node->prop) {
/* Remember, no ID user refcount management here! */
- IDP_FreeProperty_ex(node->prop, false);
+ IDP_FreePropertyContent_ex(node->prop, false);
MEM_freeN(node->prop);
}
@@ -1910,7 +1910,6 @@ static void node_socket_interface_free(bNodeTree *UNUSED(ntree), bNodeSocket *so
{
if (sock->prop) {
IDP_FreeProperty(sock->prop);
- MEM_freeN(sock->prop);
}
if (sock->default_value) {
diff --git a/source/blender/blenkernel/intern/object.c b/source/blender/blenkernel/intern/object.c
index 38a8ad2769a..85ca9cb26b9 100644
--- a/source/blender/blenkernel/intern/object.c
+++ b/source/blender/blenkernel/intern/object.c
@@ -469,6 +469,7 @@ void BKE_object_free_derived_caches(Object *ob)
ob->runtime.mesh_deform_eval = NULL;
}
+ BKE_object_to_mesh_clear(ob);
BKE_object_free_curve_cache(ob);
/* clear grease pencil data */
@@ -1467,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
@@ -1951,7 +1952,6 @@ void BKE_object_make_proxy(Main *bmain, Object *ob, Object *target, Object *cob)
/* copy IDProperties */
if (ob->id.properties) {
IDP_FreeProperty(ob->id.properties);
- MEM_freeN(ob->id.properties);
ob->id.properties = NULL;
}
if (target->id.properties) {
@@ -4487,3 +4487,32 @@ void BKE_object_type_set_empty_for_versioning(Object *ob)
}
ob->mode = OB_MODE_OBJECT;
}
+
+/* Updates select_id of all objects in the given bmain. */
+void BKE_object_update_select_id(struct Main *bmain)
+{
+ Object *ob = bmain->objects.first;
+ int select_id = 1;
+ while (ob) {
+ ob->runtime.select_id = select_id++;
+ ob = ob->id.next;
+ }
+}
+
+Mesh *BKE_object_to_mesh(Object *object)
+{
+ BKE_object_to_mesh_clear(object);
+
+ Mesh *mesh = BKE_mesh_new_from_object(object);
+ object->runtime.object_as_temp_mesh = mesh;
+ return mesh;
+}
+
+void BKE_object_to_mesh_clear(Object *object)
+{
+ if (object->runtime.object_as_temp_mesh == NULL) {
+ return;
+ }
+ BKE_id_free(NULL, object->runtime.object_as_temp_mesh);
+ object->runtime.object_as_temp_mesh = NULL;
+}
diff --git a/source/blender/blenkernel/intern/object_dupli.c b/source/blender/blenkernel/intern/object_dupli.c
index 8080834a53a..0dedbb7e934 100644
--- a/source/blender/blenkernel/intern/object_dupli.c
+++ b/source/blender/blenkernel/intern/object_dupli.c
@@ -1082,7 +1082,7 @@ static const DupliGenerator *get_dupli_generator(const DupliContext *ctx)
/* Should the dupli's be generated for this object? - Respect restrict flags */
if (DEG_get_mode(ctx->depsgraph) == DAG_EVAL_RENDER ? (restrictflag & OB_RESTRICT_RENDER) :
- (restrictflag & OB_RESTRICT_VIEW)) {
+ (restrictflag & OB_RESTRICT_VIEWPORT)) {
return NULL;
}
diff --git a/source/blender/blenkernel/intern/object_update.c b/source/blender/blenkernel/intern/object_update.c
index 183bc968897..6dee936ca76 100644
--- a/source/blender/blenkernel/intern/object_update.c
+++ b/source/blender/blenkernel/intern/object_update.c
@@ -202,9 +202,11 @@ void BKE_object_handle_data_update(Depsgraph *depsgraph, Scene *scene, Object *o
case OB_CURVE:
case OB_SURF:
- case OB_FONT:
- BKE_displist_make_curveTypes(depsgraph, scene, ob, false, false, NULL);
+ case OB_FONT: {
+ bool for_render = (DEG_get_mode(depsgraph) == DAG_EVAL_RENDER);
+ BKE_displist_make_curveTypes(depsgraph, scene, ob, for_render, false);
break;
+ }
case OB_LATTICE:
BKE_lattice_modifiers_calc(depsgraph, scene, ob);
diff --git a/source/blender/blenkernel/intern/paint.c b/source/blender/blenkernel/intern/paint.c
index c55cf18fcea..5849d691b03 100644
--- a/source/blender/blenkernel/intern/paint.c
+++ b/source/blender/blenkernel/intern/paint.c
@@ -82,8 +82,11 @@ static eOverlayControlFlags overlay_flags = 0;
void BKE_paint_invalidate_overlay_tex(Scene *scene, ViewLayer *view_layer, const Tex *tex)
{
Paint *p = BKE_paint_get_active(scene, view_layer);
- Brush *br = p->brush;
+ if (!p) {
+ return;
+ }
+ Brush *br = p->brush;
if (!br) {
return;
}
@@ -99,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;
}
@@ -1273,9 +1279,6 @@ void BKE_sculpt_update_mesh_elements(
}
}
}
-
- /* 2.8x - avoid full mesh update! */
- BKE_mesh_batch_cache_dirty_tag(me, BKE_MESH_BATCH_DIRTY_SCULPT_COORDS);
}
int BKE_sculpt_mask_layers_ensure(Object *ob, MultiresModifierData *mmd)
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_distribute.c b/source/blender/blenkernel/intern/particle_distribute.c
index 8125024585c..070c3c7a566 100644
--- a/source/blender/blenkernel/intern/particle_distribute.c
+++ b/source/blender/blenkernel/intern/particle_distribute.c
@@ -1170,7 +1170,7 @@ static int psys_thread_context_init_distribute(ParticleThreadContext *ctx,
int i_mapped = 0;
for (i = 0; i < totelem && element_weight[i] == 0.0f; i++) {
- ;
+ /* pass */
}
element_sum[i_mapped] = element_weight[i] * inv_totweight;
element_map[i_mapped] = i;
@@ -1216,7 +1216,7 @@ static int psys_thread_context_init_distribute(ParticleThreadContext *ctx,
for (i = 0, p = 0; p < totpart; p++, pos += step) {
for (; (i < totmapped - 1) && (pos > (double)element_sum[i]); i++) {
- ;
+ /* pass */
}
particle_element[p] = element_map[i];
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/pbvh.c b/source/blender/blenkernel/intern/pbvh.c
index c186394880b..f1d5347c48b 100644
--- a/source/blender/blenkernel/intern/pbvh.c
+++ b/source/blender/blenkernel/intern/pbvh.c
@@ -181,10 +181,10 @@ static int partition_indices(int *prim_indices, int lo, int hi, int axis, float
int i = lo, j = hi;
for (;;) {
for (; prim_bbc[prim_indices[i]].bcentroid[axis] < mid; i++) {
- ;
+ /* pass */
}
for (; mid < prim_bbc[prim_indices[j]].bcentroid[axis]; j--) {
- ;
+ /* pass */
}
if (!(i < j)) {
@@ -216,18 +216,18 @@ static int partition_indices_material(PBVH *bvh, int lo, int hi)
for (;;) {
if (bvh->looptri) {
for (; face_materials_match(first, &mpoly[looptri[indices[i]].poly]); i++) {
- ;
+ /* pass */
}
for (; !face_materials_match(first, &mpoly[looptri[indices[j]].poly]); j--) {
- ;
+ /* pass */
}
}
else {
for (; grid_materials_match(first, &flagmats[indices[i]]); i++) {
- ;
+ /* pass */
}
for (; !grid_materials_match(first, &flagmats[indices[j]]); j--) {
- ;
+ /* pass */
}
}
@@ -2202,26 +2202,17 @@ bool BKE_pbvh_node_planes_exclude_AABB(PBVHNode *node, void *data)
return test_planes_aabb(bb_min, bb_max, data) != ISECT_INSIDE;
}
-struct PBVHNodeDrawCallbackData {
- void (*draw_fn)(void *user_data, GPUBatch *batch);
+typedef struct PBVHNodeDrawCallbackData {
+ void (*draw_fn)(void *user_data, GPU_PBVH_Buffers *buffers);
void *user_data;
- bool fast;
- bool only_mask; /* Only draw nodes that have mask data. */
- bool wires;
-};
+} PBVHNodeDrawCallbackData;
static void pbvh_node_draw_cb(PBVHNode *node, void *data_v)
{
- struct PBVHNodeDrawCallbackData *data = data_v;
+ PBVHNodeDrawCallbackData *data = data_v;
if (!(node->flag & PBVH_FullyHidden)) {
- GPUBatch *batch = GPU_pbvh_buffers_batch_get(node->draw_buffers, data->fast, data->wires);
- bool show_mask = GPU_pbvh_buffers_has_mask(node->draw_buffers);
- if (!data->only_mask || show_mask) {
- if (batch != NULL) {
- data->draw_fn(data->user_data, batch);
- }
- }
+ data->draw_fn(data->user_data, node->draw_buffers);
}
}
@@ -2231,20 +2222,10 @@ static void pbvh_node_draw_cb(PBVHNode *node, void *data_v)
void BKE_pbvh_draw_cb(PBVH *bvh,
float (*planes)[4],
float (*fnors)[3],
- bool fast,
- bool wires,
- bool only_mask,
bool show_vcol,
- void (*draw_fn)(void *user_data, GPUBatch *batch),
+ void (*draw_fn)(void *user_data, GPU_PBVH_Buffers *buffers),
void *user_data)
{
- struct PBVHNodeDrawCallbackData draw_data = {
- .only_mask = only_mask,
- .fast = fast,
- .wires = wires,
- .draw_fn = draw_fn,
- .user_data = user_data,
- };
PBVHNode **nodes;
int totnode;
@@ -2261,6 +2242,11 @@ void BKE_pbvh_draw_cb(PBVH *bvh,
MEM_freeN(nodes);
}
+ PBVHNodeDrawCallbackData draw_data = {
+ .draw_fn = draw_fn,
+ .user_data = user_data,
+ };
+
if (planes) {
BKE_pbvh_search_callback(
bvh, BKE_pbvh_node_planes_contain_AABB, planes, pbvh_node_draw_cb, &draw_data);
@@ -2268,10 +2254,18 @@ void BKE_pbvh_draw_cb(PBVH *bvh,
else {
BKE_pbvh_search_callback(bvh, NULL, NULL, pbvh_node_draw_cb, &draw_data);
}
-#if 0
- if (G.debug_value == 14)
- pbvh_draw_BB(bvh);
-#endif
+}
+
+void BKE_pbvh_draw_debug_cb(
+ PBVH *bvh,
+ void (*draw_fn)(void *user_data, const float bmin[3], const float bmax[3], PBVHNodeFlags flag),
+ void *user_data)
+{
+ for (int a = 0; a < bvh->totnode; a++) {
+ PBVHNode *node = &bvh->nodes[a];
+
+ draw_fn(user_data, node->vb.bmin, node->vb.bmax, node->flag);
+ }
}
void BKE_pbvh_grids_update(
diff --git a/source/blender/blenkernel/intern/scene.c b/source/blender/blenkernel/intern/scene.c
index 58b36aed24f..872f99ff813 100644
--- a/source/blender/blenkernel/intern/scene.c
+++ b/source/blender/blenkernel/intern/scene.c
@@ -497,7 +497,6 @@ void BKE_scene_free_ex(Scene *sce, const bool do_id_user)
}
if (sce->r.ffcodecdata.properties) {
IDP_FreeProperty(sce->r.ffcodecdata.properties);
- MEM_freeN(sce->r.ffcodecdata.properties);
sce->r.ffcodecdata.properties = NULL;
}
@@ -566,7 +565,7 @@ void BKE_scene_init(Scene *sce)
sce->cursor.rotation_quaternion[0] = 1.0f;
sce->cursor.rotation_axis[1] = 1.0f;
- sce->r.mode = R_OSA;
+ sce->r.mode = 0;
sce->r.cfra = 1;
sce->r.sfra = 1;
sce->r.efra = 250;
@@ -767,7 +766,6 @@ void BKE_scene_init(Scene *sce)
BLI_strncpy(sce->r.pic, U.renderdir, sizeof(sce->r.pic));
BLI_rctf_init(&sce->r.safety, 0.1f, 0.9f, 0.1f, 0.9f);
- sce->r.osa = 8;
/* Note; in header_info.c the scene copy happens...,
* if you add more to renderdata it has to be checked there. */
@@ -905,6 +903,9 @@ void BKE_scene_init(Scene *sce)
sce->display.matcap_ssao_attenuation = 1.0f;
sce->display.matcap_ssao_samples = 16;
+ sce->display.render_aa = SCE_DISPLAY_AA_SAMPLES_8;
+ sce->display.viewport_aa = SCE_DISPLAY_AA_FXAA;
+
/* OpenGL Render. */
BKE_screen_view3d_shading_init(&sce->display.shading);
@@ -2384,4 +2385,20 @@ void BKE_scene_cursor_quat_to_rot(View3DCursor *cursor, const float quat[4], boo
}
}
+void BKE_scene_cursor_to_mat4(const View3DCursor *cursor, float mat[4][4])
+{
+ float mat3[3][3];
+ BKE_scene_cursor_rot_to_mat3(cursor, mat3);
+ copy_m4_m3(mat, mat3);
+ copy_v3_v3(mat[3], cursor->location);
+}
+
+void BKE_scene_cursor_from_mat4(View3DCursor *cursor, const float mat[4][4], bool use_compat)
+{
+ float mat3[3][3];
+ copy_m3_m4(mat3, mat);
+ BKE_scene_cursor_mat3_to_rot(cursor, mat3, use_compat);
+ copy_v3_v3(cursor->location, mat[3]);
+}
+
/** \} */
diff --git a/source/blender/blenkernel/intern/screen.c b/source/blender/blenkernel/intern/screen.c
index 9799f7c2943..222e8ddb724 100644
--- a/source/blender/blenkernel/intern/screen.c
+++ b/source/blender/blenkernel/intern/screen.c
@@ -193,18 +193,6 @@ static void panel_list_copy(ListBase *newlb, const ListBase *lb)
Panel *pa = lb->first;
for (; newpa; newpa = newpa->next, pa = pa->next) {
newpa->activedata = NULL;
-
- Panel *newpatab = newlb->first;
- Panel *patab = lb->first;
- while (newpatab) {
- if (newpa->paneltab == patab) {
- newpa->paneltab = newpatab;
- break;
- }
- newpatab = newpatab->next;
- patab = patab->next;
- }
-
panel_list_copy(&newpa->children, &pa->children);
}
}
@@ -439,7 +427,6 @@ void BKE_area_region_free(SpaceType *st, ARegion *ar)
}
if (uilst->properties) {
IDP_FreeProperty(uilst->properties);
- MEM_freeN(uilst->properties);
}
}
@@ -853,12 +840,13 @@ void BKE_screen_view3d_shading_init(View3DShading *shading)
shading->type = OB_SOLID;
shading->prev_type = OB_SOLID;
shading->flag = V3D_SHADING_SPECULAR_HIGHLIGHT | V3D_SHADING_XRAY_BONE;
- shading->light = V3D_LIGHTING_STUDIO;
+ shading->light = V3D_LIGHTING_MATCAP;
shading->shadow_intensity = 0.5f;
shading->xray_alpha = 0.5f;
shading->xray_alpha_wire = 0.5f;
shading->cavity_valley_factor = 1.0f;
shading->cavity_ridge_factor = 1.0f;
+ shading->cavity_type = V3D_SHADING_CAVITY_CURVATURE;
shading->curvature_ridge_factor = 1.0f;
shading->curvature_valley_factor = 1.0f;
copy_v3_fl(shading->single_color, 0.8f);
diff --git a/source/blender/blenkernel/intern/seqcache.c b/source/blender/blenkernel/intern/seqcache.c
index 1c0aa63f590..f77b3e99e30 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);
}
}
@@ -592,7 +594,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 +635,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 +651,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 b1a32552878..92f951ec637 100644
--- a/source/blender/blenkernel/intern/sequencer.c
+++ b/source/blender/blenkernel/intern/sequencer.c
@@ -262,7 +262,7 @@ static void BKE_sequence_free_ex(Scene *scene,
}
if (seq->prop) {
- IDP_FreeProperty_ex(seq->prop, do_id_user);
+ IDP_FreePropertyContent_ex(seq->prop, do_id_user);
MEM_freeN(seq->prop);
}
@@ -635,8 +635,6 @@ void BKE_sequencer_new_render_data(Main *bmain,
r_context->is_proxy_render = false;
r_context->view_id = 0;
r_context->gpu_offscreen = NULL;
- r_context->gpu_samples = (scene->r.mode & R_OSA) ? scene->r.osa : 0;
- r_context->gpu_full_samples = (r_context->gpu_samples) && (scene->r.scemode & R_FULL_SAMPLE);
}
/* ************************* iterator ************************** */
@@ -2792,7 +2790,7 @@ static ImBuf *input_preprocess(const SeqRenderData *context,
}
if (ibuf->x != context->rectx || ibuf->y != context->recty) {
- if (scene->r.mode & R_OSA) {
+ if (scene->display.render_aa > SCE_DISPLAY_AA_FXAA) {
IMB_scaleImBuf(ibuf, (short)context->rectx, (short)context->recty);
}
else {
@@ -3523,7 +3521,6 @@ static ImBuf *seq_render_scene_strip(const SeqRenderData *context,
unsigned int draw_flags = V3D_OFSDRAW_NONE;
draw_flags |= (use_gpencil) ? V3D_OFSDRAW_SHOW_ANNOTATION : 0;
- draw_flags |= (context->gpu_full_samples) ? V3D_OFSDRAW_USE_FULL_SAMPLE : 0;
draw_flags |= (context->scene->r.seq_flag & R_SEQ_OVERRIDE_SCENE_SETTINGS) ?
V3D_OFSDRAW_OVERRIDE_SCENE_SETTINGS :
0;
@@ -3549,7 +3546,7 @@ static ImBuf *seq_render_scene_strip(const SeqRenderData *context,
IB_rect,
draw_flags,
scene->r.alphamode,
- context->gpu_samples,
+ U.ogl_multisamples,
viewname,
context->gpu_offscreen,
err_out);
@@ -3578,9 +3575,9 @@ static ImBuf *seq_render_scene_strip(const SeqRenderData *context,
re = RE_NewSceneRender(scene);
}
- RE_BlenderFrame(re, context->bmain, scene, view_layer, camera, frame, false);
+ RE_RenderFrame(re, context->bmain, scene, view_layer, camera, frame, false);
- /* restore previous state after it was toggled on & off by RE_BlenderFrame */
+ /* restore previous state after it was toggled on & off by RE_RenderFrame */
G.is_rendering = is_rendering;
}
@@ -5671,12 +5668,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/tracking_stabilize.c b/source/blender/blenkernel/intern/tracking_stabilize.c
index 1fe63e21e78..695f9b21559 100644
--- a/source/blender/blenkernel/intern/tracking_stabilize.c
+++ b/source/blender/blenkernel/intern/tracking_stabilize.c
@@ -275,10 +275,10 @@ static int search_closest_marker_index(MovieTrackingTrack *track, int ref_frame)
i = MAX2(0, i);
i = MIN2(i, end - 1);
for (; i < end - 1 && markers[i].framenr <= ref_frame; ++i) {
- ;
+ /* pass */
}
for (; 0 < i && markers[i].framenr > ref_frame; --i) {
- ;
+ /* pass */
}
track->last_marker = i;
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/blenkernel/intern/unit.c b/source/blender/blenkernel/intern/unit.c
index 293eed8cfe3..f5b73d88867 100644
--- a/source/blender/blenkernel/intern/unit.c
+++ b/source/blender/blenkernel/intern/unit.c
@@ -663,7 +663,7 @@ static const char *unit_find_str(const char *str, const char *substr, bool case_
}
/* If str_found is not a valid unit, we have to check further in the string... */
for (str_found++; isalpha_or_utf8(*str_found); str_found++) {
- ;
+ /* pass */
}
str = str_found;
}
diff --git a/source/blender/blenkernel/intern/workspace.c b/source/blender/blenkernel/intern/workspace.c
index f9584adc6e0..387d4ec5773 100644
--- a/source/blender/blenkernel/intern/workspace.c
+++ b/source/blender/blenkernel/intern/workspace.c
@@ -36,6 +36,7 @@
#include "DNA_object_types.h"
#include "DNA_scene_types.h"
#include "DNA_screen_types.h"
+#include "DNA_windowmanager_types.h"
#include "DNA_workspace_types.h"
#include "DEG_depsgraph.h"
@@ -43,7 +44,8 @@
#include "MEM_guardedalloc.h"
/* -------------------------------------------------------------------- */
-/* Internal utils */
+/** \name Internal Utils
+ * \{ */
static void workspace_layout_name_set(WorkSpace *workspace,
WorkSpaceLayout *layout,
@@ -134,8 +136,11 @@ static bool UNUSED_FUNCTION(workspaces_is_screen_used)
return false;
}
+/** \} */
+
/* -------------------------------------------------------------------- */
-/* Create, delete, init */
+/** \name Create, Delete, Init
+ * \{ */
WorkSpace *BKE_workspace_add(Main *bmain, const char *name)
{
@@ -253,8 +258,11 @@ void BKE_workspace_relations_free(ListBase *relation_list)
}
}
+/** \} */
+
/* -------------------------------------------------------------------- */
-/* General Utils */
+/** \name General Utils
+ * \{ */
WorkSpaceLayout *BKE_workspace_layout_find(const WorkSpace *workspace, const bScreen *screen)
{
@@ -348,14 +356,37 @@ void BKE_workspace_tool_remove(struct WorkSpace *workspace, struct bToolRef *tre
}
if (tref->properties) {
IDP_FreeProperty(tref->properties);
- MEM_freeN(tref->properties);
}
BLI_remlink(&workspace->tools, tref);
MEM_freeN(tref);
}
+bool BKE_workspace_owner_id_check(const WorkSpace *workspace, const char *owner_id)
+{
+ if ((*owner_id == '\0') || ((workspace->flags & WORKSPACE_USE_FILTER_BY_ORIGIN) == 0)) {
+ return true;
+ }
+ else {
+ /* We could use hash lookup, for now this list is highly likely under < ~16 items. */
+ return BLI_findstring(&workspace->owner_ids, owner_id, offsetof(wmOwnerID, name)) != NULL;
+ }
+}
+
+void BKE_workspace_id_tag_all_visible(Main *bmain, int tag)
+{
+ BKE_main_id_tag_listbase(&bmain->workspaces, tag, false);
+ wmWindowManager *wm = bmain->wm.first;
+ for (wmWindow *win = wm->windows.first; win; win = win->next) {
+ WorkSpace *workspace = BKE_workspace_active_get(win->workspace_hook);
+ workspace->id.tag |= tag;
+ }
+}
+
+/** \} */
+
/* -------------------------------------------------------------------- */
-/* Getters/Setters */
+/** \name Getters/Setters
+ * \{ */
WorkSpace *BKE_workspace_active_get(WorkSpaceInstanceHook *hook)
{
@@ -433,13 +464,4 @@ void BKE_workspace_hook_layout_for_workspace_set(WorkSpaceInstanceHook *hook,
workspace_relation_ensure_updated(&workspace->hook_layout_relations, hook, layout);
}
-bool BKE_workspace_owner_id_check(const WorkSpace *workspace, const char *owner_id)
-{
- if ((*owner_id == '\0') || ((workspace->flags & WORKSPACE_USE_FILTER_BY_ORIGIN) == 0)) {
- return true;
- }
- else {
- /* we could use hash lookup, for now this list is highly under < ~16 items. */
- return BLI_findstring(&workspace->owner_ids, owner_id, offsetof(wmOwnerID, name)) != NULL;
- }
-}
+/** \} */
diff --git a/source/blender/blenkernel/intern/writeavi.c b/source/blender/blenkernel/intern/writeavi.c
index b72b99e514d..19425a0d80b 100644
--- a/source/blender/blenkernel/intern/writeavi.c
+++ b/source/blender/blenkernel/intern/writeavi.c
@@ -118,7 +118,6 @@ bMovieHandle *BKE_movie_handle_get(const char imtype)
mh.start_movie = start_stub;
mh.append_movie = append_stub;
mh.end_movie = end_stub;
- mh.get_next_frame = NULL;
mh.get_movie_path = NULL;
mh.context_create = context_create_stub;
mh.context_free = context_free_stub;
diff --git a/source/blender/blenkernel/intern/writeffmpeg.c b/source/blender/blenkernel/intern/writeffmpeg.c
index a74d5b241ed..ae41b8f3272 100644
--- a/source/blender/blenkernel/intern/writeffmpeg.c
+++ b/source/blender/blenkernel/intern/writeffmpeg.c
@@ -1616,7 +1616,7 @@ static void ffmpeg_set_expert_options(RenderData *rd)
int codec_id = rd->ffcodecdata.codec;
if (rd->ffcodecdata.properties) {
- IDP_FreeProperty(rd->ffcodecdata.properties);
+ IDP_FreePropertyContent(rd->ffcodecdata.properties);
}
if (codec_id == AV_CODEC_ID_H264) {
@@ -1680,7 +1680,7 @@ void BKE_ffmpeg_preset_set(RenderData *rd, int preset)
int isntsc = (rd->frs_sec != 25);
if (rd->ffcodecdata.properties) {
- IDP_FreeProperty(rd->ffcodecdata.properties);
+ IDP_FreePropertyContent(rd->ffcodecdata.properties);
}
switch (preset) {
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_math_matrix.h b/source/blender/blenlib/BLI_math_matrix.h
index 652f096f32d..52d976daa2d 100644
--- a/source/blender/blenlib/BLI_math_matrix.h
+++ b/source/blender/blenlib/BLI_math_matrix.h
@@ -209,6 +209,7 @@ bool invert_m3(float R[3][3]);
bool invert_m3_m3(float R[3][3], const float A[3][3]);
bool invert_m4(float R[4][4]);
bool invert_m4_m4(float R[4][4], const float A[4][4]);
+bool invert_m4_m4_fallback(float R[4][4], const float A[4][4]);
/* double arithmetic (mixed float/double) */
void mul_m4_v4d(const float M[4][4], double r[4]);
@@ -260,6 +261,7 @@ float determinant_m2(float a, float b, float c, float d);
float determinant_m3(
float a, float b, float c, float d, float e, float f, float g, float h, float i);
float determinant_m3_array(const float m[3][3]);
+float determinant_m4_mat3_array(const float m[4][4]);
float determinant_m4(const float A[4][4]);
#define PSEUDOINVERSE_EPSILON 1e-8f
@@ -277,6 +279,9 @@ void invert_m4_m4_safe(float Ainv[4][4], const float A[4][4]);
void scale_m3_fl(float R[3][3], float scale);
void scale_m4_fl(float R[4][4], float scale);
+float mat3_to_volume_scale(const float M[3][3]);
+float mat4_to_volume_scale(const float M[4][4]);
+
float mat3_to_scale(const float M[3][3]);
float mat4_to_scale(const float M[4][4]);
float mat4_to_xy_scale(const float M[4][4]);
diff --git a/source/blender/blenlib/BLI_memblock.h b/source/blender/blenlib/BLI_memblock.h
new file mode 100644
index 00000000000..c5ef26ffb91
--- /dev/null
+++ b/source/blender/blenlib/BLI_memblock.h
@@ -0,0 +1,60 @@
+/*
+ * 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.
+ */
+
+#ifndef __BLI_MEMBLOCK_H__
+#define __BLI_MEMBLOCK_H__
+
+/** \file
+ * \ingroup bli
+ */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include "BLI_compiler_attrs.h"
+
+struct BLI_memblock;
+
+typedef struct BLI_memblock BLI_memblock;
+typedef void (*MemblockValFreeFP)(void *val);
+
+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 {
+ 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();
+void *BLI_memblock_iterstep(BLI_memblock_iter *iter) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __BLI_MEMBLOCK_H__ */
diff --git a/source/blender/blenlib/BLI_rand.h b/source/blender/blenlib/BLI_rand.h
index 151b02a33aa..eec4e885493 100644
--- a/source/blender/blenlib/BLI_rand.h
+++ b/source/blender/blenlib/BLI_rand.h
@@ -25,6 +25,10 @@
* \brief Random number functions.
*/
+#ifdef __cplusplus
+extern "C" {
+#endif
+
/* RNG is an abstract random number generator type that avoids using globals.
* Always use this instead of the global RNG unless you have a good reason,
* the global RNG is not thread safe and will not give repeatable results.
@@ -106,4 +110,8 @@ void BLI_hammersley_1d(unsigned int n, double *r);
void BLI_halton_2d_sequence(unsigned int prime[2], double offset[2], int n, double *r);
void BLI_hammersley_2d_sequence(unsigned int n, double *r);
+#ifdef __cplusplus
+}
+#endif
+
#endif /* __BLI_RAND_H__ */
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/BLI_system.h b/source/blender/blenlib/BLI_system.h
index 93ad0e1e70f..f4c0399e959 100644
--- a/source/blender/blenlib/BLI_system.h
+++ b/source/blender/blenlib/BLI_system.h
@@ -41,6 +41,10 @@ char *BLI_cpu_brand_string(void);
*/
void BLI_hostname_get(char *buffer, size_t bufsize);
+/* Get maximum addressable memory in megabytes. */
+size_t BLI_system_memory_max_in_megabytes(void);
+int BLI_system_memory_max_in_megabytes_int(void);
+
/* getpid */
#ifdef WIN32
# define BLI_SYSTEM_PID_H <process.h>
diff --git a/source/blender/blenlib/CMakeLists.txt b/source/blender/blenlib/CMakeLists.txt
index dbc72ff1213..0ec6e7ee4fc 100644
--- a/source/blender/blenlib/CMakeLists.txt
+++ b/source/blender/blenlib/CMakeLists.txt
@@ -48,6 +48,7 @@ set(SRC
intern/BLI_linklist.c
intern/BLI_linklist_lockfree.c
intern/BLI_memarena.c
+ intern/BLI_memblock.c
intern/BLI_memiter.c
intern/BLI_mempool.c
intern/BLI_timer.c
@@ -194,6 +195,7 @@ set(SRC
BLI_math_statistics.h
BLI_math_vector.h
BLI_memarena.h
+ BLI_memblock.h
BLI_memiter.h
BLI_memory_utils.h
BLI_mempool.h
diff --git a/source/blender/blenlib/intern/BLI_memarena.c b/source/blender/blenlib/intern/BLI_memarena.c
index b5815f7b503..0f7ac92a348 100644
--- a/source/blender/blenlib/intern/BLI_memarena.c
+++ b/source/blender/blenlib/intern/BLI_memarena.c
@@ -77,6 +77,10 @@ static void memarena_buf_free_all(struct MemBuf *mb)
{
while (mb != NULL) {
struct MemBuf *mb_next = mb->next;
+
+ /* Unpoison memory because MEM_freeN might overwrite it. */
+ ASAN_UNPOISON_MEMORY_REGION(mb, (uint)MEM_allocN_len(mb));
+
MEM_freeN(mb);
mb = mb_next;
}
diff --git a/source/blender/blenlib/intern/BLI_memblock.c b/source/blender/blenlib/intern/BLI_memblock.c
new file mode 100644
index 00000000000..ec9b74f2b50
--- /dev/null
+++ b/source/blender/blenlib/intern/BLI_memblock.c
@@ -0,0 +1,182 @@
+/*
+ * 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 by Blender Foundation.
+ * All rights reserved.
+ */
+
+/** \file
+ * \ingroup bli
+ *
+ * Dead simple, fast memory allocator for allocating many elements of the same size.
+ *
+ */
+
+#include <string.h>
+#include <stdlib.h>
+
+#include "atomic_ops.h"
+
+#include "BLI_utildefines.h"
+
+#include "BLI_memblock.h" /* own include */
+
+#include "MEM_guardedalloc.h"
+
+#include "BLI_strict_flags.h" /* keep last */
+
+#define BLI_MEM_BLOCK_CHUNK_SIZE (1 << 15) /* 32KiB */
+#define CHUNK_LIST_SIZE 16
+
+struct BLI_memblock {
+ void **chunk_list;
+
+ /** Element size in bytes. */
+ int elem_size;
+ /** First unused element index. */
+ 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;
+};
+
+BLI_memblock *BLI_memblock_create(uint elem_size)
+{
+ BLI_assert(elem_size < BLI_MEM_BLOCK_CHUNK_SIZE);
+
+ BLI_memblock *mblk = MEM_mallocN(sizeof(BLI_memblock), "BLI_memblock");
+ mblk->elem_size = (int)elem_size;
+ mblk->elem_next = 0;
+ mblk->elem_last = -1;
+ 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->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)
+{
+ BLI_memblock_clear(mblk, free_callback);
+
+ for (int i = 0; i < mblk->chunk_len; i++) {
+ MEM_SAFE_FREE(mblk->chunk_list[i]);
+ }
+ MEM_SAFE_FREE(mblk->chunk_list);
+ MEM_freeN(mblk);
+}
+
+/* Reset elem count to 0 but keep as much memory allocated needed for at least the previous elem
+ * count. */
+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 / elem_per_chunk;
+
+ if (free_callback) {
+ for (int i = mblk->elem_last; i >= mblk->elem_next; 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);
+ }
+ }
+
+ for (int i = last_used_chunk + 1; i < mblk->chunk_len; i++) {
+ MEM_SAFE_FREE(mblk->chunk_list[i]);
+ }
+
+ if (UNLIKELY(last_used_chunk + 1 < mblk->chunk_len - CHUNK_LIST_SIZE)) {
+ mblk->chunk_len -= CHUNK_LIST_SIZE;
+ mblk->chunk_list = MEM_recallocN(mblk->chunk_list, sizeof(void *) * (uint)mblk->chunk_len);
+ }
+
+ 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)
+{
+ /* Bookeeping. */
+ if (mblk->elem_last < mblk->elem_next) {
+ mblk->elem_last = mblk->elem_next;
+ }
+ mblk->elem_next++;
+
+ 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_next >= mblk->chunk_len)) {
+ mblk->chunk_len += CHUNK_LIST_SIZE;
+ mblk->chunk_list = MEM_recallocN(mblk->chunk_list, sizeof(void *) * (uint)mblk->chunk_len);
+ }
+
+ 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 ptr;
+}
+
+void BLI_memblock_iternew(BLI_memblock *mblk, BLI_memblock_iter *iter)
+{
+ /* 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->cur_index == iter->end_index) {
+ return NULL;
+ }
+
+ iter->cur_index++;
+
+ void *ptr = (char *)(iter->chunk_list[iter->chunk_idx]) + iter->elem_ofs;
+
+ 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..2d3ba56d08e 100644
--- a/source/blender/blenlib/intern/BLI_memiter.c
+++ b/source/blender/blenlib/intern/BLI_memiter.c
@@ -239,6 +239,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/expr_pylike_eval.c b/source/blender/blenlib/intern/expr_pylike_eval.c
index 6dc0203ead2..49c7fb19b7d 100644
--- a/source/blender/blenlib/intern/expr_pylike_eval.c
+++ b/source/blender/blenlib/intern/expr_pylike_eval.c
@@ -164,7 +164,8 @@ eExprPyLike_EvalStatus BLI_expr_pylike_eval(ExprPyLike_Parsed *expr,
#define FAIL_IF(condition) \
if (condition) { \
return EXPR_PYLIKE_FATAL_ERROR; \
- }
+ } \
+ ((void)0)
/* Check the stack requirement is at least remotely sane and allocate on the actual stack. */
FAIL_IF(expr->max_stack <= 0 || expr->max_stack > 1000);
@@ -391,7 +392,8 @@ static BuiltinOpDef builtin_ops[] = {
#define CHECK_ERROR(condition) \
if (!(condition)) { \
return false; \
- }
+ } \
+ ((void)0)
/* For simplicity simple token types are represented by their own character;
* these are special identifiers for multi-character tokens. */
diff --git a/source/blender/blenlib/intern/math_matrix.c b/source/blender/blenlib/intern/math_matrix.c
index e09fae7d140..6ac1ac776b3 100644
--- a/source/blender/blenlib/intern/math_matrix.c
+++ b/source/blender/blenlib/intern/math_matrix.c
@@ -931,6 +931,13 @@ float determinant_m3_array(const float m[3][3])
m[2][0] * (m[0][1] * m[1][2] - m[0][2] * m[1][1]));
}
+float determinant_m4_mat3_array(const float m[4][4])
+{
+ return (m[0][0] * (m[1][1] * m[2][2] - m[1][2] * m[2][1]) -
+ m[1][0] * (m[0][1] * m[2][2] - m[0][2] * m[2][1]) +
+ m[2][0] * (m[0][1] * m[1][2] - m[0][2] * m[1][1]));
+}
+
bool invert_m3_ex(float m[3][3], const float epsilon)
{
float tmp[3][3];
@@ -1011,6 +1018,81 @@ bool invert_m4(float m[4][4])
return success;
}
+/**
+ * Computes the inverse of mat and puts it in inverse.
+ * Uses Gaussian Elimination with partial (maximal column) pivoting.
+ * \return true on success (i.e. can always find a pivot) and false on failure.
+ * Mark Segal - 1992.
+ *
+ * \note this is less performant than #EIG_invert_m4_m4 (Eigen), but e.g.
+ * for non-invertible scale matrices, findinging a partial solution can
+ * be useful to have a valid local transform center, see T57767.
+ */
+bool invert_m4_m4_fallback(float inverse[4][4], const float mat[4][4])
+{
+ if (EIG_invert_m4_m4(inverse, mat)) {
+ return true;
+ }
+
+ int i, j, k;
+ double temp;
+ float tempmat[4][4];
+ float max;
+ int maxj;
+
+ BLI_assert(inverse != mat);
+
+ /* Set inverse to identity */
+ for (i = 0; i < 4; i++)
+ for (j = 0; j < 4; j++)
+ inverse[i][j] = 0;
+ for (i = 0; i < 4; i++)
+ inverse[i][i] = 1;
+
+ /* Copy original matrix so we don't mess it up */
+ for (i = 0; i < 4; i++)
+ for (j = 0; j < 4; j++)
+ tempmat[i][j] = mat[i][j];
+
+ for (i = 0; i < 4; i++) {
+ /* Look for row with max pivot */
+ max = fabsf(tempmat[i][i]);
+ maxj = i;
+ for (j = i + 1; j < 4; j++) {
+ if (fabsf(tempmat[j][i]) > max) {
+ max = fabsf(tempmat[j][i]);
+ maxj = j;
+ }
+ }
+ /* Swap rows if necessary */
+ if (maxj != i) {
+ for (k = 0; k < 4; k++) {
+ SWAP(float, tempmat[i][k], tempmat[maxj][k]);
+ SWAP(float, inverse[i][k], inverse[maxj][k]);
+ }
+ }
+
+ if (UNLIKELY(tempmat[i][i] == 0.0f)) {
+ return false; /* No non-zero pivot */
+ }
+ temp = (double)tempmat[i][i];
+ for (k = 0; k < 4; k++) {
+ tempmat[i][k] = (float)((double)tempmat[i][k] / temp);
+ inverse[i][k] = (float)((double)inverse[i][k] / temp);
+ }
+ for (j = 0; j < 4; j++) {
+ if (j != i) {
+ temp = tempmat[j][i];
+ for (k = 0; k < 4; k++) {
+ tempmat[j][k] -= (float)((double)tempmat[i][k] * temp);
+ inverse[j][k] -= (float)((double)inverse[i][k] * temp);
+ }
+ }
+ }
+ }
+ return true;
+}
+
bool invert_m4_m4(float inverse[4][4], const float mat[4][4])
{
/* Use optimized matrix inverse from Eigen, since performance
@@ -1641,9 +1723,26 @@ void mat4_to_size(float size[3], const float mat[4][4])
size[2] = len_v3(mat[2]);
}
-/* this gets the average scale of a matrix, only use when your scaling
+/**
+ * This computes the overall volume scale factor of a transformation matrix.
+ * For an orthogonal matrix, it is the product of all three scale values.
+ * Returns a negative value if the transform is flipped by negative scale.
+ */
+float mat3_to_volume_scale(const float mat[3][3])
+{
+ return determinant_m3_array(mat);
+}
+
+float mat4_to_volume_scale(const float mat[4][4])
+{
+ return determinant_m4_mat3_array(mat);
+}
+
+/**
+ * This gets the average scale of a matrix, only use when your scaling
* data that has no idea of scale axis, examples are bone-envelope-radius
- * and curve radius */
+ * and curve radius.
+ */
float mat3_to_scale(const float mat[3][3])
{
/* unit length vector */
@@ -2003,10 +2102,12 @@ bool equals_m4m4(const float mat1[4][4], const float mat2[4][4])
equals_v4v4(mat1[2], mat2[2]) && equals_v4v4(mat1[3], mat2[3]));
}
-/* make a 4x4 matrix out of 3 transform components */
-/* matrices are made in the order: scale * rot * loc */
-/* TODO: need to have a version that allows for rotation order... */
-
+/**
+ * Make a 4x4 matrix out of 3 transform components.
+ * Matrices are made in the order: `scale * rot * loc`
+ *
+ * TODO: need to have a version that allows for rotation order...
+ */
void loc_eul_size_to_mat4(float mat[4][4],
const float loc[3],
const float eul[3],
@@ -2031,9 +2132,10 @@ void loc_eul_size_to_mat4(float mat[4][4],
mat[3][2] = loc[2];
}
-/* make a 4x4 matrix out of 3 transform components */
-
-/* matrices are made in the order: scale * rot * loc */
+/**
+ * Make a 4x4 matrix out of 3 transform components.
+ * Matrices are made in the order: `scale * rot * loc`
+ */
void loc_eulO_size_to_mat4(float mat[4][4],
const float loc[3],
const float eul[3],
@@ -2059,9 +2161,10 @@ void loc_eulO_size_to_mat4(float mat[4][4],
mat[3][2] = loc[2];
}
-/* make a 4x4 matrix out of 3 transform components */
-
-/* matrices are made in the order: scale * rot * loc */
+/**
+ * Make a 4x4 matrix out of 3 transform components.
+ * Matrices are made in the order: `scale * rot * loc`
+ */
void loc_quat_size_to_mat4(float mat[4][4],
const float loc[3],
const float quat[4],
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 d23b45a3937..3348912f02a 100644
--- a/source/blender/blenlib/intern/system.c
+++ b/source/blender/blenlib/intern/system.c
@@ -18,10 +18,12 @@
* \ingroup bli
*/
+#include <limits.h>
#include <stdio.h>
#include <stdlib.h>
#include "BLI_utildefines.h"
+#include "BLI_math_base.h"
#include "BLI_system.h"
#include "BLI_string.h"
@@ -189,3 +191,20 @@ void BLI_hostname_get(char *buffer, size_t bufsize)
}
#endif
}
+
+size_t BLI_system_memory_max_in_megabytes(void)
+{
+ /* Maximum addressable bytes on this platform.
+ *
+ * NOTE: Due to the shift arithmetic this is a half of the memory. */
+ const size_t limit_bytes_half = (((size_t)1) << ((sizeof(size_t) * 8) - 1));
+ /* Convert it to megabytes and return. */
+ return (limit_bytes_half >> 20) * 2;
+}
+
+int BLI_system_memory_max_in_megabytes_int(void)
+{
+ const size_t limit_megabytes = BLI_system_memory_max_in_megabytes();
+ /* NOTE: The result will fit into integer. */
+ return (int)min_zz(limit_megabytes, (size_t)INT_MAX);
+}
diff --git a/source/blender/blenloader/intern/readfile.c b/source/blender/blenloader/intern/readfile.c
index 7f62369647a..5edba272cd4 100644
--- a/source/blender/blenloader/intern/readfile.c
+++ b/source/blender/blenloader/intern/readfile.c
@@ -2537,7 +2537,7 @@ static void _IDP_DirectLinkGroup_OrFree(IDProperty **prop,
/* corrupt file! */
printf("%s: found non group data, freeing type %d!\n", caller_func_id, (*prop)->type);
/* don't risk id, data's likely corrupt. */
- // IDP_FreeProperty(*prop);
+ // IDP_FreePropertyContent(*prop);
*prop = NULL;
}
}
@@ -3763,9 +3763,6 @@ static void lib_link_pose(FileData *fd, Main *bmain, Object *ob, bPose *pose)
}
}
- /* avoid string */
- GHash *bone_hash = BKE_armature_bone_from_name_map(arm);
-
if (ob->proxy) {
/* sync proxy layer */
if (pose->proxy_layer) {
@@ -3774,7 +3771,7 @@ static void lib_link_pose(FileData *fd, Main *bmain, Object *ob, bPose *pose)
/* sync proxy active bone */
if (pose->proxy_act_bone[0]) {
- Bone *bone = BLI_ghash_lookup(bone_hash, pose->proxy_act_bone);
+ Bone *bone = BKE_armature_find_bone_name(arm, pose->proxy_act_bone);
if (bone) {
arm->act_bone = bone;
}
@@ -3784,7 +3781,7 @@ static void lib_link_pose(FileData *fd, Main *bmain, Object *ob, bPose *pose)
for (bPoseChannel *pchan = pose->chanbase.first; pchan; pchan = pchan->next) {
lib_link_constraints(fd, (ID *)ob, &pchan->constraints);
- pchan->bone = BLI_ghash_lookup(bone_hash, pchan->name);
+ pchan->bone = BKE_armature_find_bone_name(arm, pchan->name);
IDP_LibLinkProperty(pchan->prop, fd);
@@ -3799,8 +3796,6 @@ static void lib_link_pose(FileData *fd, Main *bmain, Object *ob, bPose *pose)
}
}
- BLI_ghash_free(bone_hash, NULL, NULL);
-
if (rebuild) {
DEG_id_tag_update_ex(
bmain, &ob->id, ID_RECALC_TRANSFORM | ID_RECALC_GEOMETRY | ID_RECALC_ANIMATION);
@@ -3858,6 +3853,7 @@ static void direct_link_armature(FileData *fd, bArmature *arm)
Bone *bone;
link_list(fd, &arm->bonebase);
+ arm->bonehash = NULL;
arm->edbo = NULL;
arm->adt = newdataadr(fd, arm->adt);
@@ -3869,6 +3865,8 @@ static void direct_link_armature(FileData *fd, bArmature *arm)
arm->act_bone = newdataadr(fd, arm->act_bone);
arm->act_edbone = NULL;
+
+ BKE_armature_bone_hash_make(arm);
}
/** \} */
@@ -3884,9 +3882,10 @@ static void lib_link_camera(FileData *fd, Main *main)
IDP_LibLinkProperty(ca->id.properties, fd);
lib_link_animdata(fd, &ca->id, ca->adt);
- ca->ipo = newlibadr_us(fd, ca->id.lib, ca->ipo); // XXX deprecated - old animation system
+ ca->ipo = newlibadr_us(fd, ca->id.lib, ca->ipo); /* deprecated, for versioning */
- ca->dof_ob = newlibadr(fd, ca->id.lib, ca->dof_ob);
+ ca->dof_ob = newlibadr(fd, ca->id.lib, ca->dof_ob); /* deprecated, for versioning */
+ ca->dof.focus_object = newlibadr(fd, ca->id.lib, ca->dof.focus_object);
for (CameraBGImage *bgpic = ca->bg_images.first; bgpic; bgpic = bgpic->next) {
bgpic->ima = newlibadr_us(fd, ca->id.lib, bgpic->ima);
@@ -6629,6 +6628,13 @@ static void direct_link_paint(FileData *fd, const Scene *scene, Paint *p)
p->tool_slots = newdataadr(fd, p->tool_slots);
+ /* Workaround for invalid data written in older versions. */
+ const size_t expected_size = sizeof(PaintToolSlot) * p->tool_slots_len;
+ if (p->tool_slots && MEM_allocN_len(p->tool_slots) < expected_size) {
+ MEM_freeN(p->tool_slots);
+ p->tool_slots = MEM_callocN(expected_size, "PaintToolSlot");
+ }
+
BKE_paint_runtime_init(scene->toolsettings, p);
}
@@ -7101,7 +7107,6 @@ static void direct_link_panel_list(FileData *fd, ListBase *lb)
link_list(fd, lb);
for (Panel *pa = lb->first; pa; pa = pa->next) {
- pa->paneltab = newdataadr(fd, pa->paneltab);
pa->runtime_flag = 0;
pa->activedata = NULL;
pa->type = NULL;
@@ -9602,6 +9607,9 @@ static BHead *read_userdef(BlendFileData *bfd, FileData *fd, BHead *bhead)
/* Don't read the active app template, use the default one. */
user->app_template[0] = '\0';
+ /* Clear runtime data. */
+ user->runtime.is_dirty = false;
+
/* free fd->datamap again */
oldnewmap_free_unused(fd->datamap);
oldnewmap_clear(fd->datamap);
@@ -9622,14 +9630,17 @@ BlendFileData *blo_read_file_internal(FileData *fd, const char *filepath)
ListBase mainlist = {NULL, NULL};
bfd = MEM_callocN(sizeof(BlendFileData), "blendfiledata");
- bfd->main = BKE_main_new();
- BLI_addtail(&mainlist, bfd->main);
- fd->mainlist = &mainlist;
+ bfd->main = BKE_main_new();
bfd->main->versionfile = fd->fileversion;
bfd->type = BLENFILETYPE_BLEND;
- BLI_strncpy(bfd->main->name, filepath, sizeof(bfd->main->name));
+
+ if ((fd->skip_flags & BLO_READ_SKIP_DATA) == 0) {
+ BLI_addtail(&mainlist, bfd->main);
+ fd->mainlist = &mainlist;
+ BLI_strncpy(bfd->main->name, filepath, sizeof(bfd->main->name));
+ }
if (G.background) {
/* We only read & store .blend thumbnail in background mode
@@ -9707,45 +9718,52 @@ BlendFileData *blo_read_file_internal(FileData *fd, const char *filepath)
/* do before read_libraries, but skip undo case */
if (fd->memfile == NULL) {
- do_versions(fd, NULL, bfd->main);
- do_versions_userdef(fd, bfd);
+ if ((fd->skip_flags & BLO_READ_SKIP_DATA) == 0) {
+ do_versions(fd, NULL, bfd->main);
+ }
+
+ if ((fd->skip_flags & BLO_READ_SKIP_USERDEF) == 0) {
+ do_versions_userdef(fd, bfd);
+ }
}
- read_libraries(fd, &mainlist);
+ if ((fd->skip_flags & BLO_READ_SKIP_DATA) == 0) {
+ read_libraries(fd, &mainlist);
- blo_join_main(&mainlist);
+ blo_join_main(&mainlist);
- lib_link_all(fd, bfd->main);
+ lib_link_all(fd, bfd->main);
- /* Skip in undo case. */
- if (fd->memfile == NULL) {
- /* Yep, second splitting... but this is a very cheap operation, so no big deal. */
- blo_split_main(&mainlist, bfd->main);
- for (Main *mainvar = mainlist.first; mainvar; mainvar = mainvar->next) {
- BLI_assert(mainvar->versionfile != 0);
- do_versions_after_linking(mainvar);
- }
- blo_join_main(&mainlist);
+ /* Skip in undo case. */
+ if (fd->memfile == NULL) {
+ /* Yep, second splitting... but this is a very cheap operation, so no big deal. */
+ blo_split_main(&mainlist, bfd->main);
+ for (Main *mainvar = mainlist.first; mainvar; mainvar = mainvar->next) {
+ BLI_assert(mainvar->versionfile != 0);
+ do_versions_after_linking(mainvar);
+ }
+ blo_join_main(&mainlist);
- /* After all data has been read and versioned, uses LIB_TAG_NEW. */
- ntreeUpdateAllNew(bfd->main);
- }
+ /* After all data has been read and versioned, uses LIB_TAG_NEW. */
+ ntreeUpdateAllNew(bfd->main);
+ }
- BKE_main_id_tag_all(bfd->main, LIB_TAG_NEW, false);
+ BKE_main_id_tag_all(bfd->main, LIB_TAG_NEW, false);
- /* Now that all our data-blocks are loaded,
- * we can re-generate overrides from their references. */
- if (fd->memfile == NULL) {
- /* Do not apply in undo case! */
- BKE_main_override_static_update(bfd->main);
- }
+ /* Now that all our data-blocks are loaded,
+ * we can re-generate overrides from their references. */
+ if (fd->memfile == NULL) {
+ /* Do not apply in undo case! */
+ BKE_main_override_static_update(bfd->main);
+ }
- BKE_collections_after_lib_link(bfd->main);
+ BKE_collections_after_lib_link(bfd->main);
- fix_relpaths_library(fd->relabase,
- bfd->main); /* make all relative paths, relative to the open blend file */
+ /* Make all relative paths, relative to the open blend file. */
+ fix_relpaths_library(fd->relabase, bfd->main);
- link_global(fd, bfd); /* as last */
+ link_global(fd, bfd); /* as last */
+ }
fd->mainlist = NULL; /* Safety, this is local variable, shall not be used afterward. */
@@ -10757,6 +10775,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_250.c b/source/blender/blenloader/intern/versioning_250.c
index face4b61d1e..7b239105251 100644
--- a/source/blender/blenloader/intern/versioning_250.c
+++ b/source/blender/blenloader/intern/versioning_250.c
@@ -285,8 +285,8 @@ static void area_add_window_regions(ScrArea *sa, SpaceLink *sl, ListBase *lb)
memcpy(&ar->v2d, &sipo->v2d, sizeof(View2D));
/* init mainarea view2d */
- ar->v2d.scroll |= (V2D_SCROLL_BOTTOM | V2D_SCROLL_SCALE_HORIZONTAL);
- ar->v2d.scroll |= (V2D_SCROLL_LEFT | V2D_SCROLL_SCALE_VERTICAL);
+ ar->v2d.scroll |= (V2D_SCROLL_BOTTOM | V2D_SCROLL_HORIZONTAL_HANDLES);
+ ar->v2d.scroll |= (V2D_SCROLL_LEFT | V2D_SCROLL_VERTICAL_HANDLES);
ar->v2d.min[0] = FLT_MIN;
ar->v2d.min[1] = FLT_MIN;
@@ -304,7 +304,7 @@ static void area_add_window_regions(ScrArea *sa, SpaceLink *sl, ListBase *lb)
ar->v2d.tot.ymin = (float)(-sa->winy) / 3.0f;
ar->v2d.tot.ymax = 0.0f;
- ar->v2d.scroll |= (V2D_SCROLL_BOTTOM | V2D_SCROLL_SCALE_HORIZONTAL);
+ ar->v2d.scroll |= (V2D_SCROLL_BOTTOM | V2D_SCROLL_HORIZONTAL_HANDLES);
ar->v2d.scroll |= (V2D_SCROLL_RIGHT);
ar->v2d.align = V2D_ALIGN_NO_POS_Y;
ar->v2d.flag |= V2D_VIEWSYNC_AREA_VERTICAL;
@@ -330,7 +330,7 @@ static void area_add_window_regions(ScrArea *sa, SpaceLink *sl, ListBase *lb)
ar->v2d.minzoom = 0.01f;
ar->v2d.maxzoom = 50;
- ar->v2d.scroll = (V2D_SCROLL_BOTTOM | V2D_SCROLL_SCALE_HORIZONTAL);
+ ar->v2d.scroll = (V2D_SCROLL_BOTTOM | V2D_SCROLL_HORIZONTAL_HANDLES);
ar->v2d.scroll |= (V2D_SCROLL_RIGHT);
ar->v2d.keepzoom = V2D_LOCKZOOM_Y;
ar->v2d.align = V2D_ALIGN_NO_POS_Y;
@@ -349,8 +349,8 @@ static void area_add_window_regions(ScrArea *sa, SpaceLink *sl, ListBase *lb)
SpaceSeq *sseq = (SpaceSeq *)sl;
memcpy(&ar->v2d, &sseq->v2d, sizeof(View2D));
- ar->v2d.scroll |= (V2D_SCROLL_BOTTOM | V2D_SCROLL_SCALE_HORIZONTAL);
- ar->v2d.scroll |= (V2D_SCROLL_LEFT | V2D_SCROLL_SCALE_VERTICAL);
+ ar->v2d.scroll |= (V2D_SCROLL_BOTTOM | V2D_SCROLL_HORIZONTAL_HANDLES);
+ ar->v2d.scroll |= (V2D_SCROLL_LEFT | V2D_SCROLL_VERTICAL_HANDLES);
ar->v2d.align = V2D_ALIGN_NO_NEG_Y;
ar->v2d.flag |= V2D_IS_INITIALISED;
break;
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 f9f87731197..c4e3390d65f 100644
--- a/source/blender/blenloader/intern/versioning_280.c
+++ b/source/blender/blenloader/intern/versioning_280.c
@@ -421,10 +421,13 @@ static void do_version_layers_to_collections(Main *bmain, Scene *scene)
Collection *collection = BKE_collection_add(bmain, collection_master, name);
collection->id.lib = scene->id.lib;
+ if (collection->id.lib != NULL) {
+ collection->id.tag |= LIB_TAG_INDIRECT;
+ }
collections[layer] = collection;
if (!(scene->lay & (1 << layer))) {
- collection->flag |= COLLECTION_RESTRICT_VIEW | COLLECTION_RESTRICT_RENDER;
+ collection->flag |= COLLECTION_RESTRICT_VIEWPORT | COLLECTION_RESTRICT_RENDER;
}
}
@@ -692,6 +695,26 @@ static void do_version_bbone_scale_animdata_cb(ID *UNUSED(id),
}
}
+static void do_version_constraints_maintain_volume_mode_uniform(ListBase *lb)
+{
+ for (bConstraint *con = lb->first; con; con = con->next) {
+ if (con->type == CONSTRAINT_TYPE_SAMEVOL) {
+ bSameVolumeConstraint *data = (bSameVolumeConstraint *)con->data;
+ data->mode = SAMEVOL_UNIFORM;
+ }
+ }
+}
+
+static void do_version_constraints_copy_scale_power(ListBase *lb)
+{
+ for (bConstraint *con = lb->first; con; con = con->next) {
+ if (con->type == CONSTRAINT_TYPE_SIZELIKE) {
+ bSizeLikeConstraint *data = (bSizeLikeConstraint *)con->data;
+ data->power = 1.0f;
+ }
+ }
+}
+
void do_versions_after_linking_280(Main *bmain)
{
bool use_collection_compat_28 = true;
@@ -705,7 +728,7 @@ void do_versions_after_linking_280(Main *bmain)
/* Add fake user for all existing groups. */
id_fake_user_set(&collection->id);
- if (collection->flag & (COLLECTION_RESTRICT_VIEW | COLLECTION_RESTRICT_RENDER)) {
+ if (collection->flag & (COLLECTION_RESTRICT_VIEWPORT | COLLECTION_RESTRICT_RENDER)) {
continue;
}
@@ -731,7 +754,8 @@ void do_versions_after_linking_280(Main *bmain)
char name[MAX_ID_NAME];
BLI_snprintf(name, sizeof(name), DATA_("Hidden %d"), coll_idx + 1);
*collection_hidden = BKE_collection_add(bmain, collection, name);
- (*collection_hidden)->flag |= COLLECTION_RESTRICT_VIEW | COLLECTION_RESTRICT_RENDER;
+ (*collection_hidden)->flag |= COLLECTION_RESTRICT_VIEWPORT |
+ COLLECTION_RESTRICT_RENDER;
}
BKE_collection_object_add(bmain, *collection_hidden, ob);
@@ -826,7 +850,6 @@ void do_versions_after_linking_280(Main *bmain)
for (SceneRenderLayer *srl = scene->r.layers.first; srl; srl = srl->next) {
if (srl->prop) {
IDP_FreeProperty(srl->prop);
- MEM_freeN(srl->prop);
}
BKE_freestyle_config_free(&srl->freestyleConfig, true);
}
@@ -1061,6 +1084,32 @@ void do_versions_after_linking_280(Main *bmain)
BKE_rigidbody_constraints_collection_validate(scene, rbw);
}
}
+
+ if (!MAIN_VERSION_ATLEAST(bmain, 280, 69)) {
+ /* Unify DOF settings (EEVEE part only) */
+ const int SCE_EEVEE_DOF_ENABLED = (1 << 7);
+ LISTBASE_FOREACH (Scene *, scene, &bmain->scenes) {
+ if (STREQ(scene->r.engine, RE_engine_id_BLENDER_EEVEE)) {
+ if (scene->eevee.flag & SCE_EEVEE_DOF_ENABLED) {
+ Object *cam_ob = scene->camera;
+ if (cam_ob && cam_ob->type == OB_CAMERA) {
+ Camera *cam = cam_ob->data;
+ cam->dof.flag |= CAM_DOF_ENABLED;
+ }
+ }
+ }
+ }
+
+ LISTBASE_FOREACH (Camera *, camera, &bmain->cameras) {
+ camera->dof.focus_object = camera->dof_ob;
+ camera->dof.focus_distance = camera->dof_distance;
+ camera->dof.aperture_fstop = camera->gpu_dof.fstop;
+ camera->dof.aperture_rotation = camera->gpu_dof.rotation;
+ camera->dof.aperture_ratio = camera->gpu_dof.ratio;
+ camera->dof.aperture_blades = camera->gpu_dof.num_blades;
+ camera->dof_ob = NULL;
+ }
+ }
}
/* NOTE: This version patch is intended for versions < 2.52.2,
@@ -1290,6 +1339,16 @@ void blo_do_versions_280(FileData *fd, Library *UNUSED(lib), Main *bmain)
}
}
}
+
+ /* 2.79 style Maintain Volume mode. */
+ LISTBASE_FOREACH (Object *, ob, &bmain->objects) {
+ do_version_constraints_maintain_volume_mode_uniform(&ob->constraints);
+ if (ob->pose) {
+ LISTBASE_FOREACH (bPoseChannel *, pchan, &ob->pose->chanbase) {
+ do_version_constraints_maintain_volume_mode_uniform(&pchan->constraints);
+ }
+ }
+ }
}
#ifdef USE_COLLECTION_COMPAT_28
@@ -1637,10 +1696,10 @@ void blo_do_versions_280(FileData *fd, Library *UNUSED(lib), Main *bmain)
} \
} \
((void)0)
-
+ const int SCE_EEVEE_DOF_ENABLED = (1 << 7);
IDProperty *props = IDP_GetPropertyFromGroup(scene->layer_properties,
RE_engine_id_BLENDER_EEVEE);
- EEVEE_GET_BOOL(props, volumetric_enable, SCE_EEVEE_VOLUMETRIC_ENABLED);
+ // EEVEE_GET_BOOL(props, volumetric_enable, SCE_EEVEE_VOLUMETRIC_ENABLED);
EEVEE_GET_BOOL(props, volumetric_lights, SCE_EEVEE_VOLUMETRIC_LIGHTS);
EEVEE_GET_BOOL(props, volumetric_shadows, SCE_EEVEE_VOLUMETRIC_SHADOWS);
EEVEE_GET_BOOL(props, gtao_enable, SCE_EEVEE_GTAO_ENABLED);
@@ -1651,7 +1710,7 @@ void blo_do_versions_280(FileData *fd, Library *UNUSED(lib), Main *bmain)
EEVEE_GET_BOOL(props, motion_blur_enable, SCE_EEVEE_MOTION_BLUR_ENABLED);
EEVEE_GET_BOOL(props, shadow_high_bitdepth, SCE_EEVEE_SHADOW_HIGH_BITDEPTH);
EEVEE_GET_BOOL(props, taa_reprojection, SCE_EEVEE_TAA_REPROJECTION);
- EEVEE_GET_BOOL(props, sss_enable, SCE_EEVEE_SSS_ENABLED);
+ // EEVEE_GET_BOOL(props, sss_enable, SCE_EEVEE_SSS_ENABLED);
EEVEE_GET_BOOL(props, sss_separate_albedo, SCE_EEVEE_SSS_SEPARATE_ALBEDO);
EEVEE_GET_BOOL(props, ssr_enable, SCE_EEVEE_SSR_ENABLED);
EEVEE_GET_BOOL(props, ssr_refraction, SCE_EEVEE_SSR_REFRACTION);
@@ -1705,7 +1764,6 @@ void blo_do_versions_280(FileData *fd, Library *UNUSED(lib), Main *bmain)
/* Cleanup. */
IDP_FreeProperty(scene->layer_properties);
- MEM_freeN(scene->layer_properties);
scene->layer_properties = NULL;
#undef EEVEE_GET_FLOAT_ARRAY
@@ -2816,7 +2874,7 @@ void blo_do_versions_280(FileData *fd, Library *UNUSED(lib), Main *bmain)
}
for (Material *mat = bmain->materials.first; mat; mat = mat->id.next) {
- mat->blend_flag &= ~(MA_BL_FLAG_UNUSED_2);
+ mat->blend_flag &= ~(1 << 2); /* UNUSED */
}
}
@@ -3287,6 +3345,12 @@ void blo_do_versions_280(FileData *fd, Library *UNUSED(lib), Main *bmain)
}
}
}
+ if (!DNA_struct_elem_find(fd->filesdna, "SceneDisplay", "char", "render_aa")) {
+ LISTBASE_FOREACH (Scene *, scene, &bmain->scenes) {
+ scene->display.render_aa = SCE_DISPLAY_AA_SAMPLES_8;
+ scene->display.viewport_aa = SCE_DISPLAY_AA_FXAA;
+ }
+ }
/* Split bbone_scalein/bbone_scaleout into x and y fields. */
if (!DNA_struct_elem_find(fd->filesdna, "bPoseChannel", "float", "scale_out_y")) {
@@ -3321,6 +3385,108 @@ void blo_do_versions_280(FileData *fd, Library *UNUSED(lib), Main *bmain)
}
}
+ if (!MAIN_VERSION_ATLEAST(bmain, 280, 61)) {
+ /* Added a power option to Copy Scale. */
+ if (!DNA_struct_elem_find(fd->filesdna, "bSizeLikeConstraint", "float", "power")) {
+ LISTBASE_FOREACH (Object *, ob, &bmain->objects) {
+ do_version_constraints_copy_scale_power(&ob->constraints);
+ if (ob->pose) {
+ LISTBASE_FOREACH (bPoseChannel *, pchan, &ob->pose->chanbase) {
+ do_version_constraints_copy_scale_power(&pchan->constraints);
+ }
+ }
+ }
+ }
+
+ 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 (ELEM(sl->spacetype, SPACE_CLIP, SPACE_GRAPH, SPACE_SEQ)) {
+ ListBase *regionbase = (sl == sa->spacedata.first) ? &sa->regionbase : &sl->regionbase;
+
+ ARegion *ar = NULL;
+ if (sl->spacetype == SPACE_CLIP) {
+ if (((SpaceClip *)sl)->view == SC_VIEW_GRAPH) {
+ ar = do_versions_find_region(regionbase, RGN_TYPE_PREVIEW);
+ }
+ }
+ else {
+ ar = do_versions_find_region(regionbase, RGN_TYPE_WINDOW);
+ }
+
+ if (ar != NULL) {
+ ar->v2d.scroll &= ~V2D_SCROLL_LEFT;
+ ar->v2d.scroll |= V2D_SCROLL_RIGHT;
+ }
+ }
+ }
+ }
+ }
+
+ for (bScreen *screen = bmain->screens.first; screen; screen = screen->id.next) {
+ for (ScrArea *area = screen->areabase.first; area; area = area->next) {
+ for (SpaceLink *sl = area->spacedata.first; sl; sl = sl->next) {
+ if (sl->spacetype != SPACE_OUTLINER) {
+ continue;
+ }
+ SpaceOutliner *so = (SpaceOutliner *)sl;
+ so->filter &= ~SO_FLAG_UNUSED_1;
+ so->show_restrict_flags = SO_RESTRICT_ENABLE | SO_RESTRICT_HIDE;
+ }
+ }
+ }
+ }
+
+ if (!MAIN_VERSION_ATLEAST(bmain, 280, 69)) {
+ LISTBASE_FOREACH (bArmature *, arm, &bmain->armatures) {
+ arm->flag &= ~(ARM_FLAG_UNUSED_7 | ARM_FLAG_UNUSED_9);
+ }
+
+ /* Initializes sun lights with the new angular diameter property */
+ if (!DNA_struct_elem_find(fd->filesdna, "Light", "float", "sun_angle")) {
+ LISTBASE_FOREACH (Light *, light, &bmain->lights) {
+ light->sun_angle = 2.0f * atanf(light->area_size);
+ }
+ }
+ }
+
+ 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");
+ }
+ }
+ }
+
{
/* 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 023bd685352..9bfbf4477ab 100644
--- a/source/blender/blenloader/intern/versioning_cycles.c
+++ b/source/blender/blenloader/intern/versioning_cycles.c
@@ -32,12 +32,15 @@
#include "DNA_light_types.h"
#include "DNA_node_types.h"
#include "DNA_particle_types.h"
+#include "DNA_camera_types.h"
#include "BKE_colortools.h"
#include "BKE_idprop.h"
#include "BKE_main.h"
#include "BKE_node.h"
+#include "IMB_colormanagement.h"
+
#include "BLO_readfile.h"
#include "readfile.h"
@@ -47,6 +50,12 @@ static float *cycles_node_socket_float_value(bNodeSocket *socket)
return &socket_data->value;
}
+static float *cycles_node_socket_rgba_value(bNodeSocket *socket)
+{
+ bNodeSocketValueRGBA *socket_data = socket->default_value;
+ return socket_data->value;
+}
+
static IDProperty *cycles_properties_from_ID(ID *id)
{
IDProperty *idprop = IDP_GetProperties(id, false);
@@ -59,12 +68,26 @@ static float cycles_property_float(IDProperty *idprop, const char *name, float d
return (prop) ? IDP_Float(prop) : default_value;
}
+static float cycles_property_int(IDProperty *idprop, const char *name, int default_value)
+{
+ IDProperty *prop = IDP_GetPropertyTypeFromGroup(idprop, name, IDP_INT);
+ return (prop) ? IDP_Int(prop) : default_value;
+}
+
static bool cycles_property_boolean(IDProperty *idprop, const char *name, bool default_value)
{
IDProperty *prop = IDP_GetPropertyTypeFromGroup(idprop, name, IDP_INT);
return (prop) ? IDP_Int(prop) : default_value;
}
+static const char *cycles_property_string(IDProperty *idprop,
+ const char *name,
+ const char *default_value)
+{
+ IDProperty *prop = IDP_GetPropertyTypeFromGroup(idprop, name, IDP_STRING);
+ return (prop) ? IDP_String(prop) : default_value;
+}
+
static void displacement_node_insert(bNodeTree *ntree)
{
bool need_update = false;
@@ -262,6 +285,114 @@ static void ambient_occlusion_node_relink(bNodeTree *ntree)
}
}
+static void image_node_colorspace(bNode *node)
+{
+ if (node->id == NULL) {
+ return;
+ }
+
+ int color_space;
+ if (node->type == SH_NODE_TEX_IMAGE) {
+ NodeTexImage *tex = node->storage;
+ color_space = tex->color_space;
+ }
+ else if (node->type == SH_NODE_TEX_ENVIRONMENT) {
+ NodeTexEnvironment *tex = node->storage;
+ color_space = tex->color_space;
+ }
+ else {
+ return;
+ }
+
+ const int SHD_COLORSPACE_NONE = 0;
+ Image *image = (Image *)node->id;
+ if (color_space == SHD_COLORSPACE_NONE) {
+ STRNCPY(image->colorspace_settings.name,
+ IMB_colormanagement_role_colorspace_name_get(COLOR_ROLE_DATA));
+ }
+}
+
+static void light_emission_node_to_energy(Light *light, float *energy, float color[3])
+{
+ *energy = 1.0;
+ copy_v3_fl(color, 1.0f);
+
+ /* If nodetree has animation or drivers, don't try to convert. */
+ bNodeTree *ntree = light->nodetree;
+ if (ntree == NULL || ntree->adt) {
+ return;
+ }
+
+ /* Find emission node */
+ bNode *output_node = ntreeShaderOutputNode(ntree, SHD_OUTPUT_CYCLES);
+ if (output_node == NULL) {
+ return;
+ }
+
+ bNode *emission_node = NULL;
+ for (bNodeLink *link = ntree->links.first; link; link = link->next) {
+ if (link->tonode == output_node && link->fromnode->type == SH_NODE_EMISSION) {
+ emission_node = link->fromnode;
+ break;
+ }
+ }
+
+ if (emission_node == NULL) {
+ return;
+ }
+
+ /* Don't convert if anything is linked */
+ bNodeSocket *strength_socket = nodeFindSocket(emission_node, SOCK_IN, "Strength");
+ bNodeSocket *color_socket = nodeFindSocket(emission_node, SOCK_IN, "Color");
+
+ if ((strength_socket->flag & SOCK_IN_USE) || (color_socket->flag & SOCK_IN_USE)) {
+ return;
+ }
+
+ float *strength_value = cycles_node_socket_float_value(strength_socket);
+ float *color_value = cycles_node_socket_rgba_value(color_socket);
+
+ *energy = *strength_value;
+ copy_v3_v3(color, color_value);
+
+ *strength_value = 1.0f;
+ copy_v4_fl(color_value, 1.0f);
+ light->use_nodes = false;
+}
+
+static void light_emission_unify(Light *light, const char *engine)
+{
+ if (light->type != LA_SUN) {
+ light->energy *= 100.0f;
+ }
+
+ /* Attempt to extract constant energy and color from nodes. */
+ bool use_nodes = light->use_nodes;
+ float energy, color[3];
+ light_emission_node_to_energy(light, &energy, color);
+
+ if (STREQ(engine, "CYCLES")) {
+ if (use_nodes) {
+ /* Energy extracted from nodes */
+ light->energy = energy;
+ copy_v3_v3(&light->r, color);
+ }
+ else {
+ /* Default cycles multipliers if there are no nodes */
+ if (light->type == LA_SUN) {
+ light->energy = 1.0f;
+ }
+ else {
+ light->energy = 100.0f;
+ }
+ }
+ }
+ else {
+ /* Disable nodes if scene was configured for Eevee */
+ light->use_nodes = false;
+ }
+}
+
void blo_do_versions_cycles(FileData *UNUSED(fd), Library *UNUSED(lib), Main *bmain)
{
/* Particle shape shared with Eevee. */
@@ -280,11 +411,25 @@ void blo_do_versions_cycles(FileData *UNUSED(fd), Library *UNUSED(lib), Main *bm
}
}
}
+
+ if (!MAIN_VERSION_ATLEAST(bmain, 280, 68)) {
+ /* Unify Cycles and Eevee film transparency. */
+ for (Scene *scene = bmain->scenes.first; scene; scene = scene->id.next) {
+ if (STREQ(scene->r.engine, RE_engine_id_CYCLES)) {
+ IDProperty *cscene = cycles_properties_from_ID(&scene->id);
+ if (cscene) {
+ bool cycles_film_transparency = cycles_property_boolean(
+ cscene, "film_transparent", false);
+ scene->r.alphamode = cycles_film_transparency ? R_ALPHAPREMUL : R_ADDSKY;
+ }
+ }
+ }
+ }
}
void do_versions_after_linking_cycles(Main *bmain)
{
- if (!MAIN_VERSION_ATLEAST(bmain, 280, 5)) {
+ if (!MAIN_VERSION_ATLEAST(bmain, 280, 66)) {
/* Shader node tree changes. After lib linking so we have all the typeinfo
* pointers and updated sockets and we can use the high level node API to
* manipulate nodes. */
@@ -326,7 +471,64 @@ void do_versions_after_linking_cycles(Main *bmain)
if (!MAIN_VERSION_ATLEAST(bmain, 279, 5)) {
ambient_occlusion_node_relink(ntree);
}
+
+ if (!MAIN_VERSION_ATLEAST(bmain, 280, 66)) {
+ for (bNode *node = ntree->nodes.first; node; node = node->next) {
+ image_node_colorspace(node);
+ }
+ }
}
FOREACH_NODETREE_END;
}
+
+ if (!MAIN_VERSION_ATLEAST(bmain, 280, 64)) {
+ /* Unfiy Cycles and Eevee settings. */
+ Scene *scene = bmain->scenes.first;
+ const char *engine = (scene) ? scene->r.engine : "CYCLES";
+
+ for (Light *light = bmain->lights.first; light; light = light->id.next) {
+ light_emission_unify(light, engine);
+ }
+ }
+
+ if (!MAIN_VERSION_ATLEAST(bmain, 280, 69)) {
+ /* Unify Cycles and Eevee depth of field. */
+ Scene *scene = bmain->scenes.first;
+ const char *engine = (scene) ? scene->r.engine : "CYCLES";
+
+ if (STREQ(engine, RE_engine_id_CYCLES)) {
+ for (Camera *camera = bmain->cameras.first; camera; camera = camera->id.next) {
+ IDProperty *ccamera = cycles_properties_from_ID(&camera->id);
+ if (ccamera) {
+ const char *aperture_type = cycles_property_string(ccamera, "aperture_type", "RADIUS");
+
+ camera->dof.aperture_fstop = cycles_property_float(ccamera, "aperture_fstop", 5.6f);
+ camera->dof.aperture_blades = cycles_property_int(ccamera, "aperture_blades", 0);
+ camera->dof.aperture_rotation = cycles_property_float(ccamera, "aperture_rotation", 0.0);
+ camera->dof.aperture_ratio = cycles_property_float(ccamera, "aperture_ratio", 1.0f);
+ camera->dof.flag |= CAM_DOF_ENABLED;
+
+ float aperture_size = cycles_property_float(ccamera, "aperture_size", 0.0f);
+
+ if (STREQ(aperture_type, "RADIUS") && aperture_size > 0.0f) {
+ if (camera->type == CAM_ORTHO) {
+ camera->dof.aperture_fstop = 1.0f / (2.0f * aperture_size);
+ }
+ else {
+ camera->dof.aperture_fstop = (camera->lens * 1e-3f) / (2.0f * aperture_size);
+ }
+
+ continue;
+ }
+ }
+
+ /* No depth of field, set default settings. */
+ camera->dof.aperture_fstop = 2.8f;
+ camera->dof.aperture_blades = 0;
+ camera->dof.aperture_rotation = 0.0f;
+ camera->dof.aperture_ratio = 1.0f;
+ camera->dof.flag &= ~CAM_DOF_ENABLED;
+ }
+ }
+ }
}
diff --git a/source/blender/blenloader/intern/versioning_defaults.c b/source/blender/blenloader/intern/versioning_defaults.c
index 45c2a50cc3f..aafff7b1250 100644
--- a/source/blender/blenloader/intern/versioning_defaults.c
+++ b/source/blender/blenloader/intern/versioning_defaults.c
@@ -24,7 +24,9 @@
#include "BLI_listbase.h"
#include "BLI_math.h"
#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"
@@ -68,20 +70,21 @@ void BLO_update_defaults_userpref_blend(void)
U.flag &= ~USER_SCRIPT_AUTOEXEC_DISABLE;
#endif
+ /* Transform tweak with single click and drag. */
+ U.flag |= USER_RELEASECONFIRM;
+
+ U.flag &= ~(USER_DEVELOPER_UI | USER_TOOLTIPS_PYTHON);
+
/* Clear addon preferences. */
for (bAddon *addon = U.addons.first, *addon_next; addon != NULL; addon = addon_next) {
addon_next = addon->next;
if (addon->prop) {
IDP_FreeProperty(addon->prop);
- MEM_freeN(addon->prop);
addon->prop = NULL;
}
}
- /* Transform tweak with single click and drag. */
- U.flag |= USER_RELEASECONFIRM;
-
/* Ignore the theme saved in the blend file,
* instead use the theme from 'userdef_default_theme.c' */
{
@@ -92,10 +95,13 @@ 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;
- U.memcachelimit = 4096;
+ U.memcachelimit = min_ii(BLI_system_memory_max_in_megabytes_int() / 2, 4096);
/* Auto perspective. */
U.uiflag |= USER_AUTOPERSP;
@@ -153,9 +159,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 */
@@ -279,17 +292,46 @@ void BLO_update_defaults_startup_blend(Main *bmain, const char *app_template)
}
for (bScreen *screen = bmain->screens.first; screen; screen = screen->id.next) {
- /* Hide channels in timelines. */
for (ScrArea *sa = screen->areabase.first; sa; sa = sa->next) {
- SpaceAction *saction = (sa->spacetype == SPACE_ACTION) ? sa->spacedata.first : NULL;
+ if (sa->spacetype == SPACE_ACTION) {
+ /* Show marker lines, hide channels and collapse summary in timelines. */
+ SpaceAction *saction = sa->spacedata.first;
+ saction->flag |= SACTION_SHOW_MARKER_LINES;
- if (saction && saction->mode == SACTCONT_TIMELINE) {
- for (ARegion *ar = sa->regionbase.first; ar; ar = ar->next) {
- if (ar->regiontype == RGN_TYPE_CHANNELS) {
- ar->flag |= RGN_FLAG_HIDDEN;
+ if (saction->mode == SACTCONT_TIMELINE) {
+ saction->ads.flag |= ADS_FLAG_SUMMARY_COLLAPSED;
+
+ for (ARegion *ar = sa->regionbase.first; ar; ar = ar->next) {
+ if (ar->regiontype == RGN_TYPE_CHANNELS) {
+ ar->flag |= RGN_FLAG_HIDDEN;
+ }
}
}
}
+ else if (sa->spacetype == SPACE_GRAPH) {
+ SpaceGraph *sipo = sa->spacedata.first;
+ sipo->flag |= SIPO_MARKER_LINES;
+ }
+ else if (sa->spacetype == SPACE_NLA) {
+ SpaceNla *snla = sa->spacedata.first;
+ snla->flag |= SNLA_SHOW_MARKER_LINES;
+ }
+ else if (sa->spacetype == SPACE_TEXT) {
+ /* Show syntax and line numbers in Script workspace text editor. */
+ SpaceText *stext = sa->spacedata.first;
+ stext->showsyntax = true;
+ stext->showlinenrs = true;
+ }
+ else if (sa->spacetype == SPACE_VIEW3D) {
+ /* Screen space cavity by default for faster performance. */
+ View3D *v3d = sa->spacedata.first;
+ v3d->shading.cavity_type = V3D_SHADING_CAVITY_CURVATURE;
+ v3d->shading.light = V3D_LIGHTING_MATCAP;
+ }
+ else if (sa->spacetype == SPACE_CLIP) {
+ SpaceClip *sclip = sa->spacedata.first;
+ sclip->around = V3D_AROUND_CENTER_MEDIAN;
+ }
}
}
@@ -333,8 +375,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 {
@@ -368,6 +410,12 @@ 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 (bScreen *sc = bmain->screens.first; sc; sc = sc->id.next) {
diff --git a/source/blender/blenloader/intern/versioning_userdef.c b/source/blender/blenloader/intern/versioning_userdef.c
index 91611fe8c74..d1cb9d32212 100644
--- a/source/blender/blenloader/intern/versioning_userdef.c
+++ b/source/blender/blenloader/intern/versioning_userdef.c
@@ -19,7 +19,7 @@
*
* Version patch user preferences.
*/
-
+#define DNA_DEPRECATED_ALLOW
#include <string.h>
#include "BLI_math.h"
@@ -28,6 +28,7 @@
#include "DNA_userdef_types.h"
#include "DNA_curve_types.h"
#include "DNA_windowmanager_types.h"
+#include "DNA_scene_types.h"
#include "BKE_addon.h"
#include "BKE_colorband.h"
@@ -42,7 +43,7 @@
/* Disallow access to global userdef. */
#define U (_error_)
-static void do_versions_theme(UserDef *userdef, bTheme *btheme)
+static void do_versions_theme(const UserDef *userdef, bTheme *btheme)
{
#define USER_VERSION_ATLEAST(ver, subver) MAIN_VERSION_ATLEAST(userdef, ver, subver)
@@ -113,13 +114,37 @@ static void do_versions_theme(UserDef *userdef, bTheme *btheme)
FROM_DEFAULT_V4_UCHAR(space_info.info_info);
}
+ if (!USER_VERSION_ATLEAST(280, 64)) {
+ FROM_DEFAULT_V4_UCHAR(tui.icon_scene);
+
+ if (btheme->space_view3d.obcenter_dia == 0) {
+ btheme->space_view3d.obcenter_dia = U_theme_default.space_view3d.obcenter_dia;
+ }
+
+ FROM_DEFAULT_V4_UCHAR(space_graph.text);
+ FROM_DEFAULT_V4_UCHAR(space_action.text);
+ FROM_DEFAULT_V4_UCHAR(space_nla.text);
+ 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);
+ }
+
+ if (!USER_VERSION_ATLEAST(280, 67)) {
+ FROM_DEFAULT_V4_UCHAR(space_outliner.selected_object);
+ FROM_DEFAULT_V4_UCHAR(space_outliner.active_object);
+ FROM_DEFAULT_V4_UCHAR(space_outliner.edited_object);
+ FROM_DEFAULT_V4_UCHAR(space_outliner.row_alternate);
+ }
+
/**
* Include next version bump.
*/
{
- if (btheme->space_view3d.obcenter_dia == 0) {
- btheme->space_view3d.obcenter_dia = U_theme_default.space_view3d.obcenter_dia;
- }
}
#undef FROM_DEFAULT_V4_UCHAR
@@ -542,15 +567,48 @@ void BLO_version_defaults_userpref_blend(Main *bmain, UserDef *userdef)
userdef->dupflag |= USER_DUP_GPENCIL;
}
- /**
- * Include next version bump.
- */
- {
+ if (!USER_VERSION_ATLEAST(280, 60)) {
+ const float GPU_VIEWPORT_QUALITY_FXAA = 0.10f;
+ const float GPU_VIEWPORT_QUALITY_TAA8 = 0.25f;
+ const float GPU_VIEWPORT_QUALITY_TAA16 = 0.6f;
+ const float GPU_VIEWPORT_QUALITY_TAA32 = 0.8f;
+
+ if (userdef->gpu_viewport_quality <= GPU_VIEWPORT_QUALITY_FXAA) {
+ userdef->viewport_aa = SCE_DISPLAY_AA_OFF;
+ }
+ else if (userdef->gpu_viewport_quality <= GPU_VIEWPORT_QUALITY_TAA8) {
+ userdef->viewport_aa = SCE_DISPLAY_AA_FXAA;
+ }
+ else if (userdef->gpu_viewport_quality <= GPU_VIEWPORT_QUALITY_TAA16) {
+ userdef->viewport_aa = SCE_DISPLAY_AA_SAMPLES_8;
+ }
+ else if (userdef->gpu_viewport_quality <= GPU_VIEWPORT_QUALITY_TAA32) {
+ userdef->viewport_aa = SCE_DISPLAY_AA_SAMPLES_16;
+ }
+ else {
+ userdef->viewport_aa = SCE_DISPLAY_AA_SAMPLES_32;
+ }
+ }
+
+ if (!USER_VERSION_ATLEAST(280, 62)) {
/* (keep this block even if it becomes empty). */
if (userdef->vbotimeout == 0) {
userdef->vbocollectrate = 60;
userdef->vbotimeout = 120;
}
+
+ if (userdef->lookdev_sphere_size == 0) {
+ userdef->lookdev_sphere_size = 150;
+ }
+
+ userdef->pref_flag |= USER_PREF_FLAG_SAVE;
+ }
+
+ /**
+ * Include next version bump.
+ */
+ {
+ /* pass */
}
if (userdef->pixelsize == 0.0f) {
diff --git a/source/blender/blenloader/intern/writefile.c b/source/blender/blenloader/intern/writefile.c
index 9a4e2adc0e3..6305aa95e7f 100644
--- a/source/blender/blenloader/intern/writefile.c
+++ b/source/blender/blenloader/intern/writefile.c
@@ -2416,7 +2416,7 @@ static void write_paint(WriteData *wd, Paint *p)
if (p->cavity_curve) {
write_curvemapping(wd, p->cavity_curve);
}
- writedata(wd, DATA, sizeof(PaintToolSlot) * p->tool_slots_len, p->tool_slots);
+ writestruct(wd, DATA, PaintToolSlot, p->tool_slots_len, p->tool_slots);
}
static void write_layer_collections(WriteData *wd, ListBase *lb)
diff --git a/source/blender/bmesh/intern/bmesh_mesh.c b/source/blender/bmesh/intern/bmesh_mesh.c
index cb10ec9d701..a35d10db697 100644
--- a/source/blender/bmesh/intern/bmesh_mesh.c
+++ b/source/blender/bmesh/intern/bmesh_mesh.c
@@ -1440,7 +1440,6 @@ static int bm_loop_normal_mark_indiv(BMesh *bm, BLI_bitmap *loops)
* Note that this is On² piece of code,
* but it is not designed to be used with huge selection sets,
* rather with only a few items selected at most.*/
- printf("using face history selection\n");
/* Goes from last selected to the first selected element. */
for (ese = bm->selected.last; ese; ese = ese->prev) {
if (ese->htype == BM_FACE) {
@@ -1473,7 +1472,6 @@ static int bm_loop_normal_mark_indiv(BMesh *bm, BLI_bitmap *loops)
else {
if (sel_faces) {
/* Only select all loops of selected faces. */
- printf("using face selection\n");
BMLoop *l;
BMFace *f;
BMIter liter, fiter;
@@ -1487,7 +1485,6 @@ static int bm_loop_normal_mark_indiv(BMesh *bm, BLI_bitmap *loops)
}
if (sel_edges) {
/* Only select all loops of selected edges. */
- printf("using edge selection\n");
BMLoop *l;
BMEdge *e;
BMIter liter, eiter;
@@ -1510,7 +1507,6 @@ static int bm_loop_normal_mark_indiv(BMesh *bm, BLI_bitmap *loops)
}
if (sel_verts) {
/* Select all loops of selected verts. */
- printf("using vert selection\n");
BMLoop *l;
BMVert *v;
BMIter liter, viter;
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 af5ce4ed9ac..a559d13fc70 100644
--- a/source/blender/bmesh/tools/bmesh_bevel.c
+++ b/source/blender/bmesh/tools/bmesh_bevel.c
@@ -5222,7 +5222,7 @@ static BevVert *bevel_vert_construct(BMesh *bm, BevelParams *bp, BMVert *v)
BMIter iter;
EdgeHalf *e;
float weight, z;
- float vert_axis[3];
+ float vert_axis[3] = {0, 0, 0};
int i, ccw_test_sum;
int nsel = 0;
int ntot = 0;
@@ -5357,7 +5357,6 @@ static BevVert *bevel_vert_construct(BMesh *bm, BevelParams *bp, BMVert *v)
normalize_v3(edge_dir);
add_v3_v3v3(vert_axis, vert_axis, edge_dir);
}
- mul_v3_fl(vert_axis, 1 / ntot);
}
}
@@ -5430,8 +5429,7 @@ static BevVert *bevel_vert_construct(BMesh *bm, BevelParams *bp, BMVert *v)
case BEVEL_AMT_WIDTH: {
v2 = BM_edge_other_vert(e->e, bv->v);
sub_v3_v3v3(edge_dir, bv->v->co, v2->co);
- normalize_v3(edge_dir);
- z = fabsf(2.0f * sinf(angle_normalized_v3v3(vert_axis, edge_dir)));
+ z = fabsf(2.0f * sinf(angle_v3v3(vert_axis, edge_dir)));
if (z < BEVEL_EPSILON) {
e->offset_l_spec = 0.01f * bp->offset; /* undefined behavior, so tiny bevel. */
}
@@ -5443,8 +5441,7 @@ static BevVert *bevel_vert_construct(BMesh *bm, BevelParams *bp, BMVert *v)
case BEVEL_AMT_DEPTH: {
v2 = BM_edge_other_vert(e->e, bv->v);
sub_v3_v3v3(edge_dir, bv->v->co, v2->co);
- normalize_v3(edge_dir);
- z = fabsf(cosf(angle_normalized_v3v3(vert_axis, edge_dir)));
+ z = fabsf(cosf(angle_v3v3(vert_axis, edge_dir)));
if (z < BEVEL_EPSILON) {
e->offset_l_spec = 0.01f * bp->offset; /* undefined behavior, so tiny bevel. */
}
diff --git a/source/blender/collada/AnimationExporter.cpp b/source/blender/collada/AnimationExporter.cpp
index 2c9865bcd95..ba878a28e50 100644
--- a/source/blender/collada/AnimationExporter.cpp
+++ b/source/blender/collada/AnimationExporter.cpp
@@ -79,13 +79,13 @@ bool AnimationExporter::exportAnimations()
{
Scene *sce = export_settings.get_scene();
- LinkNode &export_set = *this->export_settings.get_export_set();
+ LinkNode *export_set = this->export_settings->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(export_settings, animated_subset);
diff --git a/source/blender/collada/CameraExporter.cpp b/source/blender/collada/CameraExporter.cpp
index dea0bddd941..74862c44270 100644
--- a/source/blender/collada/CameraExporter.cpp
+++ b/source/blender/collada/CameraExporter.cpp
@@ -93,6 +93,6 @@ bool CamerasExporter::exportBlenderProfile(COLLADASW::Camera &cm, Camera *cam)
{
cm.addExtraTechniqueParameter("blender", "shiftx", cam->shiftx);
cm.addExtraTechniqueParameter("blender", "shifty", cam->shifty);
- cm.addExtraTechniqueParameter("blender", "dof_distance", cam->dof_distance);
+ cm.addExtraTechniqueParameter("blender", "dof_distance", cam->dof.focus_distance);
return true;
}
diff --git a/source/blender/collada/DocumentImporter.cpp b/source/blender/collada/DocumentImporter.cpp
index 320f8379c9e..60813fb951c 100644
--- a/source/blender/collada/DocumentImporter.cpp
+++ b/source/blender/collada/DocumentImporter.cpp
@@ -859,7 +859,7 @@ bool DocumentImporter::writeCamera(const COLLADAFW::Camera *camera)
if (et && et->isProfile("blender")) {
et->setData("shiftx", &(cam->shiftx));
et->setData("shifty", &(cam->shifty));
- et->setData("dof_distance", &(cam->dof_distance));
+ et->setData("dof_distance", &(cam->dof.focus_distance));
}
cam->clip_start = camera->getNearClippingPlane().getValue();
cam->clip_end = camera->getFarClippingPlane().getValue();
diff --git a/source/blender/collada/EffectExporter.cpp b/source/blender/collada/EffectExporter.cpp
index bbd0a2e0bd3..61603226dfd 100644
--- a/source/blender/collada/EffectExporter.cpp
+++ b/source/blender/collada/EffectExporter.cpp
@@ -244,20 +244,9 @@ void EffectsExporter::operator()(Material *ma, Object *ob)
// performs the actual writing
ep.addProfileElements();
- bool twoSided = false;
- if (ob->type == OB_MESH && ob->data) {
- Mesh *me = (Mesh *)ob->data;
- if (me->flag & ME_TWOSIDED)
- twoSided = true;
- }
- if (twoSided)
- ep.addExtraTechniqueParameter("GOOGLEEARTH", "double_sided", 1);
ep.addExtraTechniques(mSW);
ep.closeProfile();
- if (twoSided)
- mSW->appendTextBlock(
- "<extra><technique profile=\"MAX3D\"><double_sided>1</double_sided></technique></extra>");
closeEffect();
}
diff --git a/source/blender/collada/GeometryExporter.cpp b/source/blender/collada/GeometryExporter.cpp
index 926d85e7fb2..c0573dcc081 100644
--- a/source/blender/collada/GeometryExporter.cpp
+++ b/source/blender/collada/GeometryExporter.cpp
@@ -127,11 +127,6 @@ void GeometryExporter::operator()(Object *ob)
closeMesh();
- if (me->flag & ME_TWOSIDED) {
- mSW->appendTextBlock(
- "<extra><technique profile=\"MAYA\"><double_sided>1</double_sided></technique></extra>");
- }
-
closeGeometry();
if (this->export_settings.get_include_shapekeys()) {
@@ -212,11 +207,6 @@ void GeometryExporter::export_key_mesh(Object *ob, Mesh *me, KeyBlock *kb)
closeMesh();
- if (me->flag & ME_TWOSIDED) {
- mSW->appendTextBlock(
- "<extra><technique profile=\"MAYA\"><double_sided>1</double_sided></technique></extra>");
- }
-
closeGeometry();
}
diff --git a/source/blender/collada/ImageExporter.cpp b/source/blender/collada/ImageExporter.cpp
index f4837d3d358..71201c8a55c 100644
--- a/source/blender/collada/ImageExporter.cpp
+++ b/source/blender/collada/ImageExporter.cpp
@@ -61,7 +61,7 @@ void ImagesExporter::export_UV_Image(Image *image, bool use_copies)
return;
}
- bool is_dirty = (imbuf->userflags & IB_BITMAPDIRTY) != 0;
+ bool is_dirty = BKE_image_is_dirty(image);
ImageFormatData imageFormat;
BKE_imbuf_to_image_format(&imageFormat, imbuf);
diff --git a/source/blender/collada/collada_utils.cpp b/source/blender/collada/collada_utils.cpp
index 4b85500008b..8b8c9854781 100644
--- a/source/blender/collada/collada_utils.cpp
+++ b/source/blender/collada/collada_utils.cpp
@@ -925,15 +925,16 @@ 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;
}
diff --git a/source/blender/collada/collada_utils.h b/source/blender/collada/collada_utils.h
index 8fe64a19401..acbf6f94add 100644
--- a/source/blender/collada/collada_utils.h
+++ b/source/blender/collada/collada_utils.h
@@ -227,7 +227,7 @@ 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);
void bc_add_global_transform(Matrix &to_mat,
diff --git a/source/blender/compositor/operations/COM_GlareFogGlowOperation.cpp b/source/blender/compositor/operations/COM_GlareFogGlowOperation.cpp
index 1f5749d782c..30a6a05ed2c 100644
--- a/source/blender/compositor/operations/COM_GlareFogGlowOperation.cpp
+++ b/source/blender/compositor/operations/COM_GlareFogGlowOperation.cpp
@@ -154,7 +154,7 @@ static void FHT2D(
for (i = 0; stm > 0; i++) {
#define PRED(k) (((k & Nym) << Mx) + (k >> My))
for (j = PRED(i); j > i; j = PRED(j)) {
- ;
+ /* pass */
}
if (j < i) {
continue;
diff --git a/source/blender/depsgraph/CMakeLists.txt b/source/blender/depsgraph/CMakeLists.txt
index aee925ad8f8..ba6b3b32d60 100644
--- a/source/blender/depsgraph/CMakeLists.txt
+++ b/source/blender/depsgraph/CMakeLists.txt
@@ -69,7 +69,6 @@ set(SRC
intern/depsgraph_eval.cc
intern/depsgraph_physics.cc
intern/depsgraph_query.cc
- intern/depsgraph_query_filter.cc
intern/depsgraph_query_foreach.cc
intern/depsgraph_query_iter.cc
intern/depsgraph_tag.cc
diff --git a/source/blender/depsgraph/DEG_depsgraph_debug.h b/source/blender/depsgraph/DEG_depsgraph_debug.h
index 9ebd5f7ffae..73e03523003 100644
--- a/source/blender/depsgraph/DEG_depsgraph_debug.h
+++ b/source/blender/depsgraph/DEG_depsgraph_debug.h
@@ -68,7 +68,7 @@ void DEG_debug_stats_gnuplot(const struct Depsgraph *graph,
/* Compare two dependency graphs. */
bool DEG_debug_compare(const struct Depsgraph *graph1, const struct Depsgraph *graph2);
-/* Check that dependnecies in the graph are really up to date. */
+/* Check that dependencies in the graph are really up to date. */
bool DEG_debug_graph_relations_validate(struct Depsgraph *graph,
struct Main *bmain,
struct Scene *scene,
diff --git a/source/blender/depsgraph/DEG_depsgraph_query.h b/source/blender/depsgraph/DEG_depsgraph_query.h
index 89e4958eddc..a7b5535d11a 100644
--- a/source/blender/depsgraph/DEG_depsgraph_query.h
+++ b/source/blender/depsgraph/DEG_depsgraph_query.h
@@ -20,7 +20,7 @@
/** \file
* \ingroup depsgraph
*
- * Public API for Querying and Filtering Depsgraph.
+ * Public API for Querying Depsgraph.
*/
#ifndef __DEG_DEPSGRAPH_QUERY_H__
@@ -72,10 +72,15 @@ void DEG_get_customdata_mask_for_object(const struct Depsgraph *graph,
struct Object *object,
struct CustomData_MeshMasks *r_mask);
-/* Get scene the despgraph is created for. */
+/* Get scene at its evaluated state.
+ *
+ * Technically, this is a copied-on-written and fully evaluated version of the input scene.
+ * This function will check that the datablock has been expanded (and copied) from the original
+ * one. Assert will happen if it's not. */
struct Scene *DEG_get_evaluated_scene(const struct Depsgraph *graph);
-/* Get scene layer the despgraph is created for. */
+/* Get view layer at its evaluated state.
+ * This is a shortcut for accessing active view layer from evaluated scene. */
struct ViewLayer *DEG_get_evaluated_view_layer(const struct Depsgraph *graph);
/* Get evaluated version of object for given original one. */
@@ -95,6 +100,19 @@ struct Object *DEG_get_original_object(struct Object *object);
/* Get original version of given evaluated ID datablock. */
struct ID *DEG_get_original_id(struct ID *id);
+/* Check whether given ID is an original,
+ *
+ * Original IDs are considered all the IDs which are not covered by copy-on-write system and are
+ * not out-of-main localized datablocks. */
+bool DEG_is_original_id(struct ID *id);
+bool DEG_is_original_object(struct Object *object);
+
+/* Opposite of the above.
+ *
+ * If the datablock is not original it must be evaluated, and vice versa. */
+bool DEG_is_evaluated_id(struct ID *id);
+bool DEG_is_evaluated_object(struct Object *object);
+
/* ************************ DEG object iterators ********************* */
enum {
@@ -205,38 +223,6 @@ void DEG_foreach_dependent_ID(const Depsgraph *depsgraph,
void DEG_foreach_ID(const Depsgraph *depsgraph, DEGForeachIDCallback callback, void *user_data);
-/* ********************* DEG graph filtering ****************** */
-
-/* ComponentKey for nodes we want to be able to evaluate in the filtered graph */
-typedef struct DEG_FilterTarget {
- struct DEG_FilterTarget *next, *prev;
-
- struct ID *id;
- /* TODO: component identifiers - Component Type, Subdata/Component Name */
-} DEG_FilterTarget;
-
-typedef enum eDEG_FilterQuery_Granularity {
- DEG_FILTER_NODES_ALL = 0,
- DEG_FILTER_NODES_NO_OPS = 1,
- DEG_FILTER_NODES_ID_ONLY = 2,
-} eDEG_FilterQuery_Granularity;
-
-typedef struct DEG_FilterQuery {
- /* List of DEG_FilterTarget's */
- struct ListBase targets;
-
- /* Level of detail in the resulting graph */
- eDEG_FilterQuery_Granularity detail_level;
-} DEG_FilterQuery;
-
-/* Obtain a new graph instance that only contains the subset of desired nodes
- * WARNING: Do NOT pass an already filtered depsgraph through this function again,
- * as we are currently unable to accurately recreate it.
- */
-Depsgraph *DEG_graph_filter(const Depsgraph *depsgraph,
- struct Main *bmain,
- DEG_FilterQuery *query);
-
#ifdef __cplusplus
} /* extern "C" */
#endif
diff --git a/source/blender/depsgraph/intern/builder/deg_builder.cc b/source/blender/depsgraph/intern/builder/deg_builder.cc
index b8e0ba51019..36c6d246097 100644
--- a/source/blender/depsgraph/intern/builder/deg_builder.cc
+++ b/source/blender/depsgraph/intern/builder/deg_builder.cc
@@ -103,7 +103,7 @@ bool DepsgraphBuilder::need_pull_base_into_graph(Base *base)
bool DepsgraphBuilder::check_pchan_has_bbone(Object *object, const bPoseChannel *pchan)
{
BLI_assert(object->type == OB_ARMATURE);
- if (pchan->bone == NULL) {
+ if (pchan == NULL || pchan->bone == NULL) {
return false;
}
/* We don't really care whether segments are higher than 1 due to static user input (as in,
@@ -114,7 +114,10 @@ bool DepsgraphBuilder::check_pchan_has_bbone(Object *object, const bPoseChannel
}
bArmature *armature = static_cast<bArmature *>(object->data);
AnimatedPropertyID property_id(&armature->id, &RNA_Bone, pchan->bone, "bbone_segments");
- return cache_->isPropertyAnimated(&armature->id, property_id);
+ /* Check both Object and Armature animation data, because drivers modifying Armature
+ * state could easily be created in the Object AnimData. */
+ return cache_->isPropertyAnimated(&object->id, property_id) ||
+ cache_->isPropertyAnimated(&armature->id, property_id);
}
bool DepsgraphBuilder::check_pchan_has_bbone_segments(Object *object, const bPoseChannel *pchan)
diff --git a/source/blender/depsgraph/intern/builder/deg_builder.h b/source/blender/depsgraph/intern/builder/deg_builder.h
index 224e3212d57..040bb6cfeea 100644
--- a/source/blender/depsgraph/intern/builder/deg_builder.h
+++ b/source/blender/depsgraph/intern/builder/deg_builder.h
@@ -23,10 +23,10 @@
#pragma once
-struct bPoseChannel;
struct Base;
struct Main;
struct Object;
+struct bPoseChannel;
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 b6822a89093..0d10bd1d3dc 100644
--- a/source/blender/depsgraph/intern/builder/deg_builder_nodes.cc
+++ b/source/blender/depsgraph/intern/builder/deg_builder_nodes.cc
@@ -58,6 +58,7 @@ extern "C" {
#include "DNA_lightprobe_types.h"
#include "DNA_rigidbody_types.h"
#include "DNA_scene_types.h"
+#include "DNA_sound_types.h"
#include "DNA_speaker_types.h"
#include "DNA_texture_types.h"
#include "DNA_world_types.h"
@@ -443,6 +444,9 @@ void DepsgraphNodeBuilder::build_id(ID *id)
case ID_SPK:
build_speaker((Speaker *)id);
break;
+ case ID_SO:
+ build_sound((bSound *)id);
+ break;
case ID_TXT:
/* Not a part of dependency graph. */
break;
@@ -459,7 +463,7 @@ void DepsgraphNodeBuilder::build_id(ID *id)
void DepsgraphNodeBuilder::build_collection(LayerCollection *from_layer_collection,
Collection *collection)
{
- const int restrict_flag = (graph_->mode == DAG_EVAL_VIEWPORT) ? COLLECTION_RESTRICT_VIEW :
+ const int restrict_flag = (graph_->mode == DAG_EVAL_VIEWPORT) ? COLLECTION_RESTRICT_VIEWPORT :
COLLECTION_RESTRICT_RENDER;
const bool is_collection_restricted = (collection->flag & restrict_flag);
const bool is_collection_visible = !is_collection_restricted && is_parent_collection_visible_;
@@ -708,7 +712,7 @@ void DepsgraphNodeBuilder::build_object_data_speaker(Object *object)
{
Speaker *speaker = (Speaker *)object->data;
build_speaker(speaker);
- add_operation_node(&object->id, NodeType::PARAMETERS, OperationCode::SPEAKER_EVAL);
+ add_operation_node(&object->id, NodeType::AUDIO, OperationCode::SPEAKER_EVAL);
}
void DepsgraphNodeBuilder::build_object_transform(Object *object)
@@ -1154,7 +1158,7 @@ void DepsgraphNodeBuilder::build_shapekeys(Key *key)
/* This is an exit operation for the entire key datablock, is what is used
* as dependency for modifiers evaluation. */
add_operation_node(&key->id, NodeType::GEOMETRY, OperationCode::GEOMETRY_SHAPEKEY);
- /* Create per-key block properties, allowing tricky inter-dependnecies for
+ /* Create per-key block properties, allowing tricky inter-dependencies for
* drivers evaluation. */
LISTBASE_FOREACH (KeyBlock *, key_block, &key->block) {
add_operation_node(
@@ -1543,9 +1547,23 @@ void DepsgraphNodeBuilder::build_speaker(Speaker *speaker)
return;
}
/* Placeholder so we can add relations and tag ID node for update. */
- add_operation_node(&speaker->id, NodeType::PARAMETERS, OperationCode::SPEAKER_EVAL);
+ add_operation_node(&speaker->id, NodeType::AUDIO, OperationCode::SPEAKER_EVAL);
build_animdata(&speaker->id);
build_parameters(&speaker->id);
+ if (speaker->sound != NULL) {
+ build_sound(speaker->sound);
+ }
+}
+
+void DepsgraphNodeBuilder::build_sound(bSound *sound)
+{
+ if (built_map_.checkIsBuiltAndTag(sound)) {
+ return;
+ }
+ /* Placeholder so we can add relations and tag ID node for update. */
+ add_operation_node(&sound->id, NodeType::AUDIO, OperationCode::SOUND_EVAL);
+ build_animdata(&sound->id);
+ build_parameters(&sound->id);
}
/* **** ID traversal callbacks functions **** */
diff --git a/source/blender/depsgraph/intern/builder/deg_builder_nodes.h b/source/blender/depsgraph/intern/builder/deg_builder_nodes.h
index cf7cf1a62d8..41314380b23 100644
--- a/source/blender/depsgraph/intern/builder/deg_builder_nodes.h
+++ b/source/blender/depsgraph/intern/builder/deg_builder_nodes.h
@@ -62,6 +62,7 @@ struct bConstraint;
struct bGPdata;
struct bNodeTree;
struct bPoseChannel;
+struct bSound;
struct PropertyRNA;
@@ -206,6 +207,7 @@ class DepsgraphNodeBuilder : public DepsgraphBuilder {
void build_movieclip(MovieClip *clip);
void build_lightprobe(LightProbe *probe);
void build_speaker(Speaker *speaker);
+ void build_sound(bSound *sound);
/* Per-ID information about what was already in the dependency graph.
* Allows to re-use certain values, to speed up following evaluation. */
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 60b711d76d3..b898b3d3519 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
@@ -60,7 +60,7 @@ namespace DEG {
void DepsgraphNodeBuilder::build_layer_collections(ListBase *lb)
{
- const int restrict_flag = (graph_->mode == DAG_EVAL_VIEWPORT) ? COLLECTION_RESTRICT_VIEW :
+ const int restrict_flag = (graph_->mode == DAG_EVAL_VIEWPORT) ? COLLECTION_RESTRICT_VIEWPORT :
COLLECTION_RESTRICT_RENDER;
for (LayerCollection *lc = (LayerCollection *)lb->first; lc; lc = lc->next) {
@@ -92,7 +92,6 @@ void DepsgraphNodeBuilder::build_view_layer(Scene *scene,
/* Get pointer to a CoW version of scene ID. */
Scene *scene_cow = get_cow_datablock(scene);
/* Scene objects. */
- int select_id = 1;
/* NOTE: Base is used for function bindings as-is, so need to pass CoW base,
* but object is expected to be an original one. Hence we go into some
* tricks here iterating over the view layer. */
@@ -108,7 +107,6 @@ void DepsgraphNodeBuilder::build_view_layer(Scene *scene,
build_object(base_index, base->object, linked_state, true);
++base_index;
}
- base->object->select_id = select_id++;
}
build_layer_collections(&view_layer->layer_collections);
if (scene->camera != NULL) {
diff --git a/source/blender/depsgraph/intern/builder/deg_builder_relations.cc b/source/blender/depsgraph/intern/builder/deg_builder_relations.cc
index d3fd16d889f..5686bcac5cb 100644
--- a/source/blender/depsgraph/intern/builder/deg_builder_relations.cc
+++ b/source/blender/depsgraph/intern/builder/deg_builder_relations.cc
@@ -58,6 +58,7 @@ extern "C" {
#include "DNA_object_types.h"
#include "DNA_rigidbody_types.h"
#include "DNA_scene_types.h"
+#include "DNA_sound_types.h"
#include "DNA_speaker_types.h"
#include "DNA_texture_types.h"
#include "DNA_world_types.h"
@@ -487,6 +488,9 @@ void DepsgraphRelationBuilder::build_id(ID *id)
case ID_SPK:
build_speaker((Speaker *)id);
break;
+ case ID_SO:
+ build_sound((bSound *)id);
+ break;
case ID_TXT:
/* Not a part of dependency graph. */
break;
@@ -766,9 +770,9 @@ void DepsgraphRelationBuilder::build_object_data_speaker(Object *object)
{
Speaker *speaker = (Speaker *)object->data;
build_speaker(speaker);
- OperationKey probe_key(&speaker->id, NodeType::PARAMETERS, OperationCode::SPEAKER_EVAL);
- OperationKey object_key(&object->id, NodeType::PARAMETERS, OperationCode::SPEAKER_EVAL);
- add_relation(probe_key, object_key, "Speaker Update");
+ ComponentKey speaker_key(&speaker->id, NodeType::AUDIO);
+ ComponentKey object_key(&object->id, NodeType::AUDIO);
+ add_relation(speaker_key, object_key, "Speaker Update");
}
void DepsgraphRelationBuilder::build_object_parent(Object *object)
@@ -1321,25 +1325,47 @@ void DepsgraphRelationBuilder::build_driver(ID *id, FCurve *fcu)
void DepsgraphRelationBuilder::build_driver_data(ID *id, FCurve *fcu)
{
- OperationKey driver_key(id,
- NodeType::PARAMETERS,
- OperationCode::DRIVER,
- fcu->rna_path ? fcu->rna_path : "",
- fcu->array_index);
- const char *rna_path = fcu->rna_path ? fcu->rna_path : "";
- if (GS(id->name) == ID_AR && STRPREFIX(rna_path, "bones[")) {
+ /* Validate the RNA path pointer just in case. */
+ const char *rna_path = fcu->rna_path;
+ if (rna_path == NULL || rna_path[0] == '\0') {
+ return;
+ }
+ /* Parse the RNA path to find the target property pointer. */
+ RNAPathKey property_entry_key(id, rna_path, RNAPointerSource::ENTRY);
+ if (RNA_pointer_is_null(&property_entry_key.ptr)) {
+ /* TODO(sergey): This would only mean that driver is broken.
+ * so we can't create relation anyway. However, we need to avoid
+ * adding drivers which are known to be buggy to a dependency
+ * graph, in order to save computational power. */
+ return;
+ }
+ OperationKey driver_key(
+ id, NodeType::PARAMETERS, OperationCode::DRIVER, rna_path, fcu->array_index);
+ /* If the target of the driver is a Bone property, find the Armature data,
+ * and then link the driver to all pose bone evaluation components that use
+ * it. This is necessary to provide more granular dependencies specifically for
+ * Bone objects, because the armature data doesn't have per-bone components,
+ * and generic add_relation can only add one link. */
+ ID *id_ptr = (ID *)property_entry_key.ptr.id.data;
+ bool is_bone = id_ptr && property_entry_key.ptr.type == &RNA_Bone;
+ /* If the Bone property is referenced via obj.pose.bones[].bone,
+ * the RNA pointer refers to the Object ID, so skip to data. */
+ if (is_bone && GS(id_ptr->name) == ID_OB) {
+ id_ptr = (ID *)((Object *)id_ptr)->data;
+ }
+ if (is_bone && GS(id_ptr->name) == ID_AR) {
/* Drivers on armature-level bone settings (i.e. bbone stuff),
* which will affect the evaluation of corresponding pose bones. */
- char *bone_name = BLI_str_quoted_substrN(rna_path, "bones[");
- if (bone_name != NULL) {
+ Bone *bone = (Bone *)property_entry_key.ptr.data;
+ if (bone != NULL) {
/* Find objects which use this, and make their eval callbacks
* depend on this. */
for (IDNode *to_node : graph_->id_nodes) {
if (GS(to_node->id_orig->name) == ID_OB) {
Object *object = (Object *)to_node->id_orig;
/* We only care about objects with pose data which use this. */
- if (object->data == id && object->pose != NULL) {
- bPoseChannel *pchan = BKE_pose_channel_find_name(object->pose, bone_name);
+ if (object->data == id_ptr && object->pose != NULL) {
+ bPoseChannel *pchan = BKE_pose_channel_find_name(object->pose, bone->name);
if (pchan != NULL) {
OperationKey bone_key(
&object->id, NodeType::BONE, pchan->name, OperationCode::BONE_LOCAL);
@@ -1348,23 +1374,18 @@ void DepsgraphRelationBuilder::build_driver_data(ID *id, FCurve *fcu)
}
}
}
- /* Free temp data. */
- MEM_freeN(bone_name);
- bone_name = NULL;
+ /* Make the driver depend on COW, similar to the generic case below. */
+ if (id_ptr != id) {
+ ComponentKey cow_key(id_ptr, NodeType::COPY_ON_WRITE);
+ add_relation(cow_key, driver_key, "Driven CoW -> Driver", RELATION_CHECK_BEFORE_ADD);
+ }
}
else {
fprintf(stderr, "Couldn't find armature bone name for driver path - '%s'\n", rna_path);
}
}
- else if (rna_path != NULL && rna_path[0] != '\0') {
- RNAPathKey property_entry_key(id, rna_path, RNAPointerSource::ENTRY);
- if (RNA_pointer_is_null(&property_entry_key.ptr)) {
- /* TODO(sergey): This would only mean that driver is broken.
- * so we can't create relation anyway. However, we need to avoid
- * adding drivers which are known to be buggy to a dependency
- * graph, in order to save computational power. */
- return;
- }
+ else {
+ /* If it's not a Bone, handle the generic single dependency case. */
add_relation(driver_key, property_entry_key, "Driver -> Driven Property");
/* Similar to the case with f-curves, driver might drive a nested
* datablock, which means driver execution should wait for that
@@ -2046,10 +2067,11 @@ void DepsgraphRelationBuilder::build_camera(Camera *camera)
if (built_map_.checkIsBuiltAndTag(camera)) {
return;
}
+ build_animdata(&camera->id);
build_parameters(&camera->id);
- if (camera->dof_ob != NULL) {
+ if (camera->dof.focus_object != NULL) {
ComponentKey camera_parameters_key(&camera->id, NodeType::PARAMETERS);
- ComponentKey dof_ob_key(&camera->dof_ob->id, NodeType::TRANSFORM);
+ ComponentKey dof_ob_key(&camera->dof.focus_object->id, NodeType::TRANSFORM);
add_relation(dof_ob_key, camera_parameters_key, "Camera DOF");
}
}
@@ -2060,6 +2082,7 @@ void DepsgraphRelationBuilder::build_light(Light *lamp)
if (built_map_.checkIsBuiltAndTag(lamp)) {
return;
}
+ build_animdata(&lamp->id);
build_parameters(&lamp->id);
/* light's nodetree */
if (lamp->nodetree != NULL) {
@@ -2246,8 +2269,8 @@ void DepsgraphRelationBuilder::build_mask(Mask *mask)
TimeSourceKey time_src_key;
add_relation(time_src_key, mask_animation_key, "TimeSrc -> Mask Animation");
/* Final mask evaluation. */
- ComponentKey parameters_key(mask_id, NodeType::PARAMETERS);
- add_relation(mask_animation_key, parameters_key, "Mask Animation -> Mask Eval");
+ OperationKey mask_eval_key(mask_id, NodeType::PARAMETERS, OperationCode::MASK_EVAL);
+ add_relation(mask_animation_key, mask_eval_key, "Mask Animation -> Mask Eval");
}
void DepsgraphRelationBuilder::build_movieclip(MovieClip *clip)
@@ -2276,6 +2299,21 @@ void DepsgraphRelationBuilder::build_speaker(Speaker *speaker)
}
build_animdata(&speaker->id);
build_parameters(&speaker->id);
+ if (speaker->sound != NULL) {
+ build_sound(speaker->sound);
+ ComponentKey speaker_key(&speaker->id, NodeType::AUDIO);
+ ComponentKey sound_key(&speaker->sound->id, NodeType::AUDIO);
+ add_relation(sound_key, speaker_key, "Sound -> Speaker");
+ }
+}
+
+void DepsgraphRelationBuilder::build_sound(bSound *sound)
+{
+ if (built_map_.checkIsBuiltAndTag(sound)) {
+ return;
+ }
+ build_animdata(&sound->id);
+ build_parameters(&sound->id);
}
void DepsgraphRelationBuilder::build_copy_on_write_relations()
diff --git a/source/blender/depsgraph/intern/builder/deg_builder_relations.h b/source/blender/depsgraph/intern/builder/deg_builder_relations.h
index 90bdb9bae65..1cf0b48128f 100644
--- a/source/blender/depsgraph/intern/builder/deg_builder_relations.h
+++ b/source/blender/depsgraph/intern/builder/deg_builder_relations.h
@@ -78,6 +78,7 @@ struct bConstraint;
struct bGPdata;
struct bNodeTree;
struct bPoseChannel;
+struct bSound;
struct PropertyRNA;
@@ -264,6 +265,7 @@ class DepsgraphRelationBuilder : public DepsgraphBuilder {
void build_movieclip(MovieClip *clip);
void build_lightprobe(LightProbe *probe);
void build_speaker(Speaker *speaker);
+ void build_sound(bSound *sound);
void build_nested_datablock(ID *owner, ID *id);
void build_nested_nodetree(ID *owner, bNodeTree *ntree);
diff --git a/source/blender/depsgraph/intern/builder/deg_builder_relations_rig.cc b/source/blender/depsgraph/intern/builder/deg_builder_relations_rig.cc
index fadce685d31..f8313dc854b 100644
--- a/source/blender/depsgraph/intern/builder/deg_builder_relations_rig.cc
+++ b/source/blender/depsgraph/intern/builder/deg_builder_relations_rig.cc
@@ -383,7 +383,13 @@ void DepsgraphRelationBuilder::build_rig(Object *object)
bPoseChannel *prev, *next;
BKE_pchan_bbone_handles_get(pchan, &prev, &next);
if (prev) {
- OperationKey prev_key(&object->id, NodeType::BONE, prev->name, OperationCode::BONE_DONE);
+ OperationCode opcode = OperationCode::BONE_DONE;
+ /* Inheriting parent roll requires access to prev handle's B-Bone properties. */
+ if ((pchan->bone->flag & BONE_ADD_PARENT_END_ROLL) != 0 &&
+ check_pchan_has_bbone_segments(object, prev)) {
+ opcode = OperationCode::BONE_SEGMENTS;
+ }
+ OperationKey prev_key(&object->id, NodeType::BONE, prev->name, opcode);
add_relation(prev_key, bone_segments_key, "Prev Handle -> B-Bone Segments");
}
if (next) {
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 a325544e046..b5a926ad597 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
@@ -61,7 +61,7 @@ namespace DEG {
void DepsgraphRelationBuilder::build_layer_collections(ListBase *lb)
{
- const int restrict_flag = (graph_->mode == DAG_EVAL_VIEWPORT) ? COLLECTION_RESTRICT_VIEW :
+ const int restrict_flag = (graph_->mode == DAG_EVAL_VIEWPORT) ? COLLECTION_RESTRICT_VIEWPORT :
COLLECTION_RESTRICT_RENDER;
for (LayerCollection *lc = (LayerCollection *)lb->first; lc; lc = lc->next) {
diff --git a/source/blender/depsgraph/intern/builder/deg_builder_rna.cc b/source/blender/depsgraph/intern/builder/deg_builder_rna.cc
index 1238cdc70c6..fa38dce1a9f 100644
--- a/source/blender/depsgraph/intern/builder/deg_builder_rna.cc
+++ b/source/blender/depsgraph/intern/builder/deg_builder_rna.cc
@@ -196,11 +196,30 @@ RNANodeIdentifier RNANodeQuery::construct_node_identifier(const PointerRNA *ptr,
/* Bone - generally, we just want the bone component. */
node_identifier.type = NodeType::BONE;
node_identifier.component_name = pchan->name;
- /* But B-Bone properties should connect to the actual operation. */
- Object *object = reinterpret_cast<Object *>(node_identifier.id);
- if (!ELEM(NULL, pchan->bone, prop) && STRPREFIX(RNA_property_identifier(prop), "bbone_") &&
- builder_->check_pchan_has_bbone_segments(object, pchan)) {
- node_identifier.operation_code = OperationCode::BONE_SEGMENTS;
+ /* However check property name for special handling. */
+ if (prop != NULL) {
+ Object *object = reinterpret_cast<Object *>(node_identifier.id);
+ const char *prop_name = RNA_property_identifier(prop);
+ /* B-Bone properties should connect to the final operation. */
+ if (STRPREFIX(prop_name, "bbone_")) {
+ if (builder_->check_pchan_has_bbone_segments(object, pchan)) {
+ node_identifier.operation_code = OperationCode::BONE_SEGMENTS;
+ }
+ else {
+ node_identifier.operation_code = OperationCode::BONE_DONE;
+ }
+ }
+ /* Final transform properties go to the Done node for the exit. */
+ else if (STREQ(prop_name, "head") || STREQ(prop_name, "tail") ||
+ STRPREFIX(prop_name, "matrix")) {
+ if (source == RNAPointerSource::EXIT) {
+ node_identifier.operation_code = OperationCode::BONE_DONE;
+ }
+ }
+ /* And other properties can always go to the entry operation. */
+ else {
+ node_identifier.operation_code = OperationCode::BONE_LOCAL;
+ }
}
}
return node_identifier;
@@ -211,6 +230,12 @@ RNANodeIdentifier RNANodeQuery::construct_node_identifier(const PointerRNA *ptr,
* bone components, instead of using this generic code. */
node_identifier.type = NodeType::PARAMETERS;
node_identifier.operation_code = OperationCode::ARMATURE_EVAL;
+ /* If trying to look up via an Object, e.g. due to lookup via
+ * obj.pose.bones[].bone in a driver attached to the Object,
+ * redirect to its data. */
+ if (GS(node_identifier.id->name) == ID_OB) {
+ node_identifier.id = (ID *)((Object *)node_identifier.id)->data;
+ }
return node_identifier;
}
else if (RNA_struct_is_a(ptr->type, &RNA_Constraint)) {
diff --git a/source/blender/depsgraph/intern/debug/deg_debug_relations_graphviz.cc b/source/blender/depsgraph/intern/debug/deg_debug_relations_graphviz.cc
index 068a04943e6..c4455a6e59f 100644
--- a/source/blender/depsgraph/intern/debug/deg_debug_relations_graphviz.cc
+++ b/source/blender/depsgraph/intern/debug/deg_debug_relations_graphviz.cc
@@ -434,6 +434,7 @@ static void deg_debug_graphviz_node(const DebugContext &ctx, const Node *node)
case NodeType::BATCH_CACHE:
case NodeType::DUPLI:
case NodeType::SYNCHRONIZATION:
+ case NodeType::AUDIO:
case NodeType::GENERIC_DATABLOCK: {
ComponentNode *comp_node = (ComponentNode *)node;
if (!comp_node->operations.empty()) {
diff --git a/source/blender/depsgraph/intern/depsgraph_query.cc b/source/blender/depsgraph/intern/depsgraph_query.cc
index a653366a588..02f2519b3fb 100644
--- a/source/blender/depsgraph/intern/depsgraph_query.cc
+++ b/source/blender/depsgraph/intern/depsgraph_query.cc
@@ -263,3 +263,43 @@ ID *DEG_get_original_id(ID *id)
BLI_assert((id->tag & LIB_TAG_COPIED_ON_WRITE) != 0);
return (ID *)id->orig_id;
}
+
+bool DEG_is_original_id(ID *id)
+{
+ /* Some explanation of the logic.
+ *
+ * What we want here is to be able to tell whether given ID is a result of dependency graph
+ * evaluation or not.
+ *
+ * All the datablocks which are created by copy-on-write mechanism will have will be tagged with
+ * LIB_TAG_COPIED_ON_WRITE tag. Those datablocks can not be original.
+ *
+ * Modifier stack evaluation might create special datablocks which have all the modifiers
+ * applied, and those will be tagged with LIB_TAG_COPIED_ON_WRITE_EVAL_RESULT. Such datablocks
+ * can not be original as well.
+ *
+ * Localization is usually happening from evaluated datablock, or will have some special pointer
+ * magic which will make them to act as evaluated.
+ *
+ * NOTE: We conder ID evaluated if ANY of those flags is set. We do NOT require ALL of them. */
+ if (id->tag &
+ (LIB_TAG_COPIED_ON_WRITE | LIB_TAG_COPIED_ON_WRITE_EVAL_RESULT | LIB_TAG_LOCALIZED)) {
+ return false;
+ }
+ return true;
+}
+
+bool DEG_is_original_object(Object *object)
+{
+ return DEG_is_original_id(&object->id);
+}
+
+bool DEG_is_evaluated_id(ID *id)
+{
+ return !DEG_is_original_id(id);
+}
+
+bool DEG_is_evaluated_object(Object *object)
+{
+ return !DEG_is_original_object(object);
+}
diff --git a/source/blender/depsgraph/intern/depsgraph_query_filter.cc b/source/blender/depsgraph/intern/depsgraph_query_filter.cc
deleted file mode 100644
index a02ced286eb..00000000000
--- a/source/blender/depsgraph/intern/depsgraph_query_filter.cc
+++ /dev/null
@@ -1,243 +0,0 @@
-/*
- * 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) 2018 Blender Foundation.
- * All rights reserved.
- */
-
-/** \file
- * \ingroup depsgraph
- *
- * Implementation of Graph Filtering API
- */
-
-#include "MEM_guardedalloc.h"
-
-extern "C" {
-#include <string.h> // XXX: memcpy
-
-#include "BLI_utildefines.h"
-#include "BKE_idcode.h"
-#include "BKE_main.h"
-#include "BLI_listbase.h"
-#include "BLI_ghash.h"
-
-#include "BKE_action.h" // XXX: BKE_pose_channel_from_name
-} /* extern "C" */
-
-#include "DNA_object_types.h"
-#include "DNA_scene_types.h"
-
-#include "RNA_access.h"
-
-#include "DEG_depsgraph.h"
-#include "DEG_depsgraph_query.h"
-#include "DEG_depsgraph_debug.h"
-
-#include "intern/eval/deg_eval_copy_on_write.h"
-
-#include "intern/depsgraph.h"
-#include "intern/depsgraph_type.h"
-
-#include "intern/node/deg_node.h"
-#include "intern/node/deg_node_component.h"
-#include "intern/node/deg_node_id.h"
-#include "intern/node/deg_node_operation.h"
-
-/* *************************************************** */
-/* Graph Filtering Internals */
-
-namespace DEG {
-
-/* UserData for deg_add_retained_id_cb */
-struct RetainedIdUserData {
- DEG_FilterQuery *query;
- GSet *set;
-};
-
-/* Helper for DEG_foreach_ancestor_id()
- * Keep track of all ID's encountered in a set
- */
-static void deg_add_retained_id_cb(ID *id, void *user_data)
-{
- RetainedIdUserData *data = (RetainedIdUserData *)user_data;
- BLI_gset_add(data->set, (void *)id);
-}
-
-/* ------------------------------------------- */
-
-/* Remove relations pointing to the given OperationNode */
-/* TODO: Make this part of OperationNode? */
-static void deg_unlink_opnode(Depsgraph *graph, OperationNode *op_node)
-{
- vector<Relation *> all_links;
-
- /* Collect all inlinks to this operation */
- for (Relation *rel : op_node->inlinks) {
- all_links.push_back(rel);
- }
- /* Collect all outlinks from this operation */
- for (Relation *rel : op_node->outlinks) {
- all_links.push_back(rel);
- }
-
- /* Delete all collected relations */
- for (Relation *rel : all_links) {
- rel->unlink();
- OBJECT_GUARDED_DELETE(rel, Relation);
- }
-
- /* Remove from entry tags */
- if (BLI_gset_haskey(graph->entry_tags, op_node)) {
- BLI_gset_remove(graph->entry_tags, op_node, NULL);
- }
-}
-
-/* Remove every ID Node (and its associated subnodes, COW data) */
-static void deg_filter_remove_unwanted_ids(Depsgraph *graph, GSet *retained_ids)
-{
- /* 1) First pass over ID nodes + their operations
- * - Identify and tag ID's (via "custom_flags = 1") to be removed
- * - Remove all links to/from operations that will be removed. */
- for (IDNode *id_node : graph->id_nodes) {
- id_node->custom_flags = !BLI_gset_haskey(retained_ids, (void *)id_node->id_orig);
- if (id_node->custom_flags) {
- GHASH_FOREACH_BEGIN (ComponentNode *, comp_node, id_node->components) {
- for (OperationNode *op_node : comp_node->operations) {
- deg_unlink_opnode(graph, op_node);
- }
- }
- GHASH_FOREACH_END();
- }
- }
-
- /* 2) Remove unwanted operations from graph->operations */
- for (Depsgraph::OperationNodes::iterator it_opnode = graph->operations.begin();
- it_opnode != graph->operations.end();) {
- OperationNode *op_node = *it_opnode;
- IDNode *id_node = op_node->owner->owner;
- if (id_node->custom_flags) {
- it_opnode = graph->operations.erase(it_opnode);
- }
- else {
- ++it_opnode;
- }
- }
-
- /* Free ID nodes that are no longer wanted
- *
- * This is loosely based on Depsgraph::clear_id_nodes().
- * However, we don't worry about the conditional freeing for physics
- * stuff, since it's rarely needed currently. */
- for (Depsgraph::IDDepsNodes::iterator it_id = graph->id_nodes.begin();
- it_id != graph->id_nodes.end();) {
- IDNode *id_node = *it_id;
- ID *id = id_node->id_orig;
-
- if (id_node->custom_flags) {
- /* Destroy node data, then remove from collections, and free */
- id_node->destroy();
-
- BLI_ghash_remove(graph->id_hash, id, NULL, NULL);
- it_id = graph->id_nodes.erase(it_id);
-
- OBJECT_GUARDED_DELETE(id_node, IDNode);
- }
- else {
- /* This node has not been marked for deletion. Increment iterator */
- ++it_id;
- }
- }
-}
-
-} // namespace DEG
-
-/* *************************************************** */
-/* Graph Filtering API */
-
-/* Obtain a new graph instance that only contains the subset of desired nodes
- * WARNING: Do NOT pass an already filtered depsgraph through this function again,
- * as we are currently unable to accurately recreate it.
- */
-Depsgraph *DEG_graph_filter(const Depsgraph *graph_src, Main *bmain, DEG_FilterQuery *query)
-{
- const DEG::Depsgraph *deg_graph_src = reinterpret_cast<const DEG::Depsgraph *>(graph_src);
- if (deg_graph_src == NULL) {
- return NULL;
- }
-
- /* Construct a full new depsgraph based on the one we got */
- /* TODO: Improve the builders to not add any ID nodes we don't need later (e.g. ProxyBuilder?) */
- Depsgraph *graph_new = DEG_graph_new(
- deg_graph_src->scene, deg_graph_src->view_layer, deg_graph_src->mode);
- DEG_graph_build_from_view_layer(
- graph_new, bmain, deg_graph_src->scene, deg_graph_src->view_layer);
-
- /* Build a set of all the id's we want to keep */
- GSet *retained_ids = BLI_gset_ptr_new(__func__);
- DEG::RetainedIdUserData retained_id_data = {query, retained_ids};
-
- LISTBASE_FOREACH (DEG_FilterTarget *, target, &query->targets) {
- /* Target Itself */
- BLI_gset_add(retained_ids, (void *)target->id);
-
- /* Target's Ancestors (i.e. things it depends on) */
- DEG_foreach_ancestor_ID(graph_new, target->id, DEG::deg_add_retained_id_cb, &retained_id_data);
- }
-
- /* Remove everything we don't want to keep around anymore */
- DEG::Depsgraph *deg_graph_new = reinterpret_cast<DEG::Depsgraph *>(graph_new);
- if (BLI_gset_len(retained_ids) > 0) {
- DEG::deg_filter_remove_unwanted_ids(deg_graph_new, retained_ids);
- }
- // TODO: query->LOD filters
-
- /* Free temp data */
- BLI_gset_free(retained_ids, NULL);
- retained_ids = NULL;
-
- /* Print Stats */
- // XXX: Hide behind debug flags
- size_t s_outer, s_operations, s_relations;
- size_t s_ids = deg_graph_src->id_nodes.size();
- unsigned int s_idh = BLI_ghash_len(deg_graph_src->id_hash);
-
- size_t n_outer, n_operations, n_relations;
- size_t n_ids = deg_graph_new->id_nodes.size();
- unsigned int n_idh = BLI_ghash_len(deg_graph_new->id_hash);
-
- DEG_stats_simple(graph_src, &s_outer, &s_operations, &s_relations);
- DEG_stats_simple(graph_new, &n_outer, &n_operations, &n_relations);
-
- printf("%s: src = (ID's: %zu (%u), Out: %zu, Op: %zu, Rel: %zu)\n",
- __func__,
- s_ids,
- s_idh,
- s_outer,
- s_operations,
- s_relations);
- printf("%s: new = (ID's: %zu (%u), Out: %zu, Op: %zu, Rel: %zu)\n",
- __func__,
- n_ids,
- n_idh,
- n_outer,
- n_operations,
- n_relations);
-
- /* Return this new graph instance */
- return graph_new;
-}
-
-/* *************************************************** */
diff --git a/source/blender/depsgraph/intern/depsgraph_query_iter.cc b/source/blender/depsgraph/intern/depsgraph_query_iter.cc
index d3bf27747c0..06632d7e510 100644
--- a/source/blender/depsgraph/intern/depsgraph_query_iter.cc
+++ b/source/blender/depsgraph/intern/depsgraph_query_iter.cc
@@ -94,7 +94,6 @@ void verify_id_properties_freed(DEGObjectIterData *data)
// Free memory which is owned by temporary storage which is about to
// get overwritten.
IDP_FreeProperty(temp_dupli_object->id.properties);
- MEM_freeN(temp_dupli_object->id.properties);
temp_dupli_object->id.properties = NULL;
}
@@ -145,7 +144,6 @@ bool deg_objects_dupli_iterator_next(BLI_Iterator *iter)
Object *dupli_parent = data->dupli_parent;
Object *temp_dupli_object = &data->temp_dupli_object;
*temp_dupli_object = *dob->ob;
- temp_dupli_object->select_id = dupli_parent->select_id;
temp_dupli_object->base_flag = dupli_parent->base_flag | BASE_FROM_DUPLI;
temp_dupli_object->base_local_view_bits = dupli_parent->base_local_view_bits;
temp_dupli_object->dt = MIN2(temp_dupli_object->dt, dupli_parent->dt);
@@ -159,7 +157,13 @@ bool deg_objects_dupli_iterator_next(BLI_Iterator *iter)
continue;
}
+ /* This could be avoided by refactoring make_dupli() in order to track all negative scaling
+ * recursively. */
+ bool is_neg_scale = is_negative_m4(dob->mat);
+ SET_FLAG_FROM_TEST(data->temp_dupli_object.transflag, is_neg_scale, OB_NEG_SCALE);
+
copy_m4_m4(data->temp_dupli_object.obmat, dob->mat);
+ invert_m4_m4(data->temp_dupli_object.imat, data->temp_dupli_object.obmat);
iter->current = &data->temp_dupli_object;
BLI_assert(DEG::deg_validate_copy_on_write_datablock(&data->temp_dupli_object.id));
return true;
diff --git a/source/blender/depsgraph/intern/depsgraph_tag.cc b/source/blender/depsgraph/intern/depsgraph_tag.cc
index f682dadee8e..7dcba8b7655 100644
--- a/source/blender/depsgraph/intern/depsgraph_tag.cc
+++ b/source/blender/depsgraph/intern/depsgraph_tag.cc
@@ -245,6 +245,13 @@ void depsgraph_update_editors_tag(Main *bmain, Depsgraph *graph, ID *id)
deg_editors_id_update(&update_ctx, id);
}
+void depsgraph_id_tag_copy_on_write(Depsgraph *graph, IDNode *id_node, eUpdateSource update_source)
+{
+ 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,
IDNode *id_node,
NodeType component_type,
@@ -252,7 +259,13 @@ void depsgraph_tag_component(Depsgraph *graph,
eUpdateSource update_source)
{
ComponentNode *component_node = id_node->find_component(component_type);
+ /* NOTE: Animation component might not be existing yet (which happens when adding new driver or
+ * adding a new keyframe), so the required copy-on-write tag needs to be taken care explicitly
+ * here. */
if (component_node == NULL) {
+ if (component_type == NodeType::ANIMATION) {
+ depsgraph_id_tag_copy_on_write(graph, id_node, update_source);
+ }
return;
}
if (operation_code == OperationCode::OPERATION) {
@@ -266,9 +279,7 @@ void depsgraph_tag_component(Depsgraph *graph,
}
/* If component depends on copy-on-write, tag it as well. */
if (component_node->need_tag_cow_before_update()) {
- 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;
+ depsgraph_id_tag_copy_on_write(graph, id_node, update_source);
}
}
@@ -462,7 +473,9 @@ void deg_graph_on_visible_update(Main *bmain, Depsgraph *graph)
* Need to solve those issues carefully, for until then we evaluate
* animation for datablocks which appears in the graph for the first
* time. */
- flag |= ID_RECALC_ANIMATION;
+ if (BKE_animdata_from_id(id_node->id_orig) != NULL) {
+ flag |= ID_RECALC_ANIMATION;
+ }
}
/* We only tag components which needs an update. Tagging everything is
* not a good idea because that might reset particles cache (or any
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 2f153e585d3..2a76d5cd362 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
@@ -1278,7 +1278,9 @@ bool deg_copy_on_write_is_expanded(const ID *id_cow)
bool deg_copy_on_write_is_needed(const ID *id_orig)
{
const ID_Type id_type = GS(id_orig->name);
- return !ELEM(id_type, ID_IM);
+ /* TODO(sergey): Make Sound copyable. It is here only because the code for dependency graph is
+ * being work in progress. */
+ return !ELEM(id_type, ID_IM, ID_SO);
}
} // namespace DEG
diff --git a/source/blender/depsgraph/intern/node/deg_node.cc b/source/blender/depsgraph/intern/node/deg_node.cc
index 5692983fbe2..7df96330ef0 100644
--- a/source/blender/depsgraph/intern/node/deg_node.cc
+++ b/source/blender/depsgraph/intern/node/deg_node.cc
@@ -101,13 +101,12 @@ const char *nodeTypeAsString(NodeType type)
return "POINT_CACHE";
case NodeType::BATCH_CACHE:
return "BATCH_CACHE";
- /* Duplication. */
case NodeType::DUPLI:
return "DUPLI";
- /* Synchronization. */
case NodeType::SYNCHRONIZATION:
return "SYNCHRONIZATION";
- /* Generic datablock. */
+ case NodeType::AUDIO:
+ return "AUDIO";
case NodeType::GENERIC_DATABLOCK:
return "GENERIC_DATABLOCK";
diff --git a/source/blender/depsgraph/intern/node/deg_node.h b/source/blender/depsgraph/intern/node/deg_node.h
index ece43657b38..e350cc9a6f4 100644
--- a/source/blender/depsgraph/intern/node/deg_node.h
+++ b/source/blender/depsgraph/intern/node/deg_node.h
@@ -92,6 +92,8 @@ enum class NodeType {
/* Used by all operations which are updating object when something is
* changed in view layer. */
OBJECT_FROM_LAYER,
+ /* Audio-related evaluation. */
+ AUDIO,
/* Un-interestying datablock, which is a part of dependency graph, but does
* not have very distinctive update procedure. */
GENERIC_DATABLOCK,
diff --git a/source/blender/depsgraph/intern/node/deg_node_component.cc b/source/blender/depsgraph/intern/node/deg_node_component.cc
index ceec62e278b..f67a81f594f 100644
--- a/source/blender/depsgraph/intern/node/deg_node_component.cc
+++ b/source/blender/depsgraph/intern/node/deg_node_component.cc
@@ -131,7 +131,6 @@ string ComponentNode::identifier() const
const string typebuf = "" + to_string(static_cast<int>(type)) + ")";
return typebuf + name + " : " + idname +
"( affects_directly_visible: " + (affects_directly_visible ? "true" : "false") + ")";
- ;
}
OperationNode *ComponentNode::find_operation(OperationIDKey key) const
@@ -365,6 +364,7 @@ DEG_COMPONENT_NODE_DEFINE(Transform, TRANSFORM, ID_RECALC_TRANSFORM);
DEG_COMPONENT_NODE_DEFINE(ObjectFromLayer, OBJECT_FROM_LAYER, 0);
DEG_COMPONENT_NODE_DEFINE(Dupli, DUPLI, 0);
DEG_COMPONENT_NODE_DEFINE(Synchronization, SYNCHRONIZATION, 0);
+DEG_COMPONENT_NODE_DEFINE(Audio, AUDIO, 0);
DEG_COMPONENT_NODE_DEFINE(GenericDatablock, GENERIC_DATABLOCK, 0);
/* Node Types Register =================================== */
@@ -391,6 +391,7 @@ void deg_register_component_depsnodes()
register_node_typeinfo(&DNTI_OBJECT_FROM_LAYER);
register_node_typeinfo(&DNTI_DUPLI);
register_node_typeinfo(&DNTI_SYNCHRONIZATION);
+ register_node_typeinfo(&DNTI_AUDIO);
register_node_typeinfo(&DNTI_GENERIC_DATABLOCK);
}
diff --git a/source/blender/depsgraph/intern/node/deg_node_component.h b/source/blender/depsgraph/intern/node/deg_node_component.h
index 038b5917a86..733d32e9c2d 100644
--- a/source/blender/depsgraph/intern/node/deg_node_component.h
+++ b/source/blender/depsgraph/intern/node/deg_node_component.h
@@ -186,6 +186,7 @@ DEG_COMPONENT_NODE_DECLARE_GENERIC(Transform);
DEG_COMPONENT_NODE_DECLARE_NO_COW_TAG_ON_UPDATE(ObjectFromLayer);
DEG_COMPONENT_NODE_DECLARE_GENERIC(Dupli);
DEG_COMPONENT_NODE_DECLARE_GENERIC(Synchronization);
+DEG_COMPONENT_NODE_DECLARE_GENERIC(Audio);
DEG_COMPONENT_NODE_DECLARE_GENERIC(GenericDatablock);
/* Bone Component */
diff --git a/source/blender/depsgraph/intern/node/deg_node_operation.cc b/source/blender/depsgraph/intern/node/deg_node_operation.cc
index 154563303ad..62a61675bcc 100644
--- a/source/blender/depsgraph/intern/node/deg_node_operation.cc
+++ b/source/blender/depsgraph/intern/node/deg_node_operation.cc
@@ -100,6 +100,8 @@ const char *operationCodeAsString(OperationCode opcode)
return "LIGHT_PROBE_EVAL";
case OperationCode::SPEAKER_EVAL:
return "SPEAKER_EVAL";
+ case OperationCode::SOUND_EVAL:
+ return "SOUND_EVAL";
case OperationCode::ARMATURE_EVAL:
return "ARMATURE_EVAL";
/* Pose. */
diff --git a/source/blender/depsgraph/intern/node/deg_node_operation.h b/source/blender/depsgraph/intern/node/deg_node_operation.h
index c959f7f34e0..ab6242a6196 100644
--- a/source/blender/depsgraph/intern/node/deg_node_operation.h
+++ b/source/blender/depsgraph/intern/node/deg_node_operation.h
@@ -106,6 +106,7 @@ enum class OperationCode {
/* Object data. --------------------------------------------------------- */
LIGHT_PROBE_EVAL,
SPEAKER_EVAL,
+ SOUND_EVAL,
ARMATURE_EVAL,
/* Pose. ---------------------------------------------------------------- */
diff --git a/source/blender/draw/CMakeLists.txt b/source/blender/draw/CMakeLists.txt
index abbf8a2b47b..b31cb7bf770 100644
--- a/source/blender/draw/CMakeLists.txt
+++ b/source/blender/draw/CMakeLists.txt
@@ -131,6 +131,7 @@ set(SRC
intern/DRW_render.h
intern/draw_cache.h
intern/draw_cache_impl.h
+ intern/draw_cache_inline.h
intern/draw_common.h
intern/draw_debug.h
intern/draw_hair_private.h
diff --git a/source/blender/draw/DRW_engine.h b/source/blender/draw/DRW_engine.h
index da1f5c7863a..5919e100ddd 100644
--- a/source/blender/draw/DRW_engine.h
+++ b/source/blender/draw/DRW_engine.h
@@ -38,6 +38,7 @@ struct IDProperty;
struct Main;
struct Material;
struct Object;
+struct RegionView3D;
struct RenderEngine;
struct RenderEngineType;
struct Scene;
@@ -135,6 +136,15 @@ void DRW_draw_depth_loop_gpencil(struct Depsgraph *depsgraph,
void DRW_draw_depth_object(struct ARegion *ar,
struct GPUViewport *viewport,
struct Object *object);
+void DRW_draw_select_id_object(struct Scene *scene,
+ struct RegionView3D *rv3d,
+ struct Object *ob,
+ short select_mode,
+ bool draw_facedot,
+ uint initial_offset,
+ uint *r_vert_offset,
+ uint *r_edge_offset,
+ uint *r_face_offset);
void DRW_framebuffer_select_id_setup(struct ARegion *ar, const bool clear);
void DRW_framebuffer_select_id_release(struct ARegion *ar);
@@ -146,7 +156,6 @@ void DRW_render_gpencil(struct RenderEngine *engine, struct Depsgraph *depsgraph
void DRW_gpencil_freecache(struct Object *ob);
/* This is here because GPUViewport needs it */
-void DRW_pass_free(struct DRWPass *pass);
struct DRWInstanceDataList *DRW_instance_data_list_create(void);
void DRW_instance_data_list_free(struct DRWInstanceDataList *idatalist);
diff --git a/source/blender/draw/engines/basic/basic_engine.c b/source/blender/draw/engines/basic/basic_engine.c
index 05ee485e053..d6902dddc61 100644
--- a/source/blender/draw/engines/basic/basic_engine.c
+++ b/source/blender/draw/engines/basic/basic_engine.c
@@ -96,18 +96,14 @@ static void basic_cache_init(void *vedata)
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 */
stl->g_data = MEM_mallocN(sizeof(*stl->g_data), __func__);
}
{
- psl->depth_pass = DRW_pass_create(
- "Depth Pass", DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_LESS_EQUAL | DRW_STATE_WIRE);
+ psl->depth_pass = DRW_pass_create("Depth Pass",
+ 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);
@@ -143,7 +139,7 @@ static void basic_cache_populate(void *vedata, Object *ob)
const int draw_as = (part->draw_as == PART_DRAW_REND) ? part->ren_as : part->draw_as;
if (draw_as == PART_DRAW_PATH) {
struct GPUBatch *hairs = DRW_cache_particles_get_hair(ob, psys, NULL);
- DRW_shgroup_call_add(stl->g_data->depth_shgrp, hairs, NULL);
+ DRW_shgroup_call(stl->g_data->depth_shgrp, hairs, NULL);
}
}
}
@@ -159,7 +155,7 @@ static void basic_cache_populate(void *vedata, Object *ob)
if (is_flat_object_viewed_from_side) {
/* Avoid losing flat objects when in ortho views (see T56549) */
struct GPUBatch *geom = DRW_cache_object_all_edges_get(ob);
- DRW_shgroup_call_object_add(stl->g_data->depth_shgrp, geom, ob);
+ DRW_shgroup_call_object(stl->g_data->depth_shgrp, geom, ob);
return;
}
}
@@ -169,7 +165,7 @@ static void basic_cache_populate(void *vedata, Object *ob)
const bool do_cull = (draw_ctx->v3d &&
(draw_ctx->v3d->shading.flag & V3D_SHADING_BACKFACE_CULLING));
/* Depth Prepass */
- DRW_shgroup_call_object_add(
+ DRW_shgroup_call_object(
(do_cull) ? stl->g_data->depth_shgrp_cull : stl->g_data->depth_shgrp, geom, ob);
}
}
diff --git a/source/blender/draw/engines/eevee/eevee_bloom.c b/source/blender/draw/engines/eevee/eevee_bloom.c
index b0013151a70..e0165ea020a 100644
--- a/source/blender/draw/engines/eevee/eevee_bloom.c
+++ b/source/blender/draw/engines/eevee/eevee_bloom.c
@@ -186,7 +186,7 @@ static DRWShadingGroup *eevee_create_bloom_pass(const char *name,
*pass = DRW_pass_create(name, DRW_STATE_WRITE_COLOR);
DRWShadingGroup *grp = DRW_shgroup_create(sh, *pass);
- DRW_shgroup_call_add(grp, quad, NULL);
+ DRW_shgroup_call(grp, quad, NULL);
DRW_shgroup_uniform_texture_ref(grp, "sourceBuffer", &effects->unf_source_buffer);
DRW_shgroup_uniform_vec2(grp, "sourceBufferTexelSize", effects->unf_source_texel_size, 1);
if (upsample) {
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 8fb73bd605f..c14f08857c3 100644
--- a/source/blender/draw/engines/eevee/eevee_depth_of_field.c
+++ b/source/blender/draw/engines/eevee/eevee_depth_of_field.c
@@ -79,7 +79,9 @@ int EEVEE_depth_of_field_init(EEVEE_ViewLayerData *UNUSED(sldata),
const DRWContextState *draw_ctx = DRW_context_state_get();
const Scene *scene_eval = DEG_get_evaluated_scene(draw_ctx->depsgraph);
- if (scene_eval->eevee.flag & SCE_EEVEE_DOF_ENABLED) {
+ Camera *cam = (camera != NULL) ? camera->data : NULL;
+
+ if (cam && (cam->dof.flag & CAM_DOF_ENABLED)) {
RegionView3D *rv3d = draw_ctx->rv3d;
const bool use_alpha = !DRW_state_draw_background();
@@ -87,94 +89,82 @@ int EEVEE_depth_of_field_init(EEVEE_ViewLayerData *UNUSED(sldata),
eevee_create_shader_depth_of_field(use_alpha);
}
- if (camera) {
- const float *viewport_size = DRW_viewport_size_get();
- Camera *cam = (Camera *)camera->data;
-
- /* Retrieve Near and Far distance */
- effects->dof_near_far[0] = -cam->clip_start;
- effects->dof_near_far[1] = -cam->clip_end;
-
- int buffer_size[2] = {(int)viewport_size[0] / 2, (int)viewport_size[1] / 2};
-
- eGPUTextureFormat down_format = DRW_state_draw_background() ? GPU_R11F_G11F_B10F :
- GPU_RGBA16F;
-
- effects->dof_down_near = DRW_texture_pool_query_2d(
- buffer_size[0], buffer_size[1], down_format, &draw_engine_eevee_type);
- effects->dof_down_far = DRW_texture_pool_query_2d(
- buffer_size[0], buffer_size[1], down_format, &draw_engine_eevee_type);
- effects->dof_coc = DRW_texture_pool_query_2d(
- buffer_size[0], buffer_size[1], GPU_RG16F, &draw_engine_eevee_type);
-
- GPU_framebuffer_ensure_config(&fbl->dof_down_fb,
- {GPU_ATTACHMENT_NONE,
- GPU_ATTACHMENT_TEXTURE(effects->dof_down_near),
- GPU_ATTACHMENT_TEXTURE(effects->dof_down_far),
- GPU_ATTACHMENT_TEXTURE(effects->dof_coc)});
-
- /* Go full 32bits for rendering and reduce the color artifacts. */
- eGPUTextureFormat fb_format = DRW_state_is_image_render() ? GPU_RGBA32F : GPU_RGBA16F;
-
- effects->dof_blur = DRW_texture_pool_query_2d(
- buffer_size[0] * 2, buffer_size[1], fb_format, &draw_engine_eevee_type);
-
- GPU_framebuffer_ensure_config(&fbl->dof_scatter_fb,
- {
- GPU_ATTACHMENT_NONE,
- GPU_ATTACHMENT_TEXTURE(effects->dof_blur),
- });
-
- if (!DRW_state_draw_background()) {
- effects->dof_blur_alpha = DRW_texture_pool_query_2d(
- buffer_size[0] * 2, buffer_size[1], GPU_R32F, &draw_engine_eevee_type);
- GPU_framebuffer_texture_attach(fbl->dof_scatter_fb, effects->dof_blur_alpha, 1, 0);
- }
-
- /* Parameters */
- /* TODO UI Options */
- float fstop = cam->gpu_dof.fstop;
- float blades = cam->gpu_dof.num_blades;
- float rotation = cam->gpu_dof.rotation;
- float ratio = 1.0f / cam->gpu_dof.ratio;
- float sensor = BKE_camera_sensor_size(cam->sensor_fit, cam->sensor_x, cam->sensor_y);
- 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;
- /* 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;
- float sensor_scaled = scale_camera * sensor;
-
- if (rv3d != NULL) {
- sensor_scaled *= rv3d->viewcamtexcofac[0];
- }
-
- effects->dof_params[1] = aperture *
- fabsf(focal_len_scaled / (focus_dist - focal_len_scaled));
- effects->dof_params[1] *= viewport_size[0] / sensor_scaled;
- effects->dof_params[0] = -focus_dist * effects->dof_params[1];
-
- effects->dof_bokeh[0] = rotation;
- effects->dof_bokeh[1] = ratio;
- effects->dof_bokeh[2] = scene_eval->eevee.bokeh_max_size;
-
- /* Precompute values to save instructions in fragment shader. */
- effects->dof_bokeh_sides[0] = blades;
- effects->dof_bokeh_sides[1] = blades > 0.0f ? 2.0f * M_PI / blades : 0.0f;
- effects->dof_bokeh_sides[2] = blades / (2.0f * M_PI);
- effects->dof_bokeh_sides[3] = blades > 0.0f ? cosf(M_PI / blades) : 0.0f;
-
- return EFFECT_DOF | EFFECT_POST_BUFFER;
+ const float *viewport_size = DRW_viewport_size_get();
+
+ /* Retrieve Near and Far distance */
+ effects->dof_near_far[0] = -cam->clip_start;
+ effects->dof_near_far[1] = -cam->clip_end;
+
+ int buffer_size[2] = {(int)viewport_size[0] / 2, (int)viewport_size[1] / 2};
+
+ eGPUTextureFormat down_format = DRW_state_draw_background() ? GPU_R11F_G11F_B10F : GPU_RGBA16F;
+
+ effects->dof_down_near = DRW_texture_pool_query_2d(
+ buffer_size[0], buffer_size[1], down_format, &draw_engine_eevee_type);
+ effects->dof_down_far = DRW_texture_pool_query_2d(
+ buffer_size[0], buffer_size[1], down_format, &draw_engine_eevee_type);
+ effects->dof_coc = DRW_texture_pool_query_2d(
+ buffer_size[0], buffer_size[1], GPU_RG16F, &draw_engine_eevee_type);
+
+ GPU_framebuffer_ensure_config(&fbl->dof_down_fb,
+ {GPU_ATTACHMENT_NONE,
+ GPU_ATTACHMENT_TEXTURE(effects->dof_down_near),
+ GPU_ATTACHMENT_TEXTURE(effects->dof_down_far),
+ GPU_ATTACHMENT_TEXTURE(effects->dof_coc)});
+
+ /* Go full 32bits for rendering and reduce the color artifacts. */
+ eGPUTextureFormat fb_format = DRW_state_is_image_render() ? GPU_RGBA32F : GPU_RGBA16F;
+
+ effects->dof_blur = DRW_texture_pool_query_2d(
+ buffer_size[0] * 2, buffer_size[1], fb_format, &draw_engine_eevee_type);
+
+ GPU_framebuffer_ensure_config(&fbl->dof_scatter_fb,
+ {
+ GPU_ATTACHMENT_NONE,
+ GPU_ATTACHMENT_TEXTURE(effects->dof_blur),
+ });
+
+ if (!DRW_state_draw_background()) {
+ effects->dof_blur_alpha = DRW_texture_pool_query_2d(
+ buffer_size[0] * 2, buffer_size[1], GPU_R32F, &draw_engine_eevee_type);
+ GPU_framebuffer_texture_attach(fbl->dof_scatter_fb, effects->dof_blur_alpha, 1, 0);
+ }
+
+ /* Parameters */
+ /* TODO UI Options */
+ float fstop = cam->dof.aperture_fstop;
+ float blades = cam->dof.aperture_blades;
+ float rotation = cam->dof.aperture_rotation;
+ float ratio = 1.0f / cam->dof.aperture_ratio;
+ float sensor = BKE_camera_sensor_size(cam->sensor_fit, cam->sensor_x, cam->sensor_y);
+ float focus_dist = BKE_camera_object_dof_distance(camera);
+ float focal_len = cam->lens;
+
+ 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;
+ float sensor_scaled = scale_camera * sensor;
+
+ if (rv3d != NULL) {
+ sensor_scaled *= rv3d->viewcamtexcofac[0];
}
+
+ effects->dof_params[1] = aperture * fabsf(focal_len_scaled / (focus_dist - focal_len_scaled));
+ effects->dof_params[1] *= viewport_size[0] / sensor_scaled;
+ effects->dof_params[0] = -focus_dist * effects->dof_params[1];
+
+ effects->dof_bokeh[0] = rotation;
+ effects->dof_bokeh[1] = ratio;
+ effects->dof_bokeh[2] = scene_eval->eevee.bokeh_max_size;
+
+ /* Precompute values to save instructions in fragment shader. */
+ effects->dof_bokeh_sides[0] = blades;
+ effects->dof_bokeh_sides[1] = blades > 0.0f ? 2.0f * M_PI / blades : 0.0f;
+ effects->dof_bokeh_sides[2] = blades / (2.0f * M_PI);
+ effects->dof_bokeh_sides[3] = blades > 0.0f ? cosf(M_PI / blades) : 0.0f;
+
+ return EFFECT_DOF | EFFECT_POST_BUFFER;
}
/* Cleanup to release memory */
@@ -205,31 +195,31 @@ void EEVEE_depth_of_field_cache_init(EEVEE_ViewLayerData *UNUSED(sldata), EEVEE_
struct GPUBatch *quad = DRW_cache_fullscreen_quad_get();
const bool use_alpha = !DRW_state_draw_background();
- psl->dof_down = DRW_pass_create("DoF Downsample", DRW_STATE_WRITE_COLOR);
+ DRW_PASS_CREATE(psl->dof_down, DRW_STATE_WRITE_COLOR);
grp = DRW_shgroup_create(e_data.dof_downsample_sh[use_alpha], psl->dof_down);
DRW_shgroup_uniform_texture_ref(grp, "colorBuffer", &effects->source_buffer);
DRW_shgroup_uniform_texture_ref(grp, "depthBuffer", &dtxl->depth);
DRW_shgroup_uniform_vec2(grp, "nearFar", effects->dof_near_far, 1);
DRW_shgroup_uniform_vec2(grp, "dofParams", effects->dof_params, 1);
- DRW_shgroup_call_add(grp, quad, NULL);
+ DRW_shgroup_call(grp, quad, NULL);
- psl->dof_scatter = DRW_pass_create("DoF Scatter",
- DRW_STATE_WRITE_COLOR | DRW_STATE_ADDITIVE_FULL);
+ DRW_PASS_CREATE(psl->dof_scatter, DRW_STATE_WRITE_COLOR | DRW_STATE_ADDITIVE_FULL);
/* This create an empty batch of N triangles to be positioned
* by the vertex shader 0.4ms against 6ms with instancing */
const float *viewport_size = DRW_viewport_size_get();
const int sprite_len = ((int)viewport_size[0] / 2) *
((int)viewport_size[1] / 2); /* brackets matters */
- grp = DRW_shgroup_empty_tri_batch_create(
- e_data.dof_scatter_sh[use_alpha], psl->dof_scatter, sprite_len);
+ grp = DRW_shgroup_create(e_data.dof_scatter_sh[use_alpha], psl->dof_scatter);
DRW_shgroup_uniform_texture_ref(grp, "nearBuffer", &effects->dof_down_near);
DRW_shgroup_uniform_texture_ref(grp, "farBuffer", &effects->dof_down_far);
DRW_shgroup_uniform_texture_ref(grp, "cocBuffer", &effects->dof_coc);
DRW_shgroup_uniform_vec4(grp, "bokehParams", effects->dof_bokeh, 2);
- psl->dof_resolve = DRW_pass_create("DoF Resolve", DRW_STATE_WRITE_COLOR);
+ DRW_shgroup_call_procedural_triangles(grp, sprite_len, NULL);
+
+ DRW_PASS_CREATE(psl->dof_resolve, DRW_STATE_WRITE_COLOR);
grp = DRW_shgroup_create(e_data.dof_resolve_sh[use_alpha], psl->dof_resolve);
DRW_shgroup_uniform_texture_ref(grp, "scatterBuffer", &effects->dof_blur);
@@ -237,7 +227,7 @@ void EEVEE_depth_of_field_cache_init(EEVEE_ViewLayerData *UNUSED(sldata), EEVEE_
DRW_shgroup_uniform_texture_ref(grp, "depthBuffer", &dtxl->depth);
DRW_shgroup_uniform_vec2(grp, "nearFar", effects->dof_near_far, 1);
DRW_shgroup_uniform_vec2(grp, "dofParams", effects->dof_params, 1);
- DRW_shgroup_call_add(grp, quad, NULL);
+ DRW_shgroup_call(grp, quad, NULL);
if (use_alpha) {
DRW_shgroup_uniform_texture_ref(grp, "scatterAlphaBuffer", &effects->dof_blur_alpha);
diff --git a/source/blender/draw/engines/eevee/eevee_effects.c b/source/blender/draw/engines/eevee/eevee_effects.c
index a8b4159e030..3562afc9134 100644
--- a/source/blender/draw/engines/eevee/eevee_effects.c
+++ b/source/blender/draw/engines/eevee/eevee_effects.c
@@ -159,9 +159,10 @@ void EEVEE_effects_init(EEVEE_ViewLayerData *sldata,
effects->enabled_effects |= EEVEE_depth_of_field_init(sldata, vedata, camera);
effects->enabled_effects |= EEVEE_temporal_sampling_init(sldata, vedata);
effects->enabled_effects |= EEVEE_occlusion_init(sldata, vedata);
- effects->enabled_effects |= EEVEE_subsurface_init(sldata, vedata);
effects->enabled_effects |= EEVEE_screen_raytrace_init(sldata, vedata);
- effects->enabled_effects |= EEVEE_volumes_init(sldata, vedata);
+
+ EEVEE_volumes_init(sldata, vedata);
+ EEVEE_subsurface_init(sldata, vedata);
/* Force normal buffer creation. */
if (DRW_state_is_image_render() && !minimal && (view_layer->passflag & SCE_PASS_NORMAL) != 0) {
@@ -262,16 +263,6 @@ void EEVEE_effects_init(EEVEE_ViewLayerData *sldata,
GPU_FRAMEBUFFER_FREE_SAFE(fbl->double_buffer_depth_fb);
}
- /**
- * Setup double buffer so we can access last frame as it was before post processes.
- */
- if ((effects->enabled_effects & EFFECT_DOUBLE_BUFFER) != 0) {
- SETUP_BUFFER(txl->color_double_buffer, fbl->double_buffer_fb, fbl->double_buffer_color_fb);
- }
- else {
- CLEANUP_BUFFER(txl->color_double_buffer, fbl->double_buffer_fb, fbl->double_buffer_color_fb);
- }
-
if ((effects->enabled_effects & (EFFECT_TAA | EFFECT_TAA_REPROJECT)) != 0) {
SETUP_BUFFER(txl->taa_history, fbl->taa_history_fb, fbl->taa_history_color_fb);
}
@@ -286,7 +277,8 @@ void EEVEE_effects_cache_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata)
EEVEE_TextureList *txl = vedata->txl;
EEVEE_StorageList *stl = vedata->stl;
EEVEE_EffectsInfo *effects = stl->effects;
- int downsample_write = DRW_STATE_WRITE_DEPTH;
+ DRWState downsample_write = DRW_STATE_WRITE_DEPTH;
+ DRWShadingGroup *grp;
/* Intel gpu seems to have problem rendering to only depth format.
* Use color texture instead. */
@@ -297,91 +289,101 @@ void EEVEE_effects_cache_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata)
struct GPUBatch *quad = DRW_cache_fullscreen_quad_get();
{
- psl->color_downsample_ps = DRW_pass_create("Downsample", DRW_STATE_WRITE_COLOR);
- DRWShadingGroup *grp = DRW_shgroup_create(e_data.downsample_sh, psl->color_downsample_ps);
+ DRW_PASS_CREATE(psl->color_downsample_ps, DRW_STATE_WRITE_COLOR);
+ grp = DRW_shgroup_create(e_data.downsample_sh, psl->color_downsample_ps);
DRW_shgroup_uniform_texture_ref(grp, "source", &e_data.color_src);
DRW_shgroup_uniform_float(grp, "fireflyFactor", &sldata->common_data.ssr_firefly_fac, 1);
- DRW_shgroup_call_add(grp, quad, NULL);
+ DRW_shgroup_call(grp, quad, NULL);
}
{
- static int zero = 0;
- static uint six = 6;
- psl->color_downsample_cube_ps = DRW_pass_create("Downsample Cube", DRW_STATE_WRITE_COLOR);
- DRWShadingGroup *grp = DRW_shgroup_create(e_data.downsample_cube_sh,
- psl->color_downsample_cube_ps);
+ DRW_PASS_CREATE(psl->color_downsample_cube_ps, DRW_STATE_WRITE_COLOR);
+ grp = DRW_shgroup_create(e_data.downsample_cube_sh, psl->color_downsample_cube_ps);
DRW_shgroup_uniform_texture_ref(grp, "source", &e_data.color_src);
DRW_shgroup_uniform_float(grp, "texelSize", &e_data.cube_texel_size, 1);
- DRW_shgroup_uniform_int(grp, "Layer", &zero, 1);
- DRW_shgroup_call_instances_add(grp, quad, NULL, &six);
+ DRW_shgroup_uniform_int_copy(grp, "Layer", 0);
+ DRW_shgroup_call_instances(grp, quad, NULL, 6);
}
{
/* Perform min/max downsample */
- DRWShadingGroup *grp;
-
- psl->maxz_downlevel_ps = DRW_pass_create("HiZ Max Down Level",
- downsample_write | DRW_STATE_DEPTH_ALWAYS);
+ DRW_PASS_CREATE(psl->maxz_downlevel_ps, downsample_write | DRW_STATE_DEPTH_ALWAYS);
grp = DRW_shgroup_create(e_data.maxz_downlevel_sh, psl->maxz_downlevel_ps);
DRW_shgroup_uniform_texture_ref(grp, "depthBuffer", &txl->maxzbuffer);
- DRW_shgroup_call_add(grp, quad, NULL);
+ DRW_shgroup_call(grp, quad, NULL);
/* Copy depth buffer to halfres top level of HiZ */
- psl->maxz_downdepth_ps = DRW_pass_create("HiZ Max Copy Depth Halfres",
- downsample_write | DRW_STATE_DEPTH_ALWAYS);
+ DRW_PASS_CREATE(psl->maxz_downdepth_ps, downsample_write | DRW_STATE_DEPTH_ALWAYS);
grp = DRW_shgroup_create(e_data.maxz_downdepth_sh, psl->maxz_downdepth_ps);
DRW_shgroup_uniform_texture_ref(grp, "depthBuffer", &e_data.depth_src);
- DRW_shgroup_call_add(grp, quad, NULL);
+ DRW_shgroup_call(grp, quad, NULL);
- psl->maxz_downdepth_layer_ps = DRW_pass_create("HiZ Max Copy DepthLayer Halfres",
- downsample_write | DRW_STATE_DEPTH_ALWAYS);
+ DRW_PASS_CREATE(psl->maxz_downdepth_layer_ps, downsample_write | DRW_STATE_DEPTH_ALWAYS);
grp = DRW_shgroup_create(e_data.maxz_downdepth_layer_sh, psl->maxz_downdepth_layer_ps);
DRW_shgroup_uniform_texture_ref(grp, "depthBuffer", &e_data.depth_src);
DRW_shgroup_uniform_int(grp, "depthLayer", &e_data.depth_src_layer, 1);
- DRW_shgroup_call_add(grp, quad, NULL);
+ DRW_shgroup_call(grp, quad, NULL);
- psl->maxz_copydepth_ps = DRW_pass_create("HiZ Max Copy Depth Fullres",
- downsample_write | DRW_STATE_DEPTH_ALWAYS);
+ DRW_PASS_CREATE(psl->maxz_copydepth_ps, downsample_write | DRW_STATE_DEPTH_ALWAYS);
grp = DRW_shgroup_create(e_data.maxz_copydepth_sh, psl->maxz_copydepth_ps);
DRW_shgroup_uniform_texture_ref(grp, "depthBuffer", &e_data.depth_src);
- DRW_shgroup_call_add(grp, quad, NULL);
+ DRW_shgroup_call(grp, quad, NULL);
- psl->maxz_copydepth_layer_ps = DRW_pass_create("HiZ Max Copy DepthLayer Halfres",
- downsample_write | DRW_STATE_DEPTH_ALWAYS);
+ DRW_PASS_CREATE(psl->maxz_copydepth_layer_ps, downsample_write | DRW_STATE_DEPTH_ALWAYS);
grp = DRW_shgroup_create(e_data.maxz_copydepth_layer_sh, psl->maxz_copydepth_layer_ps);
DRW_shgroup_uniform_texture_ref(grp, "depthBuffer", &e_data.depth_src);
DRW_shgroup_uniform_int(grp, "depthLayer", &e_data.depth_src_layer, 1);
- DRW_shgroup_call_add(grp, quad, NULL);
+ DRW_shgroup_call(grp, quad, NULL);
}
if ((effects->enabled_effects & EFFECT_VELOCITY_BUFFER) != 0) {
/* This pass compute camera motions to the non moving objects. */
- psl->velocity_resolve = DRW_pass_create("Velocity Resolve", DRW_STATE_WRITE_COLOR);
- DRWShadingGroup *grp = DRW_shgroup_create(EEVEE_shaders_velocity_resolve_sh_get(),
- psl->velocity_resolve);
+ DRW_PASS_CREATE(psl->velocity_resolve, DRW_STATE_WRITE_COLOR);
+ grp = DRW_shgroup_create(EEVEE_shaders_velocity_resolve_sh_get(), psl->velocity_resolve);
DRW_shgroup_uniform_texture_ref(grp, "depthBuffer", &e_data.depth_src);
DRW_shgroup_uniform_block(grp, "common_block", sldata->common_ubo);
DRW_shgroup_uniform_mat4(grp, "currPersinv", effects->velocity_curr_persinv);
DRW_shgroup_uniform_mat4(grp, "pastPersmat", effects->velocity_past_persmat);
- DRW_shgroup_call_add(grp, quad, NULL);
+ DRW_shgroup_call(grp, quad, NULL);
}
if ((effects->enabled_effects & EFFECT_ALPHA_CHECKER) != 0) {
- psl->alpha_checker = DRW_pass_create("Alpha Checker",
- DRW_STATE_WRITE_COLOR | DRW_STATE_BLEND_PREMUL_UNDER);
-
GPUShader *checker_sh = GPU_shader_get_builtin_shader(GPU_SHADER_2D_CHECKER);
- DRWShadingGroup *grp = DRW_shgroup_create(checker_sh, psl->alpha_checker);
-
copy_v4_fl4(effects->color_checker_dark, 0.15f, 0.15f, 0.15f, 1.0f);
copy_v4_fl4(effects->color_checker_light, 0.2f, 0.2f, 0.2f, 1.0f);
+ DRW_PASS_CREATE(psl->alpha_checker, DRW_STATE_WRITE_COLOR | DRW_STATE_BLEND_PREMUL_UNDER);
+ grp = DRW_shgroup_create(checker_sh, psl->alpha_checker);
DRW_shgroup_uniform_vec4(grp, "color1", effects->color_checker_dark, 1);
DRW_shgroup_uniform_vec4(grp, "color2", effects->color_checker_light, 1);
DRW_shgroup_uniform_int_copy(grp, "size", 8);
- DRW_shgroup_call_add(grp, quad, NULL);
+ 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);
+ }
+}
+
+void EEVEE_effects_draw_init(EEVEE_ViewLayerData *UNUSED(sldata), EEVEE_Data *vedata)
+{
+ EEVEE_FramebufferList *fbl = vedata->fbl;
+ EEVEE_TextureList *txl = vedata->txl;
+ EEVEE_EffectsInfo *effects = vedata->stl->effects;
+ DefaultTextureList *dtxl = DRW_viewport_texture_list_get();
+ /**
+ * Setup double buffer so we can access last frame as it was before post processes.
+ */
+ if ((effects->enabled_effects & EFFECT_DOUBLE_BUFFER) != 0) {
+ SETUP_BUFFER(txl->color_double_buffer, fbl->double_buffer_fb, fbl->double_buffer_color_fb);
+ }
+ else {
+ CLEANUP_BUFFER(txl->color_double_buffer, fbl->double_buffer_fb, fbl->double_buffer_color_fb);
}
}
@@ -520,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);
}
}
@@ -539,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)
@@ -572,7 +570,7 @@ void EEVEE_draw_effects(EEVEE_ViewLayerData *UNUSED(sldata), EEVEE_Data *vedata)
/* NOTE: Lookdev drawing happens before TAA but after
* motion blur and dof to avoid distortions.
* Velocity resolve use a hack to exclude lookdev
- * balls from creating shimering reprojection vectors. */
+ * spheres from creating shimering reprojection vectors. */
EEVEE_lookdev_draw(vedata);
EEVEE_velocity_resolve(vedata);
@@ -599,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 962bc8e5efb..bb37f36f935 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)
@@ -154,9 +146,13 @@ static void eevee_cache_finish(void *vedata)
{
EEVEE_ViewLayerData *sldata = EEVEE_view_layer_data_ensure();
- EEVEE_materials_cache_finish(vedata);
+ EEVEE_volumes_cache_finish(sldata, vedata);
+ EEVEE_materials_cache_finish(sldata, vedata);
EEVEE_lights_cache_finish(sldata, vedata);
EEVEE_lightprobes_cache_finish(sldata, vedata);
+
+ EEVEE_effects_draw_init(sldata, vedata);
+ EEVEE_volumes_draw_init(sldata, vedata);
}
/* As renders in an HDR offscreen buffer, we need draw everything once
@@ -180,12 +176,13 @@ static void eevee_draw_background(void *vedata)
/* Sort transparents before the loop. */
DRW_pass_sort_shgroup_z(psl->transparent_pass);
- /* Number of iteration: needed for all temporal effect (SSR, volumetrics)
- * when using opengl render. */
- int loop_len = (DRW_state_is_image_render() &&
- (stl->effects->enabled_effects & (EFFECT_VOLUMETRIC | EFFECT_SSR)) != 0) ?
- 4 :
- 1;
+ /* Number of iteration: Use viewport taa_samples when using viewport rendering */
+ int loop_len = 1;
+ if (DRW_state_is_image_render()) {
+ const DRWContextState *draw_ctx = DRW_context_state_get();
+ const Scene *scene = draw_ctx->scene;
+ loop_len = MAX2(1, scene->eevee.taa_samples);
+ }
while (loop_len--) {
float clear_col[4] = {0.0f, 0.0f, 0.0f, 0.0f};
@@ -209,30 +206,30 @@ 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);
- 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);
- }
-
/* 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);
+ 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_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` */
+ else if (((stl->effects->enabled_effects & EFFECT_TAA) != 0) &&
+ (stl->effects->taa_current_sample > 1) && DRW_state_is_image_render()) {
+ EEVEE_temporal_sampling_update_matrices(vedata);
+ }
+
/* Set ray type. */
sldata->common_data.ray_type = EEVEE_RAY_CAMERA;
sldata->common_data.ray_depth = 0.0f;
@@ -240,8 +237,8 @@ static void eevee_draw_background(void *vedata)
GPU_framebuffer_bind(fbl->main_fb);
eGPUFrameBufferBits clear_bits = GPU_DEPTH_BIT;
- clear_bits |= (DRW_state_draw_background()) ? 0 : GPU_COLOR_BIT;
- clear_bits |= ((stl->effects->enabled_effects & EFFECT_SSS) != 0) ? GPU_STENCIL_BIT : 0;
+ SET_FLAG_FROM_TEST(clear_bits, !DRW_state_draw_background(), GPU_COLOR_BIT);
+ SET_FLAG_FROM_TEST(clear_bits, (stl->effects->enabled_effects & EFFECT_SSS), GPU_STENCIL_BIT);
GPU_framebuffer_clear(fbl->main_fb, clear_bits, clear_col, clear_depth, clear_stencil);
/* Depth prepass */
@@ -296,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_state_is_image_render()) {
- DRW_viewport_matrix_override_unset_all();
- }
+ DRW_view_set_active(NULL);
}
/* Tonemapping and transfer result to default framebuffer. */
diff --git a/source/blender/draw/engines/eevee/eevee_lightcache.c b/source/blender/draw/engines/eevee/eevee_lightcache.c
index 33cb2e87dc7..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);
@@ -757,10 +762,14 @@ static void eevee_lightbake_cache_create(EEVEE_Data *vedata, EEVEE_LightBake *lb
}
DRW_render_object_iter(vedata, NULL, lbake->depsgraph, EEVEE_render_cache);
- EEVEE_materials_cache_finish(vedata);
+ EEVEE_volumes_cache_finish(sldata, vedata);
+ EEVEE_materials_cache_finish(sldata, vedata);
EEVEE_lights_cache_finish(sldata, vedata);
EEVEE_lightprobes_cache_finish(sldata, vedata);
+ EEVEE_effects_draw_init(sldata, vedata);
+ EEVEE_volumes_draw_init(sldata, vedata);
+
txl->color = NULL;
DRW_render_instance_buffer_finish();
diff --git a/source/blender/draw/engines/eevee/eevee_lightprobes.c b/source/blender/draw/engines/eevee/eevee_lightprobes.c
index a4a17de7a57..388a8b5e73d 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) &&
@@ -227,8 +232,7 @@ void EEVEE_lightbake_cache_init(EEVEE_ViewLayerData *sldata,
EEVEE_LightProbesInfo *pinfo = sldata->probes;
{
- psl->probe_glossy_compute = DRW_pass_create("LightProbe Glossy Compute",
- DRW_STATE_WRITE_COLOR);
+ DRW_PASS_CREATE(psl->probe_glossy_compute, DRW_STATE_WRITE_COLOR);
DRWShadingGroup *grp = DRW_shgroup_create(EEVEE_shaders_probe_filter_glossy_sh_get(),
psl->probe_glossy_compute);
@@ -249,13 +253,11 @@ void EEVEE_lightbake_cache_init(EEVEE_ViewLayerData *sldata,
DRW_shgroup_uniform_block(grp, "common_block", sldata->common_ubo);
struct GPUBatch *geom = DRW_cache_fullscreen_quad_get();
- DRW_shgroup_call_add(grp, geom, NULL);
+ DRW_shgroup_call(grp, geom, NULL);
}
{
- psl->probe_diffuse_compute = DRW_pass_create("LightProbe Diffuse Compute",
- DRW_STATE_WRITE_COLOR);
-
+ DRW_PASS_CREATE(psl->probe_diffuse_compute, DRW_STATE_WRITE_COLOR);
DRWShadingGroup *grp = DRW_shgroup_create(EEVEE_shaders_probe_filter_diffuse_sh_get(),
psl->probe_diffuse_compute);
#ifdef IRRADIANCE_SH_L2
@@ -272,13 +274,11 @@ void EEVEE_lightbake_cache_init(EEVEE_ViewLayerData *sldata,
DRW_shgroup_uniform_block(grp, "common_block", sldata->common_ubo);
struct GPUBatch *geom = DRW_cache_fullscreen_quad_get();
- DRW_shgroup_call_add(grp, geom, NULL);
+ DRW_shgroup_call(grp, geom, NULL);
}
{
- psl->probe_visibility_compute = DRW_pass_create("LightProbe Visibility Compute",
- DRW_STATE_WRITE_COLOR);
-
+ DRW_PASS_CREATE(psl->probe_visibility_compute, DRW_STATE_WRITE_COLOR);
DRWShadingGroup *grp = DRW_shgroup_create(EEVEE_shaders_probe_filter_visibility_sh_get(),
psl->probe_visibility_compute);
DRW_shgroup_uniform_int(grp, "outputSize", &pinfo->shres, 1);
@@ -294,11 +294,11 @@ void EEVEE_lightbake_cache_init(EEVEE_ViewLayerData *sldata,
DRW_shgroup_uniform_block(grp, "common_block", sldata->common_ubo);
struct GPUBatch *geom = DRW_cache_fullscreen_quad_get();
- DRW_shgroup_call_add(grp, geom, NULL);
+ DRW_shgroup_call(grp, geom, NULL);
}
{
- psl->probe_grid_fill = DRW_pass_create("LightProbe Grid Floodfill", DRW_STATE_WRITE_COLOR);
+ DRW_PASS_CREATE(psl->probe_grid_fill, DRW_STATE_WRITE_COLOR);
DRWShadingGroup *grp = DRW_shgroup_create(EEVEE_shaders_probe_grid_fill_sh_get(),
psl->probe_grid_fill);
@@ -306,7 +306,7 @@ void EEVEE_lightbake_cache_init(EEVEE_ViewLayerData *sldata,
DRW_shgroup_uniform_texture_ref(grp, "irradianceGrid", &light_cache->grid_tx.tex);
struct GPUBatch *geom = DRW_cache_fullscreen_quad_get();
- DRW_shgroup_call_add(grp, geom, NULL);
+ DRW_shgroup_call(grp, geom, NULL);
}
}
@@ -326,8 +326,7 @@ void EEVEE_lightprobes_cache_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedat
pinfo->do_cube_update = false;
{
- psl->probe_background = DRW_pass_create("World Probe Background Pass",
- DRW_STATE_WRITE_COLOR | DRW_STATE_DEPTH_EQUAL);
+ DRW_PASS_CREATE(psl->probe_background, DRW_STATE_WRITE_COLOR | DRW_STATE_DEPTH_EQUAL);
struct GPUBatch *geom = DRW_cache_fullscreen_quad_get();
DRWShadingGroup *grp = NULL;
@@ -360,7 +359,7 @@ void EEVEE_lightprobes_cache_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedat
DRW_shgroup_uniform_block(grp, "planar_block", sldata->planar_ubo);
DRW_shgroup_uniform_block(grp, "light_block", sldata->light_ubo);
DRW_shgroup_uniform_block(grp, "shadow_block", sldata->shadow_ubo);
- DRW_shgroup_call_add(grp, geom, NULL);
+ DRW_shgroup_call(grp, geom, NULL);
break;
default:
col = error_col;
@@ -374,20 +373,20 @@ void EEVEE_lightprobes_cache_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedat
grp = DRW_shgroup_create(EEVEE_shaders_probe_default_sh_get(), psl->probe_background);
DRW_shgroup_uniform_vec3(grp, "color", col, 1);
DRW_shgroup_uniform_float_copy(grp, "backgroundAlpha", 1.0f);
- DRW_shgroup_call_add(grp, geom, NULL);
+ DRW_shgroup_call(grp, geom, NULL);
}
}
if (DRW_state_draw_support() && !LOOK_DEV_STUDIO_LIGHT_ENABLED(draw_ctx->v3d)) {
DRWState state = DRW_STATE_WRITE_COLOR | DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_LESS_EQUAL |
DRW_STATE_CULL_BACK;
- psl->probe_display = DRW_pass_create("LightProbe Display", state);
+ DRW_PASS_CREATE(psl->probe_display, state);
/* Cube Display */
if (scene_eval->eevee.flag & SCE_EEVEE_SHOW_CUBEMAPS && lcache->cube_len > 1) {
int cube_len = lcache->cube_len - 1; /* don't count the world. */
- DRWShadingGroup *grp = DRW_shgroup_empty_tri_batch_create(
- EEVEE_shaders_probe_cube_display_sh_get(), psl->probe_display, cube_len * 2);
+ DRWShadingGroup *grp = DRW_shgroup_create(EEVEE_shaders_probe_cube_display_sh_get(),
+ psl->probe_display);
DRW_shgroup_uniform_texture_ref(grp, "probeCubes", &lcache->cube_tx.tex);
DRW_shgroup_uniform_block(grp, "probe_block", sldata->probe_ubo);
@@ -398,6 +397,8 @@ void EEVEE_lightprobes_cache_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedat
/* TODO (fclem) get rid of those UBO. */
DRW_shgroup_uniform_block(grp, "planar_block", sldata->planar_ubo);
DRW_shgroup_uniform_block(grp, "grid_block", sldata->grid_ubo);
+
+ DRW_shgroup_call_procedural_triangles(grp, cube_len * 2, NULL);
}
/* Grid Display */
@@ -423,7 +424,7 @@ void EEVEE_lightprobes_cache_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedat
DRW_shgroup_uniform_block(shgrp, "grid_block", sldata->grid_ubo);
DRW_shgroup_uniform_block(shgrp, "common_block", sldata->common_ubo);
int tri_count = egrid->resolution[0] * egrid->resolution[1] * egrid->resolution[2] * 2;
- DRW_shgroup_call_procedural_triangles_add(shgrp, tri_count, NULL);
+ DRW_shgroup_call_procedural_triangles(shgrp, tri_count, NULL);
}
}
@@ -434,29 +435,16 @@ void EEVEE_lightprobes_cache_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedat
{"probe_mat", DRW_ATTR_FLOAT, 16},
});
- DRWShadingGroup *grp = DRW_shgroup_instance_create(EEVEE_shaders_probe_planar_display_sh_get(),
- psl->probe_display,
- DRW_cache_quad_get(),
- e_data.format_probe_display_planar);
- stl->g_data->planar_display_shgrp = grp;
+ DRWShadingGroup *grp = DRW_shgroup_create(EEVEE_shaders_probe_planar_display_sh_get(),
+ psl->probe_display);
DRW_shgroup_uniform_texture_ref(grp, "probePlanars", &txl->planar_pool);
+
+ stl->g_data->planar_display_shgrp = DRW_shgroup_call_buffer_instance(
+ grp, e_data.format_probe_display_planar, DRW_cache_quad_get());
}
else {
stl->g_data->planar_display_shgrp = NULL;
}
-
- {
- psl->probe_planar_downsample_ps = DRW_pass_create("LightProbe Planar Downsample",
- DRW_STATE_WRITE_COLOR);
-
- DRWShadingGroup *grp = DRW_shgroup_create(EEVEE_shaders_probe_planar_downsample_sh_get(),
- psl->probe_planar_downsample_ps);
-
- DRW_shgroup_uniform_texture_ref(grp, "source", &txl->planar_pool);
- DRW_shgroup_uniform_float(grp, "fireflyFactor", &sldata->common_data.ssr_firefly_fac, 1);
- DRW_shgroup_call_instances_add(
- grp, DRW_cache_fullscreen_quad_get(), NULL, (uint *)&pinfo->num_planar);
- }
}
static bool eevee_lightprobes_culling_test(Object *ob)
@@ -480,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 */
@@ -504,15 +493,17 @@ 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 */
}
EEVEE_lightprobes_planar_data_from_object(
ob, &pinfo->planar_data[pinfo->num_planar], &pinfo->planar_vis_tests[pinfo->num_planar]);
/* Debug Display */
- DRWShadingGroup *grp = vedata->stl->g_data->planar_display_shgrp;
+ DRWCallBuffer *grp = vedata->stl->g_data->planar_display_shgrp;
if (grp && (probe->flag & LIGHTPROBE_FLAG_SHOW_DATA)) {
- DRW_shgroup_call_dynamic_add(grp, &pinfo->num_planar, ob->obmat);
+ DRW_buffer_add_entry(grp, &pinfo->num_planar, ob->obmat);
}
pinfo->num_planar++;
@@ -690,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)
@@ -772,6 +776,19 @@ void EEVEE_lightprobes_cache_finish(EEVEE_ViewLayerData *sldata, EEVEE_Data *ved
}
}
}
+
+ 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);
+
+ DRWShadingGroup *grp = DRW_shgroup_create(EEVEE_shaders_probe_planar_downsample_sh_get(),
+ psl->probe_planar_downsample_ps);
+
+ DRW_shgroup_uniform_texture_ref(grp, "source", &txl->planar_pool);
+ DRW_shgroup_uniform_float(grp, "fireflyFactor", &sldata->common_data.ssr_firefly_fac, 1);
+ DRW_shgroup_call_procedural_triangles(grp, pinfo->num_planar, NULL);
+ }
}
/* -------------------------------------------------------------------- */
@@ -787,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;
-
- /* Move to capture position */
- float posmat[4][4];
- unit_m4(posmat);
- negate_v3_v3(posmat[3], pos);
+ EEVEE_StorageList *stl = user_data->vedata->stl;
+ DRWView **views = do_culling ? stl->g_data->bake_views : stl->g_data->world_views;
- perspective_m4(matstate.winmat, -clipsta, clipsta, -clipsta, clipsta, clipsta, clipend);
- invert_m4_m4(matstate.wininv, matstate.winmat);
+ float winmat[4][4], viewmat[4][4];
+ perspective_m4(winmat, -near, near, -near, near, near, far);
- /* 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);
+ /* 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);
- 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);
}
}
@@ -822,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);
}
}
@@ -862,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);
@@ -901,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)
@@ -910,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),
@@ -928,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);
@@ -976,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 */
@@ -1225,7 +1241,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 */
@@ -1234,9 +1249,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 */
@@ -1265,8 +1277,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);
@@ -1284,10 +1294,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 270defb039b..e966fadbcdb 100644
--- a/source/blender/draw/engines/eevee/eevee_lights.c
+++ b/source/blender/draw/engines/eevee/eevee_lights.c
@@ -53,6 +53,8 @@ extern char datatoc_shadow_store_frag_glsl[];
extern char datatoc_shadow_copy_frag_glsl[];
extern char datatoc_concentric_samples_lib_glsl[];
+extern char datatoc_common_view_lib_glsl[];
+
/* Prototypes */
static void eevee_light_setup(Object *ob, EEVEE_Light *evli);
static float light_attenuation_radius_get(Light *la, float light_threshold);
@@ -111,8 +113,11 @@ void EEVEE_lights_init(EEVEE_ViewLayerData *sldata)
const Scene *scene_eval = DEG_get_evaluated_scene(draw_ctx->depsgraph);
if (!e_data.shadow_sh) {
- e_data.shadow_sh = DRW_shader_create(
- datatoc_shadow_vert_glsl, NULL, datatoc_shadow_frag_glsl, NULL);
+ e_data.shadow_sh = DRW_shader_create_with_lib(datatoc_shadow_vert_glsl,
+ NULL,
+ datatoc_shadow_frag_glsl,
+ datatoc_common_view_lib_glsl,
+ NULL);
}
if (!sldata->lights) {
@@ -258,7 +263,7 @@ static DRWPass *eevee_lights_cube_store_pass_get(EEVEE_PassList *psl,
DRW_shgroup_uniform_texture_ref(grp, "shadowTexture", &sldata->shadow_cube_blur);
DRW_shgroup_uniform_block(grp, "shadow_render_block", sldata->shadow_render_ubo);
DRW_shgroup_uniform_float(grp, "shadowFilterSize", &linfo->filter_size, 1);
- DRW_shgroup_call_add(grp, DRW_cache_fullscreen_quad_get(), NULL);
+ DRW_shgroup_call(grp, DRW_cache_fullscreen_quad_get(), NULL);
}
return *pass;
}
@@ -280,7 +285,7 @@ static DRWPass *eevee_lights_cascade_store_pass_get(EEVEE_PassList *psl,
DRW_shgroup_uniform_block(grp, "shadow_render_block", sldata->shadow_render_ubo);
DRW_shgroup_uniform_int(grp, "cascadeId", &linfo->current_shadow_cascade, 1);
DRW_shgroup_uniform_float(grp, "shadowFilterSize", &linfo->filter_size, 1);
- DRW_shgroup_call_add(grp, DRW_cache_fullscreen_quad_get(), NULL);
+ DRW_shgroup_call(grp, DRW_cache_fullscreen_quad_get(), NULL);
}
return *pass;
}
@@ -314,7 +319,7 @@ void EEVEE_lights_cache_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata)
psl->shadow_cascade_store_high_pass = NULL;
{
- psl->shadow_cube_copy_pass = DRW_pass_create("Shadow Copy Pass", DRW_STATE_WRITE_COLOR);
+ DRW_PASS_CREATE(psl->shadow_cube_copy_pass, DRW_STATE_WRITE_COLOR);
DRWShadingGroup *grp = DRW_shgroup_create(e_data.shadow_copy_cube_sh[linfo->shadow_method],
psl->shadow_cube_copy_pass);
@@ -322,12 +327,11 @@ void EEVEE_lights_cache_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata)
DRW_shgroup_uniform_block(grp, "shadow_render_block", sldata->shadow_render_ubo);
DRW_shgroup_uniform_float(grp, "shadowFilterSize", &linfo->filter_size, 1);
DRW_shgroup_uniform_int(grp, "faceId", &linfo->current_shadow_face, 1);
- DRW_shgroup_call_add(grp, DRW_cache_fullscreen_quad_get(), NULL);
+ DRW_shgroup_call(grp, DRW_cache_fullscreen_quad_get(), NULL);
}
{
- psl->shadow_cascade_copy_pass = DRW_pass_create("Shadow Cascade Copy Pass",
- DRW_STATE_WRITE_COLOR);
+ DRW_PASS_CREATE(psl->shadow_cascade_copy_pass, DRW_STATE_WRITE_COLOR);
DRWShadingGroup *grp = DRW_shgroup_create(e_data.shadow_copy_cascade_sh[linfo->shadow_method],
psl->shadow_cascade_copy_pass);
@@ -335,12 +339,12 @@ void EEVEE_lights_cache_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata)
DRW_shgroup_uniform_block(grp, "shadow_render_block", sldata->shadow_render_ubo);
DRW_shgroup_uniform_float(grp, "shadowFilterSize", &linfo->filter_size, 1);
DRW_shgroup_uniform_int(grp, "cascadeId", &linfo->current_shadow_cascade, 1);
- DRW_shgroup_call_add(grp, DRW_cache_fullscreen_quad_get(), NULL);
+ DRW_shgroup_call(grp, DRW_cache_fullscreen_quad_get(), NULL);
}
{
DRWState state = DRW_STATE_WRITE_COLOR | DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_LESS_EQUAL;
- psl->shadow_pass = DRW_pass_create("Shadow Pass", state);
+ DRW_PASS_CREATE(psl->shadow_pass, state);
stl->g_data->shadow_shgrp = DRW_shgroup_create(e_data.shadow_sh, psl->shadow_pass);
}
@@ -449,7 +453,7 @@ void EEVEE_lights_cache_shcaster_add(EEVEE_ViewLayerData *UNUSED(sldata),
struct GPUBatch *geom,
Object *ob)
{
- DRW_shgroup_call_object_add(stl->g_data->shadow_shgrp, geom, ob);
+ DRW_shgroup_call_object(stl->g_data->shadow_shgrp, geom, ob);
}
void EEVEE_lights_cache_shcaster_material_add(EEVEE_ViewLayerData *sldata,
@@ -479,7 +483,7 @@ void EEVEE_lights_cache_shcaster_material_add(EEVEE_ViewLayerData *sldata,
DRW_shgroup_uniform_float(grp, "alphaThreshold", alpha_threshold, 1);
}
- DRW_shgroup_call_object_add(grp, geom, ob);
+ DRW_shgroup_call_object(grp, geom, ob);
}
/* Make that object update shadow casting lights inside its influence bounding box. */
@@ -640,7 +644,7 @@ float light_attenuation_radius_get(Light *la, float light_threshold)
/* Compute max light power. */
float power = max_fff(la->r, la->g, la->b);
- power *= fabsf(la->energy);
+ power *= fabsf(la->energy / 100.0f);
power *= max_ff(1.0f, la->spec_fac);
/* Compute the distance (using the inverse square law)
* at which the light power reaches the light_threshold. */
@@ -667,6 +671,9 @@ static void light_shape_parameters_set(EEVEE_Light *evli, const Light *la, float
evli->sizey = max_ff(0.003f, la->area_size * scale[1] * 0.5f);
}
}
+ else if (la->type == LA_SUN) {
+ evli->radius = max_ff(0.001f, tanf(la->sun_angle / 2.0f));
+ }
else {
evli->radius = max_ff(0.001f, la->area_size);
}
@@ -678,7 +685,7 @@ static float light_shape_power_get(const Light *la, const EEVEE_Light *evli)
/* Make illumination power constant */
if (la->type == LA_AREA) {
power = 1.0f / (evli->sizex * evli->sizey * 4.0f * M_PI) * /* 1/(w*h*Pi) */
- 80.0f; /* XXX : Empirical, Fit cycles power */
+ 0.8f; /* XXX : Empirical, Fit cycles power */
if (ELEM(la->area_shape, LA_AREA_DISK, LA_AREA_ELLIPSE)) {
/* Scale power to account for the lower area of the ellipse compared to the surrounding
* rectangle. */
@@ -686,8 +693,7 @@ static float light_shape_power_get(const Light *la, const EEVEE_Light *evli)
}
}
else if (la->type == LA_SPOT || la->type == LA_LOCAL) {
- power = 1.0f / (4.0f * evli->radius * evli->radius * M_PI * M_PI) * /* 1/(4*r²*Pi²) */
- M_PI * M_PI * 10.0; /* XXX : Empirical, Fit cycles power */
+ power = 1.0f / (4.0f * evli->radius * evli->radius * M_PI * M_PI); /* 1/(4*r²*Pi²) */
/* for point lights (a.k.a radius == 0.0) */
// power = M_PI * M_PI * 0.78; /* XXX : Empirical, Fit cycles power */
@@ -964,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)
@@ -972,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;
@@ -1280,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. */
@@ -1307,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);
@@ -1319,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 */
@@ -1336,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;
@@ -1351,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);
@@ -1442,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");
@@ -1459,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);
@@ -1548,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 4be87bf1a5e..a998bd3a71b 100644
--- a/source/blender/draw/engines/eevee/eevee_lookdev.c
+++ b/source/blender/draw/engines/eevee/eevee_lookdev.c
@@ -72,17 +72,21 @@ void EEVEE_lookdev_cache_init(EEVEE_Data *vedata,
Scene *scene = draw_ctx->scene;
if (LOOK_DEV_OVERLAY_ENABLED(v3d)) {
- /* Viewport / Ball size. */
+ /* Viewport / Spheres size. */
rcti rect;
ED_region_visible_rect(draw_ctx->ar, &rect);
- const int ball_size = max_ii(BLI_rcti_size_x(&rect) * 0.1f, 100.0f) * U.dpi_fac;
+ /* Make the viewport width scale the lookdev spheres a bit.
+ * Scale between 1000px and 2000px. */
+ const float viewport_scale = clamp_f(
+ BLI_rcti_size_x(&rect) / (2000.0f * U.dpi_fac), 0.5f, 1.0f);
+ const int sphere_size = U.lookdev_sphere_size * U.dpi_fac * viewport_scale;
- if (ball_size != effects->ball_size || rect.xmax != effects->anchor[0] ||
+ if (sphere_size != effects->sphere_size || rect.xmax != effects->anchor[0] ||
rect.ymin != effects->anchor[1]) {
- /* If ball size or anchor point moves, reset TAA to avoid ghosting issue.
+ /* If sphere size or anchor point moves, reset TAA to avoid ghosting issue.
* This needs to happen early because we are changing taa_current_sample. */
- effects->ball_size = ball_size;
+ effects->sphere_size = sphere_size;
effects->anchor[0] = rect.xmax;
effects->anchor[1] = rect.ymin;
EEVEE_temporal_sampling_reset(vedata);
@@ -147,7 +151,7 @@ void EEVEE_lookdev_cache_init(EEVEE_Data *vedata,
DRW_shgroup_uniform_mat3(*grp, "StudioLightMatrix", stl->g_data->studiolight_matrix);
DRW_shgroup_uniform_float_copy(*grp, "backgroundAlpha", background_alpha);
DRW_shgroup_uniform_vec3(*grp, "color", background_color, 1);
- DRW_shgroup_call_add(*grp, geom, NULL);
+ DRW_shgroup_call(*grp, geom, NULL);
if (!pinfo) {
/* Do not fadeout when doing probe rendering, only when drawing the background */
DRW_shgroup_uniform_float(
@@ -180,7 +184,7 @@ void EEVEE_lookdev_cache_init(EEVEE_Data *vedata,
}
static void eevee_lookdev_apply_taa(const EEVEE_EffectsInfo *effects,
- int ball_size,
+ int sphere_size,
float winmat[4][4])
{
if (DRW_state_is_image_render() || ((effects->enabled_effects & EFFECT_TAA) != 0)) {
@@ -191,8 +195,8 @@ static void eevee_lookdev_apply_taa(const EEVEE_EffectsInfo *effects,
BLI_halton_2d(ht_primes, ht_offset, effects->taa_current_sample, ht_point);
EEVEE_temporal_sampling_offset_calc(ht_point, 1.5f, ofs);
- winmat[3][0] += ofs[0] / ball_size;
- winmat[3][1] += ofs[1] / ball_size;
+ winmat[3][0] += ofs[0] / sphere_size;
+ winmat[3][1] += ofs[1] / sphere_size;
}
}
@@ -219,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->ball_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 :
@@ -242,30 +254,30 @@ void EEVEE_lookdev_draw(EEVEE_Data *vedata)
GPU_framebuffer_bind(fb);
- const int ball_margin = effects->ball_size / 6.0f;
- float offset[2] = {0.0f, ball_margin};
+ const int sphere_margin = effects->sphere_size / 6.0f;
+ float offset[2] = {0.0f, sphere_margin};
- offset[0] = effects->ball_size + ball_margin;
+ offset[0] = effects->sphere_size + sphere_margin;
GPU_framebuffer_viewport_set(fb,
effects->anchor[0] - offset[0],
effects->anchor[1] + offset[1],
- effects->ball_size,
- effects->ball_size);
+ effects->sphere_size,
+ effects->sphere_size);
DRW_draw_pass(psl->lookdev_diffuse_pass);
- offset[0] = (effects->ball_size + ball_margin) +
- (ball_margin + effects->ball_size + ball_margin);
+ offset[0] = (effects->sphere_size + sphere_margin) +
+ (sphere_margin + effects->sphere_size + sphere_margin);
GPU_framebuffer_viewport_set(fb,
effects->anchor[0] - offset[0],
effects->anchor[1] + offset[1],
- effects->ball_size,
- effects->ball_size);
+ effects->sphere_size,
+ effects->sphere_size);
DRW_draw_pass(psl->lookdev_glossy_pass);
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 456f4bdb5f1..456f312f1df 100644
--- a/source/blender/draw/engines/eevee/eevee_materials.c
+++ b/source/blender/draw/engines/eevee/eevee_materials.c
@@ -48,6 +48,7 @@
static struct {
char *frag_shader_lib;
char *vert_shader_str;
+ char *vert_shadow_shader_str;
char *volume_shader_lib;
struct GPUShader *default_prepass_sh;
@@ -133,7 +134,7 @@ static struct GPUTexture *create_ggx_lut_texture(int UNUSED(w), int UNUSED(h))
DRW_shgroup_uniform_texture(grp, "texJitter", e_data.jitter);
struct GPUBatch *geom = DRW_cache_fullscreen_quad_get();
- DRW_shgroup_call_add(grp, geom, NULL);
+ DRW_shgroup_call(grp, geom, NULL);
float *texels = MEM_mallocN(sizeof(float[2]) * w * h, "lut");
@@ -196,7 +197,7 @@ static struct GPUTexture *create_ggx_refraction_lut_texture(int w, int h)
DRW_shgroup_uniform_texture(grp, "utilTex", e_data.util_tex);
struct GPUBatch *geom = DRW_cache_fullscreen_quad_get();
- DRW_shgroup_call_add(grp, geom, NULL);
+ DRW_shgroup_call(grp, geom, NULL);
float *texels = MEM_mallocN(sizeof(float[2]) * w * h, "lut");
@@ -296,9 +297,6 @@ static char *eevee_get_defines(int options)
if ((options & VAR_MAT_PROBE) != 0) {
BLI_dynstr_append(ds, "#define PROBE_CAPTURE\n");
}
- if ((options & VAR_MAT_FLAT) != 0) {
- BLI_dynstr_append(ds, "#define USE_FLAT_NORMAL\n");
- }
if ((options & VAR_MAT_CLIP) != 0) {
BLI_dynstr_append(ds, "#define USE_ALPHA_CLIP\n");
}
@@ -317,9 +315,6 @@ static char *eevee_get_defines(int options)
if ((options & VAR_MAT_REFRACT) != 0) {
BLI_dynstr_append(ds, "#define USE_REFRACTION\n");
}
- if ((options & VAR_MAT_SSS) != 0) {
- BLI_dynstr_append(ds, "#define USE_SSS\n");
- }
if ((options & VAR_MAT_SSSALBED) != 0) {
BLI_dynstr_append(ds, "#define USE_SSS_ALBEDO\n");
}
@@ -332,9 +327,6 @@ static char *eevee_get_defines(int options)
if ((options & VAR_MAT_ESM) != 0) {
BLI_dynstr_append(ds, "#define SHADOW_ESM\n");
}
- if (((options & VAR_MAT_VOLUME) != 0) && ((options & VAR_MAT_BLEND) != 0)) {
- BLI_dynstr_append(ds, "#define USE_ALPHA_BLEND_VOLUMETRICS\n");
- }
if ((options & VAR_MAT_LOOKDEV) != 0) {
/* Auto config shadow method. Avoid more permutation. */
BLI_assert((options & (VAR_MAT_VSM | VAR_MAT_ESM)) == 0);
@@ -381,6 +373,7 @@ static void add_standard_uniforms(DRWShadingGroup *shgrp,
bool use_alpha_blend)
{
LightCache *lcache = vedata->stl->g_data->light_cache;
+ EEVEE_EffectsInfo *effects = vedata->stl->effects;
if (ssr_id == NULL) {
static int no_ssr = -1.0f;
@@ -393,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);
@@ -402,14 +394,7 @@ static void add_standard_uniforms(DRWShadingGroup *shgrp,
DRW_shgroup_uniform_texture_ref(shgrp, "maxzBuffer", &vedata->txl->maxzbuffer);
}
if ((use_diffuse || use_glossy) && !use_ssrefraction) {
- if ((vedata->stl->effects->enabled_effects & EFFECT_GTAO) != 0) {
- DRW_shgroup_uniform_texture_ref(
- shgrp, "horizonBuffer", &vedata->stl->effects->gtao_horizons);
- }
- else {
- /* Use maxzbuffer as fallback to avoid sampling problem on certain platform, see: T52593 */
- DRW_shgroup_uniform_texture_ref(shgrp, "horizonBuffer", &vedata->txl->maxzbuffer);
- }
+ DRW_shgroup_uniform_texture_ref(shgrp, "horizonBuffer", &effects->gtao_horizons);
}
if (use_diffuse) {
DRW_shgroup_uniform_texture_ref(shgrp, "irradianceGrid", &lcache->grid_tx.tex);
@@ -428,11 +413,9 @@ static void add_standard_uniforms(DRWShadingGroup *shgrp,
DRW_shgroup_uniform_texture_ref(shgrp, "colorBuffer", &vedata->txl->refract_color);
}
}
-
- if ((vedata->stl->effects->enabled_effects & EFFECT_VOLUMETRIC) != 0 && use_alpha_blend) {
- /* Do not use history buffers as they already have been swapped */
- DRW_shgroup_uniform_texture_ref(shgrp, "inScattering", &vedata->txl->volume_scatter);
- DRW_shgroup_uniform_texture_ref(shgrp, "inTransmittance", &vedata->txl->volume_transmittance);
+ if (use_alpha_blend) {
+ DRW_shgroup_uniform_texture_ref(shgrp, "inScattering", &effects->volume_scatter);
+ DRW_shgroup_uniform_texture_ref(shgrp, "inTransmittance", &effects->volume_transmit);
}
}
@@ -612,18 +595,23 @@ void EEVEE_materials_init(EEVEE_ViewLayerData *sldata,
e_data.vert_shader_str = BLI_string_joinN(
datatoc_common_view_lib_glsl, datatoc_common_hair_lib_glsl, datatoc_lit_surface_vert_glsl);
- e_data.default_background = DRW_shader_create(
- datatoc_background_vert_glsl, NULL, datatoc_default_world_frag_glsl, NULL);
+ 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_prepass_sh = DRW_shader_create(
- datatoc_prepass_vert_glsl, NULL, datatoc_prepass_frag_glsl, NULL);
-
- e_data.default_prepass_clip_sh = DRW_shader_create(
- datatoc_prepass_vert_glsl, NULL, datatoc_prepass_frag_glsl, "#define CLIP_PLANES\n");
+ e_data.default_background = DRW_shader_create_with_lib(datatoc_background_vert_glsl,
+ NULL,
+ datatoc_default_world_frag_glsl,
+ datatoc_common_view_lib_glsl,
+ NULL);
char *vert_str = BLI_string_joinN(
datatoc_common_view_lib_glsl, datatoc_common_hair_lib_glsl, datatoc_prepass_vert_glsl);
+ e_data.default_prepass_sh = DRW_shader_create(vert_str, NULL, datatoc_prepass_frag_glsl, NULL);
+
+ e_data.default_prepass_clip_sh = DRW_shader_create(
+ vert_str, NULL, datatoc_prepass_frag_glsl, "#define CLIP_PLANES\n");
+
e_data.default_hair_prepass_sh = DRW_shader_create(
vert_str, NULL, datatoc_prepass_frag_glsl, "#define HAIR_SHADER\n");
@@ -656,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);
}
@@ -743,7 +731,6 @@ struct GPUMaterial *EEVEE_material_mesh_get(struct Scene *scene,
bool use_blend,
bool use_multiply,
bool use_refract,
- bool use_sss,
bool use_translucency,
int shadow_method)
{
@@ -751,27 +738,11 @@ struct GPUMaterial *EEVEE_material_mesh_get(struct Scene *scene,
const void *engine = &DRW_engine_viewport_eevee_type;
int options = VAR_MAT_MESH;
- if (use_blend) {
- options |= VAR_MAT_BLEND;
- }
- if (use_multiply) {
- options |= VAR_MAT_MULT;
- }
- if (use_refract) {
- options |= VAR_MAT_REFRACT;
- }
- if (use_sss) {
- options |= VAR_MAT_SSS;
- }
- if (use_sss && effects->sss_separate_albedo) {
- options |= VAR_MAT_SSSALBED;
- }
- if (use_translucency) {
- options |= VAR_MAT_TRANSLUC;
- }
- if (((effects->enabled_effects & EFFECT_VOLUMETRIC) != 0) && use_blend) {
- options |= VAR_MAT_VOLUME;
- }
+ SET_FLAG_FROM_TEST(options, use_blend, VAR_MAT_BLEND);
+ SET_FLAG_FROM_TEST(options, use_multiply, VAR_MAT_MULT);
+ SET_FLAG_FROM_TEST(options, use_refract, VAR_MAT_REFRACT);
+ SET_FLAG_FROM_TEST(options, effects->sss_separate_albedo, VAR_MAT_SSSALBED);
+ SET_FLAG_FROM_TEST(options, use_translucency, VAR_MAT_TRANSLUC);
options |= eevee_material_shadow_option(shadow_method);
@@ -832,16 +803,9 @@ struct GPUMaterial *EEVEE_material_mesh_depth_get(struct Scene *scene,
const void *engine = &DRW_engine_viewport_eevee_type;
int options = VAR_MAT_MESH;
- if (use_hashed_alpha) {
- options |= VAR_MAT_HASH;
- }
- else {
- options |= VAR_MAT_CLIP;
- }
-
- if (is_shadow) {
- options |= VAR_MAT_SHADOW;
- }
+ SET_FLAG_FROM_TEST(options, use_hashed_alpha, VAR_MAT_HASH);
+ SET_FLAG_FROM_TEST(options, !use_hashed_alpha, VAR_MAT_CLIP);
+ SET_FLAG_FROM_TEST(options, is_shadow, VAR_MAT_SHADOW);
GPUMaterial *mat = DRW_shader_find_from_material(ma, engine, options, true);
if (mat) {
@@ -856,7 +820,7 @@ struct GPUMaterial *EEVEE_material_mesh_depth_get(struct Scene *scene,
ma,
engine,
options,
- (is_shadow) ? datatoc_shadow_vert_glsl :
+ (is_shadow) ? e_data.vert_shadow_shader_str :
e_data.vert_shader_str,
NULL,
frag_str,
@@ -905,28 +869,16 @@ static struct DRWShadingGroup *EEVEE_default_shading_group_create(EEVEE_ViewLaye
EEVEE_Data *vedata,
DRWPass *pass,
bool is_hair,
- bool is_flat_normal,
bool use_blend,
bool use_ssr,
int shadow_method)
{
- EEVEE_EffectsInfo *effects = vedata->stl->effects;
static int ssr_id;
ssr_id = (use_ssr) ? 1 : -1;
int options = VAR_MAT_MESH;
- if (is_hair) {
- options |= VAR_MAT_HAIR;
- }
- if (is_flat_normal) {
- options |= VAR_MAT_FLAT;
- }
- if (use_blend) {
- options |= VAR_MAT_BLEND;
- }
- if (((effects->enabled_effects & EFFECT_VOLUMETRIC) != 0) && use_blend) {
- options |= VAR_MAT_VOLUME;
- }
+ SET_FLAG_FROM_TEST(options, is_hair, VAR_MAT_HAIR);
+ SET_FLAG_FROM_TEST(options, use_blend, VAR_MAT_BLEND);
options |= eevee_material_shadow_option(shadow_method);
@@ -949,7 +901,6 @@ static struct DRWShadingGroup *EEVEE_default_shading_group_get(EEVEE_ViewLayerDa
ParticleSystem *psys,
ModifierData *md,
bool is_hair,
- bool is_flat_normal,
bool use_ssr,
int shadow_method)
{
@@ -957,14 +908,11 @@ static struct DRWShadingGroup *EEVEE_default_shading_group_get(EEVEE_ViewLayerDa
ssr_id = (use_ssr) ? 1 : -1;
int options = VAR_MAT_MESH;
+ EEVEE_PassList *psl = vedata->psl;
+
BLI_assert(!is_hair || (ob && psys && md));
- if (is_hair) {
- options |= VAR_MAT_HAIR;
- }
- if (is_flat_normal) {
- options |= VAR_MAT_FLAT;
- }
+ SET_FLAG_FROM_TEST(options, is_hair, VAR_MAT_HAIR);
options |= eevee_material_shadow_option(shadow_method);
@@ -972,17 +920,16 @@ static struct DRWShadingGroup *EEVEE_default_shading_group_get(EEVEE_ViewLayerDa
create_default_shader(options);
}
- if (vedata->psl->default_pass[options] == NULL) {
- DRWState state = DRW_STATE_WRITE_COLOR | DRW_STATE_DEPTH_EQUAL | DRW_STATE_CLIP_PLANES |
- DRW_STATE_WIRE;
- vedata->psl->default_pass[options] = DRW_pass_create("Default Lit Pass", state);
+ if (psl->default_pass[options] == NULL) {
+ DRWState state = DRW_STATE_WRITE_COLOR | DRW_STATE_DEPTH_EQUAL | DRW_STATE_CLIP_PLANES;
+ DRW_PASS_CREATE(psl->default_pass[options], state);
/* XXX / WATCH: This creates non persistent binds for the ubos and textures.
* But it's currently OK because the following shgroups does not add any bind.
* EDIT: THIS IS NOT THE CASE FOR HAIRS !!! DUMMY!!! */
if (!is_hair) {
DRWShadingGroup *shgrp = DRW_shgroup_create(e_data.default_lit[options],
- vedata->psl->default_pass[options]);
+ psl->default_pass[options]);
add_standard_uniforms(shgrp, sldata, vedata, &ssr_id, NULL, true, true, false, false, false);
}
}
@@ -1010,8 +957,7 @@ void EEVEE_materials_cache_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata)
}
{
- psl->background_pass = DRW_pass_create("Background Pass",
- DRW_STATE_WRITE_COLOR | DRW_STATE_DEPTH_EQUAL);
+ DRW_PASS_CREATE(psl->background_pass, DRW_STATE_WRITE_COLOR | DRW_STATE_DEPTH_EQUAL);
struct GPUBatch *geom = DRW_cache_fullscreen_quad_get();
DRWShadingGroup *grp = NULL;
@@ -1043,7 +989,7 @@ void EEVEE_materials_cache_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata)
DRW_shgroup_uniform_block(grp, "planar_block", sldata->planar_ubo);
DRW_shgroup_uniform_block(grp, "light_block", sldata->light_ubo);
DRW_shgroup_uniform_block(grp, "shadow_block", sldata->shadow_ubo);
- DRW_shgroup_call_add(grp, geom, NULL);
+ DRW_shgroup_call(grp, geom, NULL);
break;
case GPU_MAT_QUEUED:
/* TODO Bypass probe compilation. */
@@ -1062,96 +1008,85 @@ void EEVEE_materials_cache_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata)
grp = DRW_shgroup_create(e_data.default_background, psl->background_pass);
DRW_shgroup_uniform_vec3(grp, "color", col, 1);
DRW_shgroup_uniform_float(grp, "backgroundAlpha", &stl->g_data->background_alpha, 1);
- DRW_shgroup_call_add(grp, geom, NULL);
+ DRW_shgroup_call(grp, geom, NULL);
}
}
{
- DRWState state = DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_LESS_EQUAL | DRW_STATE_WIRE;
- psl->depth_pass = DRW_pass_create("Depth Pass", state);
+ DRWState state = DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_LESS_EQUAL;
+ DRW_PASS_CREATE(psl->depth_pass, state);
stl->g_data->depth_shgrp = DRW_shgroup_create(e_data.default_prepass_sh, psl->depth_pass);
state = DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_LESS_EQUAL | DRW_STATE_CULL_BACK;
- psl->depth_pass_cull = DRW_pass_create("Depth Pass Cull", state);
+ DRW_PASS_CREATE(psl->depth_pass_cull, state);
stl->g_data->depth_shgrp_cull = DRW_shgroup_create(e_data.default_prepass_sh,
psl->depth_pass_cull);
- state = DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_LESS_EQUAL | DRW_STATE_CLIP_PLANES |
- DRW_STATE_WIRE;
- psl->depth_pass_clip = DRW_pass_create("Depth Pass Clip", state);
+ state = DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_LESS_EQUAL | DRW_STATE_CLIP_PLANES;
+ DRW_PASS_CREATE(psl->depth_pass_clip, state);
stl->g_data->depth_shgrp_clip = DRW_shgroup_create(e_data.default_prepass_clip_sh,
psl->depth_pass_clip);
- 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;
- psl->depth_pass_clip_cull = DRW_pass_create("Depth Pass Cull Clip", state);
+ 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);
}
{
- DRWState state = DRW_STATE_WRITE_COLOR | DRW_STATE_DEPTH_EQUAL | DRW_STATE_CLIP_PLANES |
- DRW_STATE_WIRE;
- psl->material_pass = DRW_pass_create("Material Pass", state);
- psl->material_pass_cull = DRW_pass_create("Material Pass Cull", state | DRW_STATE_CULL_BACK);
+ DRWState state = DRW_STATE_WRITE_COLOR | DRW_STATE_DEPTH_EQUAL | DRW_STATE_CLIP_PLANES;
+ DRW_PASS_CREATE(psl->material_pass, state);
+ DRW_PASS_CREATE(psl->material_pass_cull, state | DRW_STATE_CULL_BACK);
}
{
- DRWState state = DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_LESS_EQUAL | DRW_STATE_WIRE;
- psl->refract_depth_pass = DRW_pass_create("Refract Depth Pass", state);
+ DRWState state = DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_LESS_EQUAL;
+ DRW_PASS_CREATE(psl->refract_depth_pass, state);
stl->g_data->refract_depth_shgrp = DRW_shgroup_create(e_data.default_prepass_sh,
psl->refract_depth_pass);
state = DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_LESS_EQUAL | DRW_STATE_CULL_BACK;
- psl->refract_depth_pass_cull = DRW_pass_create("Refract Depth Pass Cull", state);
+ DRW_PASS_CREATE(psl->refract_depth_pass_cull, state);
stl->g_data->refract_depth_shgrp_cull = DRW_shgroup_create(e_data.default_prepass_sh,
psl->refract_depth_pass_cull);
- state = DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_LESS_EQUAL | DRW_STATE_CLIP_PLANES |
- DRW_STATE_WIRE;
- psl->refract_depth_pass_clip = DRW_pass_create("Refract Depth Pass Clip", state);
+ state = DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_LESS_EQUAL | DRW_STATE_CLIP_PLANES;
+ DRW_PASS_CREATE(psl->refract_depth_pass_clip, state);
stl->g_data->refract_depth_shgrp_clip = DRW_shgroup_create(e_data.default_prepass_clip_sh,
psl->refract_depth_pass_clip);
- 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;
- psl->refract_depth_pass_clip_cull = DRW_pass_create("Refract Depth Pass Cull Clip", state);
+ 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);
}
{
- DRWState state = (DRW_STATE_WRITE_COLOR | DRW_STATE_DEPTH_EQUAL | DRW_STATE_CLIP_PLANES |
- DRW_STATE_WIRE);
- psl->refract_pass = DRW_pass_create("Opaque Refraction Pass", state);
+ DRWState state = (DRW_STATE_WRITE_COLOR | DRW_STATE_DEPTH_EQUAL | DRW_STATE_CLIP_PLANES);
+ DRW_PASS_CREATE(psl->refract_pass, state);
}
{
DRWState state = (DRW_STATE_WRITE_COLOR | DRW_STATE_DEPTH_EQUAL | DRW_STATE_CLIP_PLANES |
- DRW_STATE_WIRE | DRW_STATE_WRITE_STENCIL);
- psl->sss_pass = DRW_pass_create("Subsurface Pass", state);
- psl->sss_pass_cull = DRW_pass_create("Subsurface Pass Cull", state | DRW_STATE_CULL_BACK);
+ DRW_STATE_WRITE_STENCIL);
+ DRW_PASS_CREATE(psl->sss_pass, state);
+ DRW_PASS_CREATE(psl->sss_pass_cull, state | DRW_STATE_CULL_BACK);
e_data.sss_count = 0;
}
{
- DRWState state = DRW_STATE_WRITE_COLOR | DRW_STATE_DEPTH_LESS_EQUAL | DRW_STATE_CLIP_PLANES |
- DRW_STATE_WIRE;
- psl->transparent_pass = DRW_pass_create("Material Transparent Pass", state);
+ DRWState state = DRW_STATE_WRITE_COLOR | DRW_STATE_DEPTH_LESS_EQUAL | DRW_STATE_CLIP_PLANES;
+ DRW_PASS_CREATE(psl->transparent_pass, state);
}
{
- psl->update_noise_pass = DRW_pass_create("Update Noise Pass", DRW_STATE_WRITE_COLOR);
+ DRW_PASS_CREATE(psl->update_noise_pass, DRW_STATE_WRITE_COLOR);
DRWShadingGroup *grp = DRW_shgroup_create(e_data.update_noise_sh, psl->update_noise_pass);
DRW_shgroup_uniform_texture(grp, "blueNoise", e_data.noise_tex);
DRW_shgroup_uniform_vec3(grp, "offsets", e_data.noise_offsets, 1);
- DRW_shgroup_call_add(grp, DRW_cache_fullscreen_quad_get(), NULL);
+ DRW_shgroup_call(grp, DRW_cache_fullscreen_quad_get(), NULL);
}
if (LOOK_DEV_OVERLAY_ENABLED(draw_ctx->v3d)) {
@@ -1169,45 +1104,39 @@ void EEVEE_materials_cache_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata)
DRWState state = DRW_STATE_WRITE_COLOR | DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_ALWAYS |
DRW_STATE_CULL_BACK;
- psl->lookdev_diffuse_pass = DRW_pass_create("LookDev Diffuse Pass", state);
+ DRW_PASS_CREATE(psl->lookdev_diffuse_pass, state);
shgrp = DRW_shgroup_create(e_data.default_lit[options], psl->lookdev_diffuse_pass);
add_standard_uniforms(shgrp, sldata, vedata, NULL, NULL, true, true, false, false, false);
DRW_shgroup_uniform_vec3(shgrp, "basecol", color_diffuse, 1);
DRW_shgroup_uniform_float_copy(shgrp, "metallic", 0.0f);
DRW_shgroup_uniform_float_copy(shgrp, "specular", 0.5f);
DRW_shgroup_uniform_float_copy(shgrp, "roughness", 1.0f);
- DRW_shgroup_call_add(shgrp, sphere, NULL);
+ DRW_shgroup_call(shgrp, sphere, NULL);
- psl->lookdev_glossy_pass = DRW_pass_create("LookDev Glossy Pass", state);
+ DRW_PASS_CREATE(psl->lookdev_glossy_pass, state);
shgrp = DRW_shgroup_create(e_data.default_lit[options], psl->lookdev_glossy_pass);
add_standard_uniforms(shgrp, sldata, vedata, NULL, NULL, true, true, false, false, false);
DRW_shgroup_uniform_vec3(shgrp, "basecol", color_chrome, 1);
DRW_shgroup_uniform_float_copy(shgrp, "metallic", 1.0f);
DRW_shgroup_uniform_float_copy(shgrp, "roughness", 0.0f);
- DRW_shgroup_call_add(shgrp, sphere, NULL);
+ DRW_shgroup_call(shgrp, sphere, NULL);
}
}
-#define ADD_SHGROUP_CALL(shgrp, ob, ma, geom, oedata) \
+#define ADD_SHGROUP_CALL(shgrp, ob, geom, oedata) \
do { \
- if (is_sculpt_mode_draw) { \
- DRW_shgroup_call_sculpt_add(shgrp, ob, ob->obmat); \
+ if (oedata) { \
+ DRW_shgroup_call_object_with_callback(shgrp, geom, ob, oedata); \
} \
else { \
- if (oedata) { \
- DRW_shgroup_call_object_add_with_callback( \
- shgrp, geom, ob, ma, EEVEE_lightprobes_obj_visibility_cb, oedata); \
- } \
- else { \
- DRW_shgroup_call_object_add_ex(shgrp, geom, ob, ma, false); \
- } \
+ DRW_shgroup_call_object(shgrp, geom, ob); \
} \
} while (0)
-#define ADD_SHGROUP_CALL_SAFE(shgrp, ob, ma, geom, oedata) \
+#define ADD_SHGROUP_CALL_SAFE(shgrp, ob, geom, oedata) \
do { \
if (shgrp) { \
- ADD_SHGROUP_CALL(shgrp, ob, ma, geom, oedata); \
+ ADD_SHGROUP_CALL(shgrp, ob, geom, oedata); \
} \
} while (0)
@@ -1221,8 +1150,6 @@ static void material_opaque(Material *ma,
GHash *material_hash,
EEVEE_ViewLayerData *sldata,
EEVEE_Data *vedata,
- bool do_cull,
- bool use_flat_nor,
struct GPUMaterial **gpumat,
struct GPUMaterial **gpumat_depth,
struct DRWShadingGroup **shgrp,
@@ -1242,11 +1169,11 @@ static void material_opaque(Material *ma,
float *spec_p = &ma->spec;
float *rough_p = &ma->roughness;
+ const bool do_cull = (ma->blend_flag & MA_BL_CULL_BACKFACE) != 0;
const bool use_gpumat = (ma->use_nodes && ma->nodetree);
const bool use_ssrefract = ((ma->blend_flag & MA_BL_SS_REFRACTION) != 0) &&
((effects->enabled_effects & EFFECT_REFRACT) != 0);
- bool use_sss = ((effects->enabled_effects & EFFECT_SSS) != 0);
- const bool use_translucency = use_sss && ((ma->blend_flag & MA_BL_TRANSLUCENCY) != 0);
+ const bool use_translucency = ((ma->blend_flag & MA_BL_TRANSLUCENCY) != 0);
EeveeMaterialShadingGroups *emsg = BLI_ghash_lookup(material_hash, (const void *)ma);
@@ -1262,7 +1189,6 @@ static void material_opaque(Material *ma,
false,
false,
use_ssrefract,
- use_sss,
use_translucency,
linfo->shadow_method) :
NULL;
@@ -1278,15 +1204,8 @@ static void material_opaque(Material *ma,
static float half = 0.5f;
/* Shading */
- *gpumat = EEVEE_material_mesh_get(scene,
- ma,
- vedata,
- false,
- false,
- use_ssrefract,
- use_sss,
- use_translucency,
- linfo->shadow_method);
+ *gpumat = EEVEE_material_mesh_get(
+ scene, ma, vedata, false, false, use_ssrefract, use_translucency, linfo->shadow_method);
eGPUMaterialStatus status_mat_surface = GPU_material_status(*gpumat);
@@ -1364,10 +1283,10 @@ static void material_opaque(Material *ma,
int *ssr_id = (((effects->enabled_effects & EFFECT_SSR) != 0) && !use_ssrefract) ?
&first_ssr :
&no_ssr;
+ const bool use_sss = GPU_material_flag_get(*gpumat, GPU_MATFLAG_SSS);
use_diffuse = GPU_material_flag_get(*gpumat, GPU_MATFLAG_DIFFUSE);
use_glossy = GPU_material_flag_get(*gpumat, GPU_MATFLAG_GLOSSY);
use_refract = GPU_material_flag_get(*gpumat, GPU_MATFLAG_REFRACT);
- use_sss = use_sss && GPU_material_flag_get(*gpumat, GPU_MATFLAG_SSS);
*shgrp = DRW_shgroup_material_create(
*gpumat,
@@ -1442,7 +1361,7 @@ static void material_opaque(Material *ma,
if (*shgrp == NULL) {
bool use_ssr = ((effects->enabled_effects & EFFECT_SSR) != 0);
*shgrp = EEVEE_default_shading_group_get(
- sldata, vedata, NULL, NULL, NULL, false, use_flat_nor, use_ssr, linfo->shadow_method);
+ sldata, vedata, NULL, NULL, NULL, false, use_ssr, linfo->shadow_method);
DRW_shgroup_uniform_vec3(*shgrp, "basecol", color_p, 1);
DRW_shgroup_uniform_float(*shgrp, "metallic", metal_p, 1);
DRW_shgroup_uniform_float(*shgrp, "specular", spec_p, 1);
@@ -1474,8 +1393,6 @@ static void material_opaque(Material *ma,
static void material_transparent(Material *ma,
EEVEE_ViewLayerData *sldata,
EEVEE_Data *vedata,
- bool do_cull,
- bool use_flat_nor,
struct GPUMaterial **gpumat,
struct DRWShadingGroup **shgrp,
struct DRWShadingGroup **shgrp_depth)
@@ -1486,6 +1403,7 @@ static void material_transparent(Material *ma,
EEVEE_PassList *psl = ((EEVEE_Data *)vedata)->psl;
EEVEE_LightsInfo *linfo = sldata->lights;
+ const bool do_cull = (ma->blend_flag & MA_BL_CULL_BACKFACE) != 0;
const bool use_ssrefract = (((ma->blend_flag & MA_BL_SS_REFRACTION) != 0) &&
((stl->effects->enabled_effects & EFFECT_REFRACT) != 0));
float *color_p = &ma->r;
@@ -1506,7 +1424,6 @@ static void material_transparent(Material *ma,
(ma->blend_method == MA_BM_MULTIPLY),
use_ssrefract,
false,
- false,
linfo->shadow_method);
switch (GPU_material_status(*gpumat)) {
@@ -1548,14 +1465,8 @@ static void material_transparent(Material *ma,
/* Fallback to default shader */
if (*shgrp == NULL) {
- *shgrp = EEVEE_default_shading_group_create(sldata,
- vedata,
- psl->transparent_pass,
- false,
- use_flat_nor,
- true,
- false,
- linfo->shadow_method);
+ *shgrp = EEVEE_default_shading_group_create(
+ sldata, vedata, psl->transparent_pass, false, true, false, linfo->shadow_method);
DRW_shgroup_uniform_vec3(*shgrp, "basecol", color_p, 1);
DRW_shgroup_uniform_float(*shgrp, "metallic", metal_p, 1);
DRW_shgroup_uniform_float(*shgrp, "specular", spec_p, 1);
@@ -1594,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;
@@ -1604,6 +1514,16 @@ static void material_transparent(Material *ma,
}
}
+/* Return correct material or &defmaterial if slot is empty. */
+BLI_INLINE Material *eevee_object_material_get(Object *ob, int slot)
+{
+ Material *ma = give_current_material(ob, slot + 1);
+ if (ma == NULL) {
+ ma = &defmaterial;
+ }
+ return ma;
+}
+
void EEVEE_materials_cache_populate(EEVEE_Data *vedata,
EEVEE_ViewLayerData *sldata,
Object *ob,
@@ -1615,17 +1535,14 @@ void EEVEE_materials_cache_populate(EEVEE_Data *vedata,
Scene *scene = draw_ctx->scene;
GHash *material_hash = stl->g_data->material_hash;
- const bool do_cull = (draw_ctx->v3d &&
- (draw_ctx->v3d->shading.flag & V3D_SHADING_BACKFACE_CULLING));
- const bool is_sculpt_mode = (ob->sculpt != NULL);
+ bool is_sculpt_mode = DRW_object_use_pbvh_drawing(ob);
/* For now just force fully shaded with eevee when supported. */
- const bool is_sculpt_mode_draw = ob->sculpt && ob->sculpt->pbvh &&
- BKE_pbvh_type(ob->sculpt->pbvh) != PBVH_FACES;
- const bool is_default_mode_shader = is_sculpt_mode;
+ is_sculpt_mode = is_sculpt_mode &&
+ !(ob->sculpt->pbvh && BKE_pbvh_type(ob->sculpt->pbvh) == PBVH_FACES);
/* First get materials for this mesh. */
if (ELEM(ob->type, OB_MESH, OB_CURVE, OB_SURF, OB_FONT, OB_MBALL)) {
- const int materials_len = MAX2(1, (is_sculpt_mode_draw ? 1 : ob->totcol));
+ const int materials_len = MAX2(1, ob->totcol);
struct DRWShadingGroup **shgrp_array = BLI_array_alloca(shgrp_array, materials_len);
struct DRWShadingGroup **shgrp_depth_array = BLI_array_alloca(shgrp_depth_array,
@@ -1635,45 +1552,24 @@ void EEVEE_materials_cache_populate(EEVEE_Data *vedata,
struct GPUMaterial **gpumat_array = BLI_array_alloca(gpumat_array, materials_len);
struct GPUMaterial **gpumat_depth_array = BLI_array_alloca(gpumat_array, materials_len);
-
- bool use_flat_nor = false;
-
- if (is_default_mode_shader) {
- if (is_sculpt_mode_draw) {
- use_flat_nor = DRW_object_is_flat_normal(ob);
- }
- }
+ struct Material **ma_array = BLI_array_alloca(ma_array, materials_len);
for (int i = 0; i < materials_len; ++i) {
- Material *ma;
-
- if (is_sculpt_mode_draw) {
- ma = NULL;
- }
- else {
- ma = give_current_material(ob, i + 1);
- }
-
+ ma_array[i] = eevee_object_material_get(ob, i);
gpumat_array[i] = NULL;
gpumat_depth_array[i] = NULL;
shgrp_array[i] = NULL;
shgrp_depth_array[i] = NULL;
shgrp_depth_clip_array[i] = NULL;
- if (ma == NULL) {
- ma = &defmaterial;
- }
-
- switch (ma->blend_method) {
+ switch (ma_array[i]->blend_method) {
case MA_BM_SOLID:
case MA_BM_CLIP:
case MA_BM_HASHED:
- material_opaque(ma,
+ material_opaque(ma_array[i],
material_hash,
sldata,
vedata,
- do_cull,
- use_flat_nor,
&gpumat_array[i],
&gpumat_depth_array[i],
&shgrp_array[i],
@@ -1683,11 +1579,9 @@ void EEVEE_materials_cache_populate(EEVEE_Data *vedata,
case MA_BM_ADD:
case MA_BM_MULTIPLY:
case MA_BM_BLEND:
- material_transparent(ma,
+ material_transparent(ma_array[i],
sldata,
vedata,
- do_cull,
- use_flat_nor,
&gpumat_array[i],
&shgrp_array[i],
&shgrp_depth_array[i]);
@@ -1698,10 +1592,6 @@ void EEVEE_materials_cache_populate(EEVEE_Data *vedata,
}
}
- if (is_sculpt_mode && is_sculpt_mode_draw == false) {
- DRW_cache_mesh_sculpt_coords_ensure(ob);
- }
-
/* Only support single volume material for now. */
/* XXX We rely on the previously compiled surface shader
* to know if the material has a "volume nodetree".
@@ -1716,7 +1606,7 @@ void EEVEE_materials_cache_populate(EEVEE_Data *vedata,
int auto_layer_count;
struct GPUBatch **mat_geom = NULL;
- if (!is_sculpt_mode_draw) {
+ if (!is_sculpt_mode) {
mat_geom = DRW_cache_object_surface_material_get(ob,
gpumat_array,
materials_len,
@@ -1725,17 +1615,19 @@ void EEVEE_materials_cache_populate(EEVEE_Data *vedata,
&auto_layer_count);
}
- if (is_sculpt_mode_draw || mat_geom) {
+ if (is_sculpt_mode) {
+ /* Vcol is not supported in the modes that require PBVH drawing. */
+ bool use_vcol = false;
+ DRW_shgroup_call_sculpt_with_materials(shgrp_array, ob, use_vcol);
+ DRW_shgroup_call_sculpt_with_materials(shgrp_depth_array, ob, use_vcol);
+ DRW_shgroup_call_sculpt_with_materials(shgrp_depth_clip_array, ob, use_vcol);
+ /* TODO(fclem): Support shadows in sculpt mode. */
+ }
+ else if (mat_geom) {
for (int i = 0; i < materials_len; ++i) {
- if (!is_sculpt_mode_draw && mat_geom[i] == NULL) {
+ if (mat_geom[i] == NULL) {
continue;
}
- EEVEE_ObjectEngineData *oedata = NULL;
- Material *ma = give_current_material(ob, i + 1);
-
- if (ma == NULL) {
- ma = &defmaterial;
- }
/* Do not render surface if we are rendering a volume object
* and do not have a surface closure. */
@@ -1746,23 +1638,16 @@ void EEVEE_materials_cache_populate(EEVEE_Data *vedata,
/* XXX TODO rewrite this to include the dupli objects.
* This means we cannot exclude dupli objects from reflections!!! */
+ EEVEE_ObjectEngineData *oedata = NULL;
if ((ob->base_flag & BASE_FROM_DUPLI) == 0) {
oedata = EEVEE_object_data_ensure(ob);
oedata->ob = ob;
oedata->test_data = &sldata->probes->vis_data;
}
- /* Shading pass */
- ADD_SHGROUP_CALL(shgrp_array[i], ob, ma, mat_geom[i], oedata);
-
- /* Depth Prepass */
- ADD_SHGROUP_CALL_SAFE(shgrp_depth_array[i], ob, ma, mat_geom[i], oedata);
- ADD_SHGROUP_CALL_SAFE(shgrp_depth_clip_array[i], ob, ma, mat_geom[i], oedata);
-
- /* TODO(fclem): Don't support shadows in sculpt mode. */
- if (is_sculpt_mode_draw) {
- break;
- }
+ ADD_SHGROUP_CALL(shgrp_array[i], ob, mat_geom[i], oedata);
+ ADD_SHGROUP_CALL_SAFE(shgrp_depth_array[i], ob, mat_geom[i], oedata);
+ ADD_SHGROUP_CALL_SAFE(shgrp_depth_clip_array[i], ob, mat_geom[i], oedata);
char *name = auto_layer_names;
for (int j = 0; j < auto_layer_count; ++j) {
@@ -1785,19 +1670,19 @@ void EEVEE_materials_cache_populate(EEVEE_Data *vedata,
/* Shadow Pass */
struct GPUMaterial *gpumat;
- switch (ma->blend_shadow) {
+ switch (ma_array[i]->blend_shadow) {
case MA_BS_SOLID:
EEVEE_lights_cache_shcaster_add(sldata, stl, mat_geom[i], ob);
*cast_shadow = true;
break;
case MA_BS_CLIP:
- gpumat = EEVEE_material_mesh_depth_get(scene, ma, false, true);
+ gpumat = EEVEE_material_mesh_depth_get(scene, ma_array[i], false, true);
EEVEE_lights_cache_shcaster_material_add(
- sldata, psl, gpumat, mat_geom[i], ob, &ma->alpha_threshold);
+ sldata, psl, gpumat, mat_geom[i], ob, &ma_array[i]->alpha_threshold);
*cast_shadow = true;
break;
case MA_BS_HASHED:
- gpumat = EEVEE_material_mesh_depth_get(scene, ma, true, true);
+ gpumat = EEVEE_material_mesh_depth_get(scene, ma_array[i], true, true);
EEVEE_lights_cache_shcaster_material_add(sldata, psl, gpumat, mat_geom[i], ob, NULL);
*cast_shadow = true;
break;
@@ -1810,7 +1695,7 @@ void EEVEE_materials_cache_populate(EEVEE_Data *vedata,
}
/* Volumetrics */
- if (((stl->effects->enabled_effects & EFFECT_VOLUMETRIC) != 0) && use_volume_material) {
+ if (use_volume_material) {
EEVEE_volumes_cache_object_add(sldata, vedata, scene, ob);
}
}
@@ -1845,11 +1730,7 @@ void EEVEE_hair_cache_populate(EEVEE_Data *vedata,
}
DRWShadingGroup *shgrp = NULL;
- Material *ma = give_current_material(ob, part->omat);
-
- if (ma == NULL) {
- ma = &defmaterial;
- }
+ Material *ma = eevee_object_material_get(ob, part->omat - 1);
float *color_p = &ma->r;
float *metal_p = &ma->metallic;
@@ -1861,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) {
@@ -1916,7 +1796,7 @@ void EEVEE_hair_cache_populate(EEVEE_Data *vedata,
/* Fallback to default shader */
if (shgrp == NULL) {
shgrp = EEVEE_default_shading_group_get(
- sldata, vedata, ob, psys, md, true, false, use_ssr, sldata->lights->shadow_method);
+ sldata, vedata, ob, psys, md, true, use_ssr, sldata->lights->shadow_method);
DRW_shgroup_uniform_vec3(shgrp, "basecol", color_p, 1);
DRW_shgroup_uniform_float(shgrp, "metallic", metal_p, 1);
DRW_shgroup_uniform_float(shgrp, "specular", spec_p, 1);
@@ -1931,11 +1811,16 @@ void EEVEE_hair_cache_populate(EEVEE_Data *vedata,
}
}
-void EEVEE_materials_cache_finish(EEVEE_Data *vedata)
+void EEVEE_materials_cache_finish(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata)
{
EEVEE_StorageList *stl = ((EEVEE_Data *)vedata)->stl;
BLI_ghash_free(stl->g_data->material_hash, NULL, MEM_freeN);
+
+ SET_FLAG_FROM_TEST(stl->effects->enabled_effects, e_data.sss_count > 0, EFFECT_SSS);
+
+ /* TODO(fclem) this is not really clean. Init should not be done in cache finish. */
+ EEVEE_subsurface_draw_init(sldata, vedata);
}
void EEVEE_materials_free(void)
@@ -1945,6 +1830,7 @@ void EEVEE_materials_free(void)
}
MEM_SAFE_FREE(e_data.frag_shader_lib);
MEM_SAFE_FREE(e_data.vert_shader_str);
+ MEM_SAFE_FREE(e_data.vert_shadow_shader_str);
MEM_SAFE_FREE(e_data.volume_shader_lib);
DRW_SHADER_FREE_SAFE(e_data.default_hair_prepass_sh);
DRW_SHADER_FREE_SAFE(e_data.default_hair_prepass_clip_sh);
diff --git a/source/blender/draw/engines/eevee/eevee_mist.c b/source/blender/draw/engines/eevee/eevee_mist.c
index 1ea1e086aea..9f989146b05 100644
--- a/source/blender/draw/engines/eevee/eevee_mist.c
+++ b/source/blender/draw/engines/eevee/eevee_mist.c
@@ -106,12 +106,12 @@ void EEVEE_mist_output_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata)
g_data->mist_falloff *= 0.5f;
/* Create Pass and shgroup. */
- psl->mist_accum_ps = DRW_pass_create("Mist Accum", DRW_STATE_WRITE_COLOR | DRW_STATE_ADDITIVE);
+ DRW_PASS_CREATE(psl->mist_accum_ps, DRW_STATE_WRITE_COLOR | DRW_STATE_ADDITIVE);
DRWShadingGroup *grp = DRW_shgroup_create(e_data.mist_sh, psl->mist_accum_ps);
DRW_shgroup_uniform_texture_ref(grp, "depthBuffer", &dtxl->depth);
DRW_shgroup_uniform_block(grp, "common_block", sldata->common_ubo);
DRW_shgroup_uniform_vec3(grp, "mistSettings", &g_data->mist_start, 1);
- DRW_shgroup_call_add(grp, DRW_cache_fullscreen_quad_get(), NULL);
+ DRW_shgroup_call(grp, DRW_cache_fullscreen_quad_get(), NULL);
}
void EEVEE_mist_output_accumulate(EEVEE_ViewLayerData *UNUSED(sldata), EEVEE_Data *vedata)
diff --git a/source/blender/draw/engines/eevee/eevee_motion_blur.c b/source/blender/draw/engines/eevee/eevee_motion_blur.c
index f8795a7ff0e..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);
@@ -195,7 +195,7 @@ void EEVEE_motion_blur_cache_init(EEVEE_ViewLayerData *UNUSED(sldata), EEVEE_Dat
struct GPUBatch *quad = DRW_cache_fullscreen_quad_get();
if ((effects->enabled_effects & EFFECT_MOTION_BLUR) != 0) {
- psl->motion_blur = DRW_pass_create("Motion Blur", DRW_STATE_WRITE_COLOR);
+ DRW_PASS_CREATE(psl->motion_blur, DRW_STATE_WRITE_COLOR);
DRWShadingGroup *grp = DRW_shgroup_create(e_data.motion_blur_sh, psl->motion_blur);
DRW_shgroup_uniform_int(grp, "samples", &effects->motion_blur_samples, 1);
@@ -203,7 +203,7 @@ void EEVEE_motion_blur_cache_init(EEVEE_ViewLayerData *UNUSED(sldata), EEVEE_Dat
DRW_shgroup_uniform_mat4(grp, "pastViewProjMatrix", effects->past_world_to_ndc);
DRW_shgroup_uniform_texture_ref(grp, "colorBuffer", &effects->source_buffer);
DRW_shgroup_uniform_texture_ref(grp, "depthBuffer", &dtxl->depth);
- DRW_shgroup_call_add(grp, quad, NULL);
+ DRW_shgroup_call(grp, quad, NULL);
}
}
diff --git a/source/blender/draw/engines/eevee/eevee_occlusion.c b/source/blender/draw/engines/eevee/eevee_occlusion.c
index 822df19f899..59def366695 100644
--- a/source/blender/draw/engines/eevee/eevee_occlusion.c
+++ b/source/blender/draw/engines/eevee/eevee_occlusion.c
@@ -41,6 +41,8 @@ static struct {
struct GPUShader *gtao_layer_sh;
struct GPUShader *gtao_debug_sh;
struct GPUTexture *src_depth;
+
+ struct GPUTexture *dummy_horizon_tx;
} e_data = {NULL}; /* Engine data */
extern char datatoc_ambient_occlusion_lib_glsl[];
@@ -74,6 +76,11 @@ int EEVEE_occlusion_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata)
const DRWContextState *draw_ctx = DRW_context_state_get();
const Scene *scene_eval = DEG_get_evaluated_scene(draw_ctx->depsgraph);
+ if (!e_data.dummy_horizon_tx) {
+ float pixel[4] = {0.0f, 0.0f, 0.0f, 0.0f};
+ e_data.dummy_horizon_tx = DRW_texture_create_2d(1, 1, GPU_RGBA8, DRW_TEX_WRAP, pixel);
+ }
+
if (scene_eval->eevee.flag & SCE_EEVEE_GTAO_ENABLED) {
const float *viewport_size = DRW_viewport_size_get();
const int fs_size[2] = {(int)viewport_size[0], (int)viewport_size[1]};
@@ -117,7 +124,7 @@ int EEVEE_occlusion_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata)
}
/* Cleanup */
- effects->gtao_horizons = NULL;
+ effects->gtao_horizons = e_data.dummy_horizon_tx;
GPU_FRAMEBUFFER_FREE_SAFE(fbl->gtao_fb);
common_data->ao_settings = 0.0f;
@@ -151,7 +158,7 @@ void EEVEE_occlusion_output_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata
/* Accumulation pass */
DRWState state = DRW_STATE_WRITE_COLOR | DRW_STATE_ADDITIVE;
- psl->ao_accum_ps = DRW_pass_create("AO Accum", state);
+ DRW_PASS_CREATE(psl->ao_accum_ps, state);
DRWShadingGroup *grp = DRW_shgroup_create(e_data.gtao_debug_sh, psl->ao_accum_ps);
DRW_shgroup_uniform_texture(grp, "utilTex", EEVEE_materials_get_util_tex());
DRW_shgroup_uniform_texture_ref(grp, "maxzBuffer", &txl->maxzbuffer);
@@ -159,7 +166,7 @@ void EEVEE_occlusion_output_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata
DRW_shgroup_uniform_texture_ref(grp, "normalBuffer", &effects->ssr_normal_input);
DRW_shgroup_uniform_texture_ref(grp, "horizonBuffer", &effects->gtao_horizons);
DRW_shgroup_uniform_block(grp, "common_block", sldata->common_ubo);
- DRW_shgroup_call_add(grp, DRW_cache_fullscreen_quad_get(), NULL);
+ DRW_shgroup_call(grp, DRW_cache_fullscreen_quad_get(), NULL);
}
else {
/* Cleanup to release memory */
@@ -190,26 +197,25 @@ void EEVEE_occlusion_cache_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata)
* the shading stage. This let us do correct shadowing for each diffuse / specular
* lobe present in the shader using the correct normal.
*/
- psl->ao_horizon_search = DRW_pass_create("GTAO Horizon Search", DRW_STATE_WRITE_COLOR);
+ DRW_PASS_CREATE(psl->ao_horizon_search, DRW_STATE_WRITE_COLOR);
DRWShadingGroup *grp = DRW_shgroup_create(e_data.gtao_sh, psl->ao_horizon_search);
DRW_shgroup_uniform_texture(grp, "utilTex", EEVEE_materials_get_util_tex());
DRW_shgroup_uniform_texture_ref(grp, "maxzBuffer", &txl->maxzbuffer);
DRW_shgroup_uniform_texture_ref(grp, "depthBuffer", &effects->ao_src_depth);
DRW_shgroup_uniform_block(grp, "common_block", sldata->common_ubo);
- DRW_shgroup_call_add(grp, quad, NULL);
+ DRW_shgroup_call(grp, quad, NULL);
- psl->ao_horizon_search_layer = DRW_pass_create("GTAO Horizon Search Layer",
- DRW_STATE_WRITE_COLOR);
+ DRW_PASS_CREATE(psl->ao_horizon_search_layer, DRW_STATE_WRITE_COLOR);
grp = DRW_shgroup_create(e_data.gtao_layer_sh, psl->ao_horizon_search_layer);
DRW_shgroup_uniform_texture(grp, "utilTex", EEVEE_materials_get_util_tex());
DRW_shgroup_uniform_texture_ref(grp, "maxzBuffer", &txl->maxzbuffer);
DRW_shgroup_uniform_texture_ref(grp, "depthBufferLayered", &effects->ao_src_depth);
DRW_shgroup_uniform_block(grp, "common_block", sldata->common_ubo);
DRW_shgroup_uniform_int(grp, "layer", &stl->effects->ao_depth_layer, 1);
- DRW_shgroup_call_add(grp, quad, NULL);
+ DRW_shgroup_call(grp, quad, NULL);
if (G.debug_value == 6) {
- psl->ao_horizon_debug = DRW_pass_create("GTAO Horizon Debug", DRW_STATE_WRITE_COLOR);
+ DRW_PASS_CREATE(psl->ao_horizon_debug, DRW_STATE_WRITE_COLOR);
grp = DRW_shgroup_create(e_data.gtao_debug_sh, psl->ao_horizon_debug);
DRW_shgroup_uniform_texture(grp, "utilTex", EEVEE_materials_get_util_tex());
DRW_shgroup_uniform_texture_ref(grp, "maxzBuffer", &txl->maxzbuffer);
@@ -217,7 +223,7 @@ void EEVEE_occlusion_cache_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata)
DRW_shgroup_uniform_texture_ref(grp, "normalBuffer", &effects->ssr_normal_input);
DRW_shgroup_uniform_texture_ref(grp, "horizonBuffer", &effects->gtao_horizons);
DRW_shgroup_uniform_block(grp, "common_block", sldata->common_ubo);
- DRW_shgroup_call_add(grp, quad, NULL);
+ DRW_shgroup_call(grp, quad, NULL);
}
}
}
@@ -304,4 +310,5 @@ void EEVEE_occlusion_free(void)
DRW_SHADER_FREE_SAFE(e_data.gtao_sh);
DRW_SHADER_FREE_SAFE(e_data.gtao_layer_sh);
DRW_SHADER_FREE_SAFE(e_data.gtao_debug_sh);
+ DRW_TEXTURE_FREE_SAFE(e_data.dummy_horizon_tx);
}
diff --git a/source/blender/draw/engines/eevee/eevee_private.h b/source/blender/draw/engines/eevee/eevee_private.h
index c3cd25923b2..2e652dff232 100644
--- a/source/blender/draw/engines/eevee/eevee_private.h
+++ b/source/blender/draw/engines/eevee/eevee_private.h
@@ -147,26 +147,24 @@ enum {
VAR_MAT_MESH = (1 << 0),
VAR_MAT_PROBE = (1 << 1),
VAR_MAT_HAIR = (1 << 2),
- VAR_MAT_FLAT = (1 << 3),
- VAR_MAT_BLEND = (1 << 4),
- VAR_MAT_VSM = (1 << 5),
- VAR_MAT_ESM = (1 << 6),
- VAR_MAT_VOLUME = (1 << 7),
- VAR_MAT_LOOKDEV = (1 << 8),
+ VAR_MAT_BLEND = (1 << 3),
+ VAR_MAT_VSM = (1 << 4),
+ VAR_MAT_ESM = (1 << 5),
+ VAR_MAT_VOLUME = (1 << 6),
+ VAR_MAT_LOOKDEV = (1 << 7),
/* Max number of variation */
/* IMPORTANT : Leave it last and set
* it's value accordingly. */
- VAR_MAT_MAX = (1 << 9),
+ VAR_MAT_MAX = (1 << 8),
/* These are options that are not counted in VAR_MAT_MAX
* because they are not cumulative with the others above. */
- VAR_MAT_CLIP = (1 << 10),
- VAR_MAT_HASH = (1 << 11),
- VAR_MAT_MULT = (1 << 12),
- VAR_MAT_SHADOW = (1 << 13),
- VAR_MAT_REFRACT = (1 << 14),
- VAR_MAT_SSS = (1 << 15),
- VAR_MAT_TRANSLUC = (1 << 16),
- VAR_MAT_SSSALBED = (1 << 17),
+ VAR_MAT_CLIP = (1 << 9),
+ VAR_MAT_HASH = (1 << 10),
+ VAR_MAT_MULT = (1 << 11),
+ VAR_MAT_SHADOW = (1 << 12),
+ VAR_MAT_REFRACT = (1 << 13),
+ VAR_MAT_TRANSLUC = (1 << 15),
+ VAR_MAT_SSSALBED = (1 << 16),
};
/* ************ PROBE UBO ************* */
@@ -335,9 +333,9 @@ typedef struct EEVEE_TextureList {
struct GPUTexture *volume_prop_emission;
struct GPUTexture *volume_prop_phase;
struct GPUTexture *volume_scatter;
- struct GPUTexture *volume_transmittance;
+ struct GPUTexture *volume_transmit;
struct GPUTexture *volume_scatter_history;
- struct GPUTexture *volume_transmittance_history;
+ struct GPUTexture *volume_transmit_history;
struct GPUTexture *lookdev_grid_tx;
struct GPUTexture *lookdev_cube_tx;
@@ -554,6 +552,8 @@ typedef struct EEVEE_EffectsInfo {
struct GPUTexture *sss_stencil;
/* Volumetrics */
int volume_current_sample;
+ struct GPUTexture *volume_scatter;
+ struct GPUTexture *volume_transmit;
/* SSR */
bool reflection_trace_full;
bool ssr_was_persp;
@@ -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 ball_size;
+ 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];
@@ -817,8 +807,7 @@ typedef struct EEVEE_PrivateData {
struct DRWShadingGroup *refract_depth_shgrp_cull;
struct DRWShadingGroup *refract_depth_shgrp_clip;
struct DRWShadingGroup *refract_depth_shgrp_clip_cull;
- struct DRWShadingGroup *cube_display_shgrp;
- struct DRWShadingGroup *planar_display_shgrp;
+ struct DRWCallBuffer *planar_display_shgrp;
struct GHash *material_hash;
float background_alpha; /* TODO find a better place for this. */
/* Chosen lightcache: can come from Lookdev or the viewlayer. */
@@ -830,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];
@@ -850,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 */
@@ -880,7 +874,7 @@ void EEVEE_hair_cache_populate(EEVEE_Data *vedata,
EEVEE_ViewLayerData *sldata,
Object *ob,
bool *cast_shadow);
-void EEVEE_materials_cache_finish(EEVEE_Data *vedata);
+void EEVEE_materials_cache_finish(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata);
struct GPUMaterial *EEVEE_material_world_lightprobe_get(struct Scene *scene, struct World *wo);
struct GPUMaterial *EEVEE_material_world_background_get(struct Scene *scene, struct World *wo);
struct GPUMaterial *EEVEE_material_world_volume_get(struct Scene *scene, struct World *wo);
@@ -890,7 +884,6 @@ struct GPUMaterial *EEVEE_material_mesh_get(struct Scene *scene,
bool use_blend,
bool use_multiply,
bool use_refract,
- bool use_sss,
bool use_translucency,
int shadow_method);
struct GPUMaterial *EEVEE_material_mesh_volume_get(struct Scene *scene, Material *ma);
@@ -921,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 */
@@ -1027,7 +1020,8 @@ void EEVEE_reflection_compute(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata);
void EEVEE_screen_raytrace_free(void);
/* eevee_subsurface.c */
-int EEVEE_subsurface_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata);
+void EEVEE_subsurface_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata);
+void EEVEE_subsurface_draw_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata);
void EEVEE_subsurface_cache_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata);
void EEVEE_subsurface_output_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata);
void EEVEE_subsurface_add_pass(EEVEE_ViewLayerData *sldata,
@@ -1056,21 +1050,21 @@ 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);
/* eevee_volumes.c */
-int EEVEE_volumes_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata);
+void EEVEE_volumes_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata);
void EEVEE_volumes_set_jitter(EEVEE_ViewLayerData *sldata, uint current_sample);
void EEVEE_volumes_cache_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata);
void EEVEE_volumes_cache_object_add(EEVEE_ViewLayerData *sldata,
EEVEE_Data *vedata,
struct Scene *scene,
Object *ob);
+void EEVEE_volumes_cache_finish(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata);
+void EEVEE_volumes_draw_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata);
void EEVEE_volumes_compute(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata);
void EEVEE_volumes_resolve(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata);
void EEVEE_volumes_free_smoke_textures(void);
@@ -1082,6 +1076,7 @@ void EEVEE_effects_init(EEVEE_ViewLayerData *sldata,
Object *camera,
const bool minimal);
void EEVEE_effects_cache_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata);
+void EEVEE_effects_draw_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata);
void EEVEE_create_minmax_buffer(EEVEE_Data *vedata, struct GPUTexture *depth_src, int layer);
void EEVEE_downsample_buffer(EEVEE_Data *vedata, struct GPUTexture *texture_src, int level);
void EEVEE_downsample_cube_buffer(EEVEE_Data *vedata, struct GPUTexture *texture_src, int level);
diff --git a/source/blender/draw/engines/eevee/eevee_render.c b/source/blender/draw/engines/eevee/eevee_render.c
index 961fe103251..8ef613f3711 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,22 @@ 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];
+
+ print_v4_id(camtexcofac);
}
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 +114,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 +311,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 +332,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 +365,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 viewmat[4][4];
+ DRW_view_viewmat_get(NULL, viewmat, false);
/* Convert ogl depth [0..1] to view Z [near..far] */
for (int i = 0; i < rp->rectx * rp->recty; ++i) {
@@ -365,7 +378,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] = viewmat[3][2] / (rp->rect[i] + viewmat[2][2]);
}
else {
rp->rect[i] = -common_data->view_vecs[0][2] +
@@ -486,10 +499,14 @@ void EEVEE_render_draw(EEVEE_Data *vedata, RenderEngine *engine, RenderLayer *rl
EEVEE_PrivateData *g_data = stl->g_data;
/* FINISH CACHE */
- EEVEE_materials_cache_finish(vedata);
+ EEVEE_volumes_cache_finish(sldata, vedata);
+ EEVEE_materials_cache_finish(sldata, vedata);
EEVEE_lights_cache_finish(sldata, vedata);
EEVEE_lightprobes_cache_finish(sldata, vedata);
+ EEVEE_effects_draw_init(sldata, vedata);
+ EEVEE_volumes_draw_init(sldata, vedata);
+
/* Sort transparents before the loop. */
DRW_pass_sort_shgroup_z(psl->transparent_pass);
@@ -529,25 +546,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);
@@ -562,7 +569,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 22c7dd00b97..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();
@@ -215,7 +215,7 @@ void EEVEE_screen_raytrace_cache_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *v
* mipmap for each ray using its pdf. (filtered importance sampling)
* We then evaluate the lighting from the probes and mix the results together.
*/
- psl->ssr_raytrace = DRW_pass_create("SSR Raytrace", DRW_STATE_WRITE_COLOR);
+ DRW_PASS_CREATE(psl->ssr_raytrace, DRW_STATE_WRITE_COLOR);
DRWShadingGroup *grp = DRW_shgroup_create(trace_shader, psl->ssr_raytrace);
DRW_shgroup_uniform_texture_ref(grp, "depthBuffer", &e_data.depth_src);
DRW_shgroup_uniform_texture_ref(grp, "normalBuffer", &effects->ssr_normal_input);
@@ -230,9 +230,9 @@ void EEVEE_screen_raytrace_cache_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *v
if (!effects->reflection_trace_full) {
DRW_shgroup_uniform_ivec2(grp, "halfresOffset", effects->ssr_halfres_ofs, 1);
}
- DRW_shgroup_call_add(grp, quad, NULL);
+ DRW_shgroup_call(grp, quad, NULL);
- psl->ssr_resolve = DRW_pass_create("SSR Resolve", DRW_STATE_WRITE_COLOR | DRW_STATE_ADDITIVE);
+ DRW_PASS_CREATE(psl->ssr_resolve, DRW_STATE_WRITE_COLOR | DRW_STATE_ADDITIVE);
grp = DRW_shgroup_create(resolve_shader, psl->ssr_resolve);
DRW_shgroup_uniform_texture_ref(grp, "depthBuffer", &e_data.depth_src);
DRW_shgroup_uniform_texture_ref(grp, "normalBuffer", &effects->ssr_normal_input);
@@ -253,7 +253,7 @@ void EEVEE_screen_raytrace_cache_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *v
DRW_shgroup_uniform_texture_ref(grp, "horizonBuffer", &effects->gtao_horizons);
}
- DRW_shgroup_call_add(grp, quad, NULL);
+ DRW_shgroup_call(grp, quad, NULL);
}
}
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_subsurface.c b/source/blender/draw/engines/eevee/eevee_subsurface.c
index cbe0f474ac7..19aefd03e72 100644
--- a/source/blender/draw/engines/eevee/eevee_subsurface.c
+++ b/source/blender/draw/engines/eevee/eevee_subsurface.c
@@ -59,30 +59,30 @@ static void eevee_create_shader_subsurface(void)
MEM_freeN(frag_str);
}
-int EEVEE_subsurface_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata)
+void EEVEE_subsurface_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata)
{
EEVEE_CommonUniformBuffer *common_data = &sldata->common_data;
EEVEE_StorageList *stl = vedata->stl;
EEVEE_EffectsInfo *effects = stl->effects;
- EEVEE_FramebufferList *fbl = vedata->fbl;
- EEVEE_TextureList *txl = vedata->txl;
- DefaultTextureList *dtxl = DRW_viewport_texture_list_get();
- const float *viewport_size = DRW_viewport_size_get();
- const int fs_size[2] = {(int)viewport_size[0], (int)viewport_size[1]};
const DRWContextState *draw_ctx = DRW_context_state_get();
const Scene *scene_eval = DEG_get_evaluated_scene(draw_ctx->depsgraph);
- if (scene_eval->eevee.flag & SCE_EEVEE_SSS_ENABLED) {
- effects->sss_sample_count = 1 + scene_eval->eevee.sss_samples * 2;
- effects->sss_separate_albedo = (scene_eval->eevee.flag & SCE_EEVEE_SSS_SEPARATE_ALBEDO) != 0;
- common_data->sss_jitter_threshold = scene_eval->eevee.sss_jitter_threshold;
+ effects->sss_sample_count = 1 + scene_eval->eevee.sss_samples * 2;
+ effects->sss_separate_albedo = (scene_eval->eevee.flag & SCE_EEVEE_SSS_SEPARATE_ALBEDO) != 0;
+ common_data->sss_jitter_threshold = scene_eval->eevee.sss_jitter_threshold;
+}
- /* Shaders */
- if (!e_data.sss_sh[0]) {
- eevee_create_shader_subsurface();
- }
+void EEVEE_subsurface_draw_init(EEVEE_ViewLayerData *UNUSED(sldata), EEVEE_Data *vedata)
+{
+ EEVEE_EffectsInfo *effects = vedata->stl->effects;
+ EEVEE_FramebufferList *fbl = vedata->fbl;
+ EEVEE_TextureList *txl = vedata->txl;
+ DefaultTextureList *dtxl = DRW_viewport_texture_list_get();
+ const float *viewport_size = DRW_viewport_size_get();
+ const int fs_size[2] = {(int)viewport_size[0], (int)viewport_size[1]};
+ if (effects->enabled_effects & EFFECT_SSS) {
/* NOTE : we need another stencil because the stencil buffer is on the same texture
* as the depth buffer we are sampling from. This could be avoided if the stencil is
* a separate texture but that needs OpenGL 4.4 or ARB_texture_stencil8.
@@ -124,18 +124,16 @@ int EEVEE_subsurface_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata)
else {
effects->sss_albedo = NULL;
}
- return EFFECT_SSS;
}
-
- /* Cleanup to release memory */
- GPU_FRAMEBUFFER_FREE_SAFE(fbl->sss_blur_fb);
- GPU_FRAMEBUFFER_FREE_SAFE(fbl->sss_resolve_fb);
- GPU_FRAMEBUFFER_FREE_SAFE(fbl->sss_clear_fb);
- effects->sss_stencil = NULL;
- effects->sss_blur = NULL;
- effects->sss_data = NULL;
-
- return 0;
+ else {
+ /* Cleanup to release memory */
+ GPU_FRAMEBUFFER_FREE_SAFE(fbl->sss_blur_fb);
+ GPU_FRAMEBUFFER_FREE_SAFE(fbl->sss_resolve_fb);
+ GPU_FRAMEBUFFER_FREE_SAFE(fbl->sss_clear_fb);
+ effects->sss_stencil = NULL;
+ effects->sss_blur = NULL;
+ effects->sss_data = NULL;
+ }
}
static void set_shgrp_stencil(void *UNUSED(userData), DRWShadingGroup *shgrp)
@@ -150,17 +148,14 @@ void EEVEE_subsurface_output_init(EEVEE_ViewLayerData *UNUSED(sldata), EEVEE_Dat
EEVEE_StorageList *stl = vedata->stl;
EEVEE_EffectsInfo *effects = stl->effects;
- DefaultTextureList *dtxl = DRW_viewport_texture_list_get();
- const DRWContextState *draw_ctx = DRW_context_state_get();
- const Scene *scene_eval = DEG_get_evaluated_scene(draw_ctx->depsgraph);
-
- if (scene_eval->eevee.flag & SCE_EEVEE_SSS_ENABLED) {
+ if (effects->enabled_effects & EFFECT_SSS) {
DRW_texture_ensure_fullscreen_2d(&txl->sss_dir_accum, GPU_RGBA16F, 0);
DRW_texture_ensure_fullscreen_2d(&txl->sss_col_accum, GPU_RGBA16F, 0);
GPUTexture *stencil_tex = effects->sss_stencil;
if (GPU_depth_blitting_workaround()) {
+ DefaultTextureList *dtxl = DRW_viewport_texture_list_get();
/* Blitting stencil buffer does not work on macOS + Radeon Pro.
* Blit depth instead and use sss_stencil's depth as depth texture,
* and dtxl->depth as stencil mask. */
@@ -179,7 +174,7 @@ void EEVEE_subsurface_output_init(EEVEE_ViewLayerData *UNUSED(sldata), EEVEE_Dat
/* Make the opaque refraction pass mask the sss. */
DRWState state = DRW_STATE_WRITE_COLOR | DRW_STATE_DEPTH_EQUAL | DRW_STATE_CLIP_PLANES |
- DRW_STATE_WIRE | DRW_STATE_WRITE_STENCIL;
+ DRW_STATE_WRITE_STENCIL;
DRW_pass_state_set(vedata->psl->refract_pass, state);
DRW_pass_foreach_shgroup(vedata->psl->refract_pass, &set_shgrp_stencil, NULL);
}
@@ -194,20 +189,19 @@ void EEVEE_subsurface_output_init(EEVEE_ViewLayerData *UNUSED(sldata), EEVEE_Dat
void EEVEE_subsurface_cache_init(EEVEE_ViewLayerData *UNUSED(sldata), EEVEE_Data *vedata)
{
EEVEE_PassList *psl = vedata->psl;
- EEVEE_StorageList *stl = vedata->stl;
- EEVEE_EffectsInfo *effects = stl->effects;
- if ((effects->enabled_effects & EFFECT_SSS) != 0) {
- /** Screen Space SubSurface Scattering overview
- * TODO
- */
- psl->sss_blur_ps = DRW_pass_create("Blur Horiz",
- DRW_STATE_WRITE_COLOR | DRW_STATE_STENCIL_EQUAL);
-
- DRWState state = DRW_STATE_WRITE_COLOR | DRW_STATE_ADDITIVE | DRW_STATE_STENCIL_EQUAL;
- psl->sss_resolve_ps = DRW_pass_create("Blur Vert", state);
- psl->sss_accum_ps = DRW_pass_create("Resolve Accum", state);
+ /* Shaders */
+ if (!e_data.sss_sh[0]) {
+ eevee_create_shader_subsurface();
}
+
+ /** Screen Space SubSurface Scattering overview
+ * TODO
+ */
+ DRWState state = DRW_STATE_WRITE_COLOR | DRW_STATE_STENCIL_EQUAL;
+ DRW_PASS_CREATE(psl->sss_blur_ps, state);
+ DRW_PASS_CREATE(psl->sss_resolve_ps, state | DRW_STATE_ADDITIVE);
+ DRW_PASS_CREATE(psl->sss_accum_ps, state | DRW_STATE_ADDITIVE);
}
void EEVEE_subsurface_add_pass(EEVEE_ViewLayerData *sldata,
@@ -229,7 +223,7 @@ void EEVEE_subsurface_add_pass(EEVEE_ViewLayerData *sldata,
DRW_shgroup_uniform_block(grp, "sssProfile", sss_profile);
DRW_shgroup_uniform_block(grp, "common_block", sldata->common_ubo);
DRW_shgroup_stencil_mask(grp, sss_id);
- DRW_shgroup_call_add(grp, quad, NULL);
+ DRW_shgroup_call(grp, quad, NULL);
struct GPUShader *sh = (effects->sss_separate_albedo) ? e_data.sss_sh[2] : e_data.sss_sh[1];
grp = DRW_shgroup_create(sh, psl->sss_resolve_ps);
@@ -239,7 +233,7 @@ void EEVEE_subsurface_add_pass(EEVEE_ViewLayerData *sldata,
DRW_shgroup_uniform_block(grp, "sssProfile", sss_profile);
DRW_shgroup_uniform_block(grp, "common_block", sldata->common_ubo);
DRW_shgroup_stencil_mask(grp, sss_id);
- DRW_shgroup_call_add(grp, quad, NULL);
+ DRW_shgroup_call(grp, quad, NULL);
if (effects->sss_separate_albedo) {
DRW_shgroup_uniform_texture_ref(grp, "sssAlbedo", &effects->sss_albedo);
@@ -253,7 +247,7 @@ void EEVEE_subsurface_add_pass(EEVEE_ViewLayerData *sldata,
DRW_shgroup_uniform_block(grp, "sssProfile", sss_profile);
DRW_shgroup_uniform_block(grp, "common_block", sldata->common_ubo);
DRW_shgroup_stencil_mask(grp, sss_id);
- DRW_shgroup_call_add(grp, quad, NULL);
+ DRW_shgroup_call(grp, quad, NULL);
if (effects->sss_separate_albedo) {
DRW_shgroup_uniform_texture_ref(grp, "sssAlbedo", &effects->sss_albedo);
diff --git a/source/blender/draw/engines/eevee/eevee_temporal_sampling.c b/source/blender/draw/engines/eevee/eevee_temporal_sampling.c
index 194fff9b93c..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,45 @@ 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);
+
+ /* 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.
+ * Note: `DRW_MAT_PERS` and `DRW_MAT_VIEW` needs to read the original matrices. */
+void EEVEE_temporal_sampling_update_matrices(EEVEE_Data *vedata)
+{
+ EEVEE_StorageList *stl = ((EEVEE_Data *)vedata)->stl;
+ EEVEE_EffectsInfo *effects = stl->effects;
+
+ double ht_point[2];
+ double ht_offset[2] = {0.0, 0.0};
+ uint ht_primes[2] = {2, 3};
+
+ BLI_halton_2d(ht_primes, ht_offset, effects->taa_current_sample - 1, ht_point);
- 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);
+ EEVEE_temporal_sampling_matrices_calc(effects, ht_point);
+
+ DRW_view_set_active(effects->taa_view);
}
void EEVEE_temporal_sampling_reset(EEVEE_Data *vedata)
@@ -169,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;
@@ -178,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 |
@@ -210,14 +237,9 @@ 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_viewport_matrix_get(effects->overide_winmat, DRW_MAT_WIN);
- /* The view is jittered by the oglrenderer. So avoid testing in this case. */
- if (!DRW_state_is_image_render()) {
- view_is_valid = view_is_valid && compare_m4m4(persmat, effects->prev_drw_persmat, FLT_MIN);
- copy_m4_m4(effects->prev_drw_persmat, persmat);
- }
+ 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);
/* Prevent ghosting from probe data. */
view_is_valid = view_is_valid && (effects->prev_drw_support == DRW_state_draw_support());
@@ -227,23 +249,11 @@ int EEVEE_temporal_sampling_init(EEVEE_ViewLayerData *UNUSED(sldata), EEVEE_Data
(effects->taa_current_sample < effects->taa_total_sample)) ||
DRW_state_is_image_render()) {
if (view_is_valid) {
- /* OGL render already jitter the camera. */
+ /* Viewport rendering updates the matrices in `eevee_draw_background` */
if (!DRW_state_is_image_render()) {
effects->taa_current_sample += 1;
repro_flag = 0;
-
- double ht_point[2];
- double ht_offset[2] = {0.0, 0.0};
- uint ht_primes[2] = {2, 3};
-
- BLI_halton_2d(ht_primes, ht_offset, effects->taa_current_sample - 1, ht_point);
-
- EEVEE_temporal_sampling_matrices_calc(effects, viewmat, persmat, 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);
+ EEVEE_temporal_sampling_update_matrices(vedata);
}
}
else {
@@ -273,7 +283,7 @@ void EEVEE_temporal_sampling_cache_init(EEVEE_ViewLayerData *sldata, EEVEE_Data
if ((effects->enabled_effects & (EFFECT_TAA | EFFECT_TAA_REPROJECT)) != 0) {
struct GPUShader *sh = EEVEE_shaders_taa_resolve_sh_get(effects->enabled_effects);
- psl->taa_resolve = DRW_pass_create("Temporal AA Resolve", DRW_STATE_WRITE_COLOR);
+ DRW_PASS_CREATE(psl->taa_resolve, DRW_STATE_WRITE_COLOR);
DRWShadingGroup *grp = DRW_shgroup_create(sh, psl->taa_resolve);
DRW_shgroup_uniform_texture_ref(grp, "colorHistoryBuffer", &txl->taa_history);
@@ -287,7 +297,7 @@ void EEVEE_temporal_sampling_cache_init(EEVEE_ViewLayerData *sldata, EEVEE_Data
else {
DRW_shgroup_uniform_float(grp, "alpha", &effects->taa_alpha, 1);
}
- DRW_shgroup_call_add(grp, DRW_cache_fullscreen_quad_get(), NULL);
+ DRW_shgroup_call(grp, DRW_cache_fullscreen_quad_get(), NULL);
}
}
@@ -313,19 +323,15 @@ void EEVEE_temporal_sampling_draw(EEVEE_Data *vedata)
DRW_draw_pass(psl->taa_resolve);
/* Restore the depth from sample 1. */
- if (!DRW_state_is_image_render()) {
- GPU_framebuffer_blit(fbl->double_buffer_depth_fb, 0, fbl->main_fb, 0, GPU_DEPTH_BIT);
- }
+ GPU_framebuffer_blit(fbl->double_buffer_depth_fb, 0, fbl->main_fb, 0, GPU_DEPTH_BIT);
SWAP_BUFFERS_TAA();
}
else {
- if (!DRW_state_is_image_render()) {
- /* Save the depth buffer for the next frame.
- * This saves us from doing anything special
- * in the other mode engines. */
- GPU_framebuffer_blit(fbl->main_fb, 0, fbl->double_buffer_depth_fb, 0, GPU_DEPTH_BIT);
- }
+ /* Save the depth buffer for the next frame.
+ * This saves us from doing anything special
+ * in the other mode engines. */
+ GPU_framebuffer_blit(fbl->main_fb, 0, fbl->double_buffer_depth_fb, 0, GPU_DEPTH_BIT);
/* Do reprojection for noise reduction */
/* TODO : do AA jitter if in only render view. */
diff --git a/source/blender/draw/engines/eevee/eevee_volumes.c b/source/blender/draw/engines/eevee/eevee_volumes.c
index 76c8f010142..59f144b1faf 100644
--- a/source/blender/draw/engines/eevee/eevee_volumes.c
+++ b/source/blender/draw/engines/eevee/eevee_volumes.c
@@ -49,8 +49,8 @@ static struct {
char *volumetric_common_lights_lib;
struct GPUShader *volumetric_clear_sh;
- struct GPUShader *volumetric_scatter_sh;
- struct GPUShader *volumetric_scatter_with_lights_sh;
+ struct GPUShader *scatter_sh;
+ struct GPUShader *scatter_with_lights_sh;
struct GPUShader *volumetric_integration_sh;
struct GPUShader *volumetric_resolve_sh;
@@ -60,6 +60,9 @@ static struct {
GPUTexture *dummy_density;
GPUTexture *dummy_flame;
+ GPUTexture *dummy_scatter;
+ GPUTexture *dummy_transmit;
+
/* List of all smoke domains rendered within this frame. */
ListBase smoke_domains;
} e_data = {NULL}; /* Engine data */
@@ -100,22 +103,21 @@ static void eevee_create_shader_volumes(void)
e_data.volumetric_common_lib,
"#define VOLUMETRICS\n"
"#define CLEAR\n");
- e_data.volumetric_scatter_sh = DRW_shader_create_with_lib(datatoc_volumetric_vert_glsl,
- datatoc_volumetric_geom_glsl,
- datatoc_volumetric_scatter_frag_glsl,
- e_data.volumetric_common_lights_lib,
- SHADER_DEFINES
- "#define VOLUMETRICS\n"
- "#define VOLUME_SHADOW\n");
- e_data.volumetric_scatter_with_lights_sh = DRW_shader_create_with_lib(
- datatoc_volumetric_vert_glsl,
- datatoc_volumetric_geom_glsl,
- datatoc_volumetric_scatter_frag_glsl,
- e_data.volumetric_common_lights_lib,
- SHADER_DEFINES
- "#define VOLUMETRICS\n"
- "#define VOLUME_LIGHTING\n"
- "#define VOLUME_SHADOW\n");
+ e_data.scatter_sh = DRW_shader_create_with_lib(datatoc_volumetric_vert_glsl,
+ datatoc_volumetric_geom_glsl,
+ datatoc_volumetric_scatter_frag_glsl,
+ e_data.volumetric_common_lights_lib,
+ SHADER_DEFINES
+ "#define VOLUMETRICS\n"
+ "#define VOLUME_SHADOW\n");
+ e_data.scatter_with_lights_sh = DRW_shader_create_with_lib(datatoc_volumetric_vert_glsl,
+ datatoc_volumetric_geom_glsl,
+ datatoc_volumetric_scatter_frag_glsl,
+ e_data.volumetric_common_lights_lib,
+ SHADER_DEFINES
+ "#define VOLUMETRICS\n"
+ "#define VOLUME_LIGHTING\n"
+ "#define VOLUME_SHADOW\n");
e_data.volumetric_integration_sh = DRW_shader_create_with_lib(
datatoc_volumetric_vert_glsl,
datatoc_volumetric_geom_glsl,
@@ -150,7 +152,7 @@ void EEVEE_volumes_set_jitter(EEVEE_ViewLayerData *sldata, uint current_sample)
common_data->vol_jitter[2] = (float)ht_point[2];
}
-int EEVEE_volumes_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata)
+void EEVEE_volumes_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata)
{
EEVEE_StorageList *stl = vedata->stl;
EEVEE_FramebufferList *fbl = vedata->fbl;
@@ -165,309 +167,207 @@ int EEVEE_volumes_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata)
BLI_listbase_clear(&e_data.smoke_domains);
- if (scene_eval->eevee.flag & SCE_EEVEE_VOLUMETRIC_ENABLED) {
-
- /* Shaders */
- if (!e_data.volumetric_scatter_sh) {
- eevee_create_shader_volumes();
- }
-
- const int tile_size = scene_eval->eevee.volumetric_tile_size;
-
- /* Find Froxel Texture resolution. */
- int tex_size[3];
-
- tex_size[0] = (int)ceilf(fmaxf(1.0f, viewport_size[0] / (float)tile_size));
- tex_size[1] = (int)ceilf(fmaxf(1.0f, viewport_size[1] / (float)tile_size));
- tex_size[2] = max_ii(scene_eval->eevee.volumetric_samples, 1);
-
- common_data->vol_coord_scale[0] = viewport_size[0] / (float)(tile_size * tex_size[0]);
- common_data->vol_coord_scale[1] = viewport_size[1] / (float)(tile_size * tex_size[1]);
-
- /* TODO compute snap to maxZBuffer for clustered rendering */
-
- if ((common_data->vol_tex_size[0] != tex_size[0]) ||
- (common_data->vol_tex_size[1] != tex_size[1]) ||
- (common_data->vol_tex_size[2] != tex_size[2])) {
- DRW_TEXTURE_FREE_SAFE(txl->volume_prop_scattering);
- DRW_TEXTURE_FREE_SAFE(txl->volume_prop_extinction);
- DRW_TEXTURE_FREE_SAFE(txl->volume_prop_emission);
- DRW_TEXTURE_FREE_SAFE(txl->volume_prop_phase);
- DRW_TEXTURE_FREE_SAFE(txl->volume_scatter);
- DRW_TEXTURE_FREE_SAFE(txl->volume_transmittance);
- DRW_TEXTURE_FREE_SAFE(txl->volume_scatter_history);
- DRW_TEXTURE_FREE_SAFE(txl->volume_transmittance_history);
- GPU_FRAMEBUFFER_FREE_SAFE(fbl->volumetric_fb);
- GPU_FRAMEBUFFER_FREE_SAFE(fbl->volumetric_scat_fb);
- GPU_FRAMEBUFFER_FREE_SAFE(fbl->volumetric_integ_fb);
- common_data->vol_tex_size[0] = tex_size[0];
- common_data->vol_tex_size[1] = tex_size[1];
- common_data->vol_tex_size[2] = tex_size[2];
-
- common_data->vol_inv_tex_size[0] = 1.0f / (float)(tex_size[0]);
- common_data->vol_inv_tex_size[1] = 1.0f / (float)(tex_size[1]);
- common_data->vol_inv_tex_size[2] = 1.0f / (float)(tex_size[2]);
- }
-
- /* Like frostbite's paper, 5% blend of the new frame. */
- common_data->vol_history_alpha = (txl->volume_prop_scattering == NULL) ? 0.0f : 0.95f;
-
- if (txl->volume_prop_scattering == NULL) {
- /* Volume properties: We evaluate all volumetric objects
- * and store their final properties into each froxel */
- txl->volume_prop_scattering = DRW_texture_create_3d(
- tex_size[0], tex_size[1], tex_size[2], GPU_R11F_G11F_B10F, DRW_TEX_FILTER, NULL);
- txl->volume_prop_extinction = DRW_texture_create_3d(
- tex_size[0], tex_size[1], tex_size[2], GPU_R11F_G11F_B10F, DRW_TEX_FILTER, NULL);
- txl->volume_prop_emission = DRW_texture_create_3d(
- tex_size[0], tex_size[1], tex_size[2], GPU_R11F_G11F_B10F, DRW_TEX_FILTER, NULL);
- txl->volume_prop_phase = DRW_texture_create_3d(
- tex_size[0], tex_size[1], tex_size[2], GPU_RG16F, DRW_TEX_FILTER, NULL);
-
- /* Volume scattering: We compute for each froxel the
- * Scattered light towards the view. We also resolve temporal
- * super sampling during this stage. */
- txl->volume_scatter = DRW_texture_create_3d(
- tex_size[0], tex_size[1], tex_size[2], GPU_R11F_G11F_B10F, DRW_TEX_FILTER, NULL);
- txl->volume_transmittance = DRW_texture_create_3d(
- tex_size[0], tex_size[1], tex_size[2], GPU_R11F_G11F_B10F, DRW_TEX_FILTER, NULL);
+ const int tile_size = scene_eval->eevee.volumetric_tile_size;
+
+ /* Find Froxel Texture resolution. */
+ int tex_size[3];
+
+ tex_size[0] = (int)ceilf(fmaxf(1.0f, viewport_size[0] / (float)tile_size));
+ tex_size[1] = (int)ceilf(fmaxf(1.0f, viewport_size[1] / (float)tile_size));
+ tex_size[2] = max_ii(scene_eval->eevee.volumetric_samples, 1);
+
+ common_data->vol_coord_scale[0] = viewport_size[0] / (float)(tile_size * tex_size[0]);
+ common_data->vol_coord_scale[1] = viewport_size[1] / (float)(tile_size * tex_size[1]);
+
+ /* TODO compute snap to maxZBuffer for clustered rendering */
+ if ((common_data->vol_tex_size[0] != tex_size[0]) ||
+ (common_data->vol_tex_size[1] != tex_size[1]) ||
+ (common_data->vol_tex_size[2] != tex_size[2])) {
+ DRW_TEXTURE_FREE_SAFE(txl->volume_prop_scattering);
+ DRW_TEXTURE_FREE_SAFE(txl->volume_prop_extinction);
+ DRW_TEXTURE_FREE_SAFE(txl->volume_prop_emission);
+ DRW_TEXTURE_FREE_SAFE(txl->volume_prop_phase);
+ DRW_TEXTURE_FREE_SAFE(txl->volume_scatter);
+ DRW_TEXTURE_FREE_SAFE(txl->volume_transmit);
+ DRW_TEXTURE_FREE_SAFE(txl->volume_scatter_history);
+ DRW_TEXTURE_FREE_SAFE(txl->volume_transmit_history);
+ GPU_FRAMEBUFFER_FREE_SAFE(fbl->volumetric_fb);
+ GPU_FRAMEBUFFER_FREE_SAFE(fbl->volumetric_scat_fb);
+ GPU_FRAMEBUFFER_FREE_SAFE(fbl->volumetric_integ_fb);
+ copy_v3_v3_int(common_data->vol_tex_size, tex_size);
+
+ common_data->vol_inv_tex_size[0] = 1.0f / (float)(tex_size[0]);
+ common_data->vol_inv_tex_size[1] = 1.0f / (float)(tex_size[1]);
+ common_data->vol_inv_tex_size[2] = 1.0f / (float)(tex_size[2]);
+ }
- /* Final integration: We compute for each froxel the
- * amount of scattered light and extinction coef at this
- * given depth. We use theses textures as double buffer
- * for the volumetric history. */
- txl->volume_scatter_history = DRW_texture_create_3d(
- tex_size[0], tex_size[1], tex_size[2], GPU_R11F_G11F_B10F, DRW_TEX_FILTER, NULL);
- txl->volume_transmittance_history = DRW_texture_create_3d(
- tex_size[0], tex_size[1], tex_size[2], GPU_R11F_G11F_B10F, DRW_TEX_FILTER, NULL);
- }
+ /* Like frostbite's paper, 5% blend of the new frame. */
+ common_data->vol_history_alpha = (txl->volume_prop_scattering == NULL) ? 0.0f : 0.95f;
- /* Temporal Super sampling jitter */
- uint ht_primes[3] = {3, 7, 2};
- uint current_sample = 0;
+ /* Temporal Super sampling jitter */
+ uint ht_primes[3] = {3, 7, 2};
+ uint current_sample = 0;
- /* If TAA is in use do not use the history buffer. */
- bool do_taa = ((effects->enabled_effects & EFFECT_TAA) != 0);
+ /* If TAA is in use do not use the history buffer. */
+ bool do_taa = ((effects->enabled_effects & EFFECT_TAA) != 0);
- if (draw_ctx->evil_C != NULL) {
- struct wmWindowManager *wm = CTX_wm_manager(draw_ctx->evil_C);
- do_taa = do_taa && (ED_screen_animation_no_scrub(wm) == NULL);
- }
+ if (draw_ctx->evil_C != NULL) {
+ struct wmWindowManager *wm = CTX_wm_manager(draw_ctx->evil_C);
+ do_taa = do_taa && (ED_screen_animation_no_scrub(wm) == NULL);
+ }
- if (do_taa) {
- common_data->vol_history_alpha = 0.0f;
- current_sample = effects->taa_current_sample - 1;
- effects->volume_current_sample = -1;
- }
- else {
- 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;
- if (current_sample != max_sample - 1) {
- DRW_viewport_request_redraw();
- }
+ if (do_taa) {
+ common_data->vol_history_alpha = 0.0f;
+ current_sample = effects->taa_current_sample - 1;
+ effects->volume_current_sample = -1;
+ }
+ else {
+ 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;
+ if (current_sample != max_sample - 1) {
+ DRW_viewport_request_redraw();
}
+ }
- EEVEE_volumes_set_jitter(sldata, current_sample);
+ EEVEE_volumes_set_jitter(sldata, current_sample);
- /* Framebuffer setup */
- GPU_framebuffer_ensure_config(&fbl->volumetric_fb,
- {GPU_ATTACHMENT_NONE,
- GPU_ATTACHMENT_TEXTURE(txl->volume_prop_scattering),
- GPU_ATTACHMENT_TEXTURE(txl->volume_prop_extinction),
- GPU_ATTACHMENT_TEXTURE(txl->volume_prop_emission),
- GPU_ATTACHMENT_TEXTURE(txl->volume_prop_phase)});
- GPU_framebuffer_ensure_config(&fbl->volumetric_scat_fb,
- {GPU_ATTACHMENT_NONE,
- GPU_ATTACHMENT_TEXTURE(txl->volume_scatter),
- GPU_ATTACHMENT_TEXTURE(txl->volume_transmittance)});
- GPU_framebuffer_ensure_config(&fbl->volumetric_integ_fb,
- {GPU_ATTACHMENT_NONE,
- GPU_ATTACHMENT_TEXTURE(txl->volume_scatter_history),
- GPU_ATTACHMENT_TEXTURE(txl->volume_transmittance_history)});
-
- float integration_start = scene_eval->eevee.volumetric_start;
- float integration_end = scene_eval->eevee.volumetric_end;
- common_data->vol_light_clamp = scene_eval->eevee.volumetric_light_clamp;
- common_data->vol_shadow_steps = (float)scene_eval->eevee.volumetric_shadow_samples;
- if ((scene_eval->eevee.flag & SCE_EEVEE_VOLUMETRIC_SHADOWS) == 0) {
- common_data->vol_shadow_steps = 0;
- }
+ float integration_start = scene_eval->eevee.volumetric_start;
+ float integration_end = scene_eval->eevee.volumetric_end;
+ common_data->vol_light_clamp = scene_eval->eevee.volumetric_light_clamp;
+ common_data->vol_shadow_steps = (float)scene_eval->eevee.volumetric_shadow_samples;
+ if ((scene_eval->eevee.flag & SCE_EEVEE_VOLUMETRIC_SHADOWS) == 0) {
+ common_data->vol_shadow_steps = 0;
+ }
- /* 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);
- EEVEE_update_viewvecs(invproj, winmat, sldata->common_data.view_vecs);
-
- if (DRW_viewport_is_persp_get()) {
- float sample_distribution = scene_eval->eevee.volumetric_sample_distribution;
- sample_distribution = 4.0f * (1.00001f - sample_distribution);
-
- const float clip_start = common_data->view_vecs[0][2];
- /* Negate */
- float near = integration_start = min_ff(-integration_start, clip_start - 1e-4f);
- float far = integration_end = min_ff(-integration_end, near - 1e-4f);
-
- common_data->vol_depth_param[0] = (far - near * exp2(1.0f / sample_distribution)) /
- (far - near);
- common_data->vol_depth_param[1] = (1.0f - common_data->vol_depth_param[0]) / near;
- common_data->vol_depth_param[2] = sample_distribution;
- }
- else {
- const float clip_start = common_data->view_vecs[0][2];
- const float clip_end = clip_start + common_data->view_vecs[1][2];
- integration_start = min_ff(integration_end, clip_start);
- integration_end = max_ff(-integration_end, clip_end);
-
- common_data->vol_depth_param[0] = integration_start;
- common_data->vol_depth_param[1] = integration_end;
- common_data->vol_depth_param[2] = 1.0f / (integration_end - integration_start);
- }
+ /* Update view_vecs */
+ float invproj[4][4], winmat[4][4];
+ 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_view_is_persp_get(NULL)) {
+ float sample_distribution = scene_eval->eevee.volumetric_sample_distribution;
+ sample_distribution = 4.0f * (1.00001f - sample_distribution);
+
+ const float clip_start = common_data->view_vecs[0][2];
+ /* Negate */
+ float near = integration_start = min_ff(-integration_start, clip_start - 1e-4f);
+ float far = integration_end = min_ff(-integration_end, near - 1e-4f);
+
+ common_data->vol_depth_param[0] = (far - near * exp2(1.0f / sample_distribution)) /
+ (far - near);
+ common_data->vol_depth_param[1] = (1.0f - common_data->vol_depth_param[0]) / near;
+ common_data->vol_depth_param[2] = sample_distribution;
+ }
+ else {
+ const float clip_start = common_data->view_vecs[0][2];
+ const float clip_end = clip_start + common_data->view_vecs[1][2];
+ integration_start = min_ff(integration_end, clip_start);
+ integration_end = max_ff(-integration_end, clip_end);
+
+ common_data->vol_depth_param[0] = integration_start;
+ common_data->vol_depth_param[1] = integration_end;
+ common_data->vol_depth_param[2] = 1.0f / (integration_end - integration_start);
+ }
- /* Disable clamp if equal to 0. */
- if (common_data->vol_light_clamp == 0.0) {
- common_data->vol_light_clamp = FLT_MAX;
- }
+ /* Disable clamp if equal to 0. */
+ if (common_data->vol_light_clamp == 0.0) {
+ common_data->vol_light_clamp = FLT_MAX;
+ }
- common_data->vol_use_lights = (scene_eval->eevee.flag & SCE_EEVEE_VOLUMETRIC_LIGHTS) != 0;
+ common_data->vol_use_lights = (scene_eval->eevee.flag & SCE_EEVEE_VOLUMETRIC_LIGHTS) != 0;
- return EFFECT_VOLUMETRIC | EFFECT_POST_BUFFER;
+ if (!e_data.dummy_scatter) {
+ float scatter[4] = {0.0f, 0.0f, 0.0f, 0.0f};
+ float transmit[4] = {1.0f, 1.0f, 1.0f, 1.0f};
+ e_data.dummy_scatter = DRW_texture_create_3d(1, 1, 1, GPU_RGBA8, DRW_TEX_WRAP, scatter);
+ e_data.dummy_transmit = DRW_texture_create_3d(1, 1, 1, GPU_RGBA8, DRW_TEX_WRAP, transmit);
}
-
- /* Cleanup to release memory */
- DRW_TEXTURE_FREE_SAFE(txl->volume_prop_scattering);
- DRW_TEXTURE_FREE_SAFE(txl->volume_prop_extinction);
- DRW_TEXTURE_FREE_SAFE(txl->volume_prop_emission);
- DRW_TEXTURE_FREE_SAFE(txl->volume_prop_phase);
- DRW_TEXTURE_FREE_SAFE(txl->volume_scatter);
- DRW_TEXTURE_FREE_SAFE(txl->volume_transmittance);
- DRW_TEXTURE_FREE_SAFE(txl->volume_scatter_history);
- DRW_TEXTURE_FREE_SAFE(txl->volume_transmittance_history);
- GPU_FRAMEBUFFER_FREE_SAFE(fbl->volumetric_fb);
- GPU_FRAMEBUFFER_FREE_SAFE(fbl->volumetric_scat_fb);
- GPU_FRAMEBUFFER_FREE_SAFE(fbl->volumetric_integ_fb);
-
- return 0;
}
void EEVEE_volumes_cache_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata)
{
EEVEE_PassList *psl = vedata->psl;
EEVEE_StorageList *stl = vedata->stl;
- EEVEE_TextureList *txl = vedata->txl;
EEVEE_EffectsInfo *effects = stl->effects;
- LightCache *lcache = stl->g_data->light_cache;
EEVEE_CommonUniformBuffer *common_data = &sldata->common_data;
- if ((effects->enabled_effects & EFFECT_VOLUMETRIC) != 0) {
- const DRWContextState *draw_ctx = DRW_context_state_get();
- Scene *scene = draw_ctx->scene;
- DRWShadingGroup *grp = NULL;
-
- /* Quick breakdown of the Volumetric rendering:
- *
- * The rendering is separated in 4 stages:
- *
- * - Material Parameters : we collect volume properties of
- * all participating media in the scene and store them in
- * a 3D texture aligned with the 3D frustum.
- * This is done in 2 passes, one that clear the texture
- * and/or evaluate the world volumes, and the 2nd one that
- * additively render object volumes.
- *
- * - Light Scattering : the volume properties then are sampled
- * and light scattering is evaluated for each cell of the
- * volume texture. Temporal super-sampling (if enabled) occurs here.
- *
- * - Volume Integration : the scattered light and extinction is
- * integrated (accumulated) along the view-rays. The result is stored
- * for every cell in another texture.
- *
- * - Full-screen Resolve : From the previous stage, we get two
- * 3D textures that contains integrated scattered light and extinction
- * for "every" positions in the frustum. We only need to sample
- * them and blend the scene color with those factors. This also
- * work for alpha blended materials.
- */
-
- /* World pass is not additive as it also clear the buffer. */
- psl->volumetric_world_ps = DRW_pass_create("Volumetric World", DRW_STATE_WRITE_COLOR);
-
- /* World Volumetric */
- struct World *wo = scene->world;
- if (wo != NULL && wo->use_nodes && wo->nodetree &&
- !LOOK_DEV_STUDIO_LIGHT_ENABLED(draw_ctx->v3d)) {
- struct GPUMaterial *mat = EEVEE_material_world_volume_get(scene, wo);
-
- grp = DRW_shgroup_material_empty_tri_batch_create(
- mat, psl->volumetric_world_ps, common_data->vol_tex_size[2]);
-
- if (grp) {
- DRW_shgroup_uniform_block(grp, "common_block", sldata->common_ubo);
- /* TODO (fclem): remove those (need to clean the GLSL files). */
- DRW_shgroup_uniform_block(grp, "grid_block", sldata->grid_ubo);
- DRW_shgroup_uniform_block(grp, "probe_block", sldata->probe_ubo);
- DRW_shgroup_uniform_block(grp, "planar_block", sldata->planar_ubo);
- DRW_shgroup_uniform_block(grp, "light_block", sldata->light_ubo);
- DRW_shgroup_uniform_block(grp, "shadow_block", sldata->shadow_ubo);
-
- /* Fix principle volumetric not working with world materials. */
- DRW_shgroup_uniform_texture(grp, "sampdensity", e_data.dummy_density);
- DRW_shgroup_uniform_texture(grp, "sampflame", e_data.dummy_flame);
- DRW_shgroup_uniform_vec2(grp, "unftemperature", (float[2]){0.0f, 1.0f}, 1);
- }
- }
+ const DRWContextState *draw_ctx = DRW_context_state_get();
+ Scene *scene = draw_ctx->scene;
+ DRWShadingGroup *grp = NULL;
- if (grp == NULL) {
- /* If no world or volume material is present just clear the buffer with this drawcall */
- grp = DRW_shgroup_empty_tri_batch_create(
- e_data.volumetric_clear_sh, psl->volumetric_world_ps, common_data->vol_tex_size[2]);
+ /* Shaders */
+ if (!e_data.scatter_sh) {
+ eevee_create_shader_volumes();
+ }
- DRW_shgroup_uniform_block(grp, "common_block", sldata->common_ubo);
+ /* Quick breakdown of the Volumetric rendering:
+ *
+ * The rendering is separated in 4 stages:
+ *
+ * - Material Parameters : we collect volume properties of
+ * all participating media in the scene and store them in
+ * a 3D texture aligned with the 3D frustum.
+ * This is done in 2 passes, one that clear the texture
+ * and/or evaluate the world volumes, and the 2nd one that
+ * additively render object volumes.
+ *
+ * - Light Scattering : the volume properties then are sampled
+ * and light scattering is evaluated for each cell of the
+ * volume texture. Temporal super-sampling (if enabled) occurs here.
+ *
+ * - Volume Integration : the scattered light and extinction is
+ * integrated (accumulated) along the view-rays. The result is stored
+ * for every cell in another texture.
+ *
+ * - Full-screen Resolve : From the previous stage, we get two
+ * 3D textures that contains integrated scattered light and extinction
+ * for "every" positions in the frustum. We only need to sample
+ * them and blend the scene color with those factors. This also
+ * work for alpha blended materials.
+ */
+
+ /* World pass is not additive as it also clear the buffer. */
+ DRW_PASS_CREATE(psl->volumetric_world_ps, DRW_STATE_WRITE_COLOR);
+ DRW_PASS_CREATE(psl->volumetric_objects_ps, DRW_STATE_WRITE_COLOR | DRW_STATE_ADDITIVE);
+
+ /* World Volumetric */
+ struct World *wo = scene->world;
+ if (wo != NULL && wo->use_nodes && wo->nodetree &&
+ !LOOK_DEV_STUDIO_LIGHT_ENABLED(draw_ctx->v3d)) {
+ struct GPUMaterial *mat = EEVEE_material_world_volume_get(scene, wo);
+
+ if (GPU_material_use_domain_volume(mat)) {
+ grp = DRW_shgroup_material_create(mat, psl->volumetric_world_ps);
}
- /* Volumetric Objects */
- psl->volumetric_objects_ps = DRW_pass_create("Volumetric Properties",
- DRW_STATE_WRITE_COLOR | DRW_STATE_ADDITIVE);
+ if (grp) {
+ DRW_shgroup_uniform_block(grp, "common_block", sldata->common_ubo);
+ /* TODO (fclem): remove those (need to clean the GLSL files). */
+ DRW_shgroup_uniform_block(grp, "grid_block", sldata->grid_ubo);
+ DRW_shgroup_uniform_block(grp, "probe_block", sldata->probe_ubo);
+ DRW_shgroup_uniform_block(grp, "planar_block", sldata->planar_ubo);
+ DRW_shgroup_uniform_block(grp, "light_block", sldata->light_ubo);
+ DRW_shgroup_uniform_block(grp, "shadow_block", sldata->shadow_ubo);
- struct GPUShader *scatter_sh = (common_data->vol_use_lights) ?
- e_data.volumetric_scatter_with_lights_sh :
- e_data.volumetric_scatter_sh;
- psl->volumetric_scatter_ps = DRW_pass_create("Volumetric Scattering", DRW_STATE_WRITE_COLOR);
- grp = DRW_shgroup_empty_tri_batch_create(
- scatter_sh, psl->volumetric_scatter_ps, common_data->vol_tex_size[2]);
- DRW_shgroup_uniform_texture_ref(grp, "irradianceGrid", &lcache->grid_tx.tex);
- DRW_shgroup_uniform_texture_ref(grp, "shadowCubeTexture", &sldata->shadow_cube_pool);
- DRW_shgroup_uniform_texture_ref(grp, "shadowCascadeTexture", &sldata->shadow_cascade_pool);
- DRW_shgroup_uniform_texture_ref(grp, "volumeScattering", &txl->volume_prop_scattering);
- DRW_shgroup_uniform_texture_ref(grp, "volumeExtinction", &txl->volume_prop_extinction);
- DRW_shgroup_uniform_texture_ref(grp, "volumeEmission", &txl->volume_prop_emission);
- DRW_shgroup_uniform_texture_ref(grp, "volumePhase", &txl->volume_prop_phase);
- DRW_shgroup_uniform_texture_ref(grp, "historyScattering", &txl->volume_scatter_history);
- DRW_shgroup_uniform_texture_ref(
- grp, "historyTransmittance", &txl->volume_transmittance_history);
- DRW_shgroup_uniform_block(grp, "light_block", sldata->light_ubo);
- DRW_shgroup_uniform_block(grp, "shadow_block", sldata->shadow_ubo);
- DRW_shgroup_uniform_block(grp, "common_block", sldata->common_ubo);
+ /* Fix principle volumetric not working with world materials. */
+ DRW_shgroup_uniform_texture(grp, "sampdensity", e_data.dummy_density);
+ DRW_shgroup_uniform_texture(grp, "sampflame", e_data.dummy_flame);
+ DRW_shgroup_uniform_vec2_copy(grp, "unftemperature", (float[2]){0.0f, 1.0f});
- psl->volumetric_integration_ps = DRW_pass_create("Volumetric Integration",
- DRW_STATE_WRITE_COLOR);
- grp = DRW_shgroup_empty_tri_batch_create(e_data.volumetric_integration_sh,
- psl->volumetric_integration_ps,
- common_data->vol_tex_size[2]);
- DRW_shgroup_uniform_texture_ref(grp, "volumeScattering", &txl->volume_scatter);
- DRW_shgroup_uniform_texture_ref(grp, "volumeExtinction", &txl->volume_transmittance);
- DRW_shgroup_uniform_block(grp, "common_block", sldata->common_ubo);
+ DRW_shgroup_call_procedural_triangles(grp, common_data->vol_tex_size[2], NULL);
- psl->volumetric_resolve_ps = DRW_pass_create("Volumetric Resolve", DRW_STATE_WRITE_COLOR);
- grp = DRW_shgroup_create(e_data.volumetric_resolve_sh, psl->volumetric_resolve_ps);
- DRW_shgroup_uniform_texture_ref(grp, "inScattering", &txl->volume_scatter);
- DRW_shgroup_uniform_texture_ref(grp, "inTransmittance", &txl->volume_transmittance);
- DRW_shgroup_uniform_texture_ref(grp, "inSceneColor", &e_data.color_src);
- DRW_shgroup_uniform_texture_ref(grp, "inSceneDepth", &e_data.depth_src);
+ effects->enabled_effects |= (EFFECT_VOLUMETRIC | EFFECT_POST_BUFFER);
+ }
+ }
+
+ if (grp == NULL) {
+ /* If no world or volume material is present just clear the buffer with this drawcall */
+ grp = DRW_shgroup_create(e_data.volumetric_clear_sh, psl->volumetric_world_ps);
DRW_shgroup_uniform_block(grp, "common_block", sldata->common_ubo);
- DRW_shgroup_call_add(grp, DRW_cache_fullscreen_quad_get(), NULL);
+
+ DRW_shgroup_call_procedural_triangles(grp, common_data->vol_tex_size[2], NULL);
}
}
@@ -500,28 +400,10 @@ void EEVEE_volumes_cache_object_add(EEVEE_ViewLayerData *sldata,
return;
}
- DRWShadingGroup *grp = DRW_shgroup_material_empty_tri_batch_create(
- mat, vedata->psl->volumetric_objects_ps, sldata->common_data.vol_tex_size[2]);
-
- /* Making sure it's updated. */
- invert_m4_m4(ob->imat, ob->obmat);
+ DRWShadingGroup *grp = DRW_shgroup_material_create(mat, vedata->psl->volumetric_objects_ps);
BKE_mesh_texspace_get_reference((struct Mesh *)ob->data, NULL, &texcoloc, NULL, &texcosize);
- float(*imat)[4] = ob->imat;
-
- if ((ob->base_flag & BASE_FROM_DUPLI) != 0) {
- /* TODO Remove from here and use a dedicated buffer. */
- EEVEE_InstanceVolumeMatrix *ivm = (EEVEE_InstanceVolumeMatrix *)DRW_drawdata_ensure(
- &ob->id,
- (DrawEngineType *)EEVEE_volumes_cache_object_add,
- sizeof(EEVEE_InstanceVolumeMatrix),
- NULL,
- NULL);
- copy_m4_m4(ivm->volume_mat, ob->imat);
- imat = ivm->volume_mat;
- }
-
/* TODO(fclem) remove those "unnecessary" UBOs */
DRW_shgroup_uniform_block(grp, "planar_block", sldata->planar_ubo);
DRW_shgroup_uniform_block(grp, "probe_block", sldata->probe_ubo);
@@ -530,7 +412,6 @@ void EEVEE_volumes_cache_object_add(EEVEE_ViewLayerData *sldata,
DRW_shgroup_uniform_block(grp, "grid_block", sldata->grid_ubo);
DRW_shgroup_uniform_block(grp, "common_block", sldata->common_ubo);
- DRW_shgroup_uniform_mat4(grp, "volumeObjectMatrix", imat);
DRW_shgroup_uniform_vec3(grp, "volumeOrcoLoc", texcoloc, 1);
DRW_shgroup_uniform_vec3(grp, "volumeOrcoSize", texcosize, 1);
@@ -578,6 +459,139 @@ void EEVEE_volumes_cache_object_add(EEVEE_ViewLayerData *sldata,
DRW_shgroup_uniform_vec3(grp, "volumeColor", white, 1);
DRW_shgroup_uniform_vec2(grp, "unftemperature", (float[2]){0.0f, 1.0f}, 1);
}
+
+ /* TODO Reduce to number of slices intersecting. */
+ /* TODO Preemptive culling. */
+ DRW_shgroup_call_procedural_triangles(grp, sldata->common_data.vol_tex_size[2], ob->obmat);
+
+ vedata->stl->effects->enabled_effects |= (EFFECT_VOLUMETRIC | EFFECT_POST_BUFFER);
+}
+
+void EEVEE_volumes_cache_finish(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata)
+{
+ EEVEE_PassList *psl = vedata->psl;
+ EEVEE_TextureList *txl = vedata->txl;
+ EEVEE_EffectsInfo *effects = vedata->stl->effects;
+ LightCache *lcache = vedata->stl->g_data->light_cache;
+ EEVEE_CommonUniformBuffer *common_data = &sldata->common_data;
+
+ if ((effects->enabled_effects & EFFECT_VOLUMETRIC) != 0) {
+ DRWShadingGroup *grp;
+ struct GPUShader *sh;
+
+ DRW_PASS_CREATE(psl->volumetric_scatter_ps, DRW_STATE_WRITE_COLOR);
+ sh = (common_data->vol_use_lights) ? e_data.scatter_with_lights_sh : e_data.scatter_sh;
+ grp = DRW_shgroup_create(sh, psl->volumetric_scatter_ps);
+ DRW_shgroup_uniform_texture_ref(grp, "irradianceGrid", &lcache->grid_tx.tex);
+ DRW_shgroup_uniform_texture_ref(grp, "shadowCubeTexture", &sldata->shadow_cube_pool);
+ DRW_shgroup_uniform_texture_ref(grp, "shadowCascadeTexture", &sldata->shadow_cascade_pool);
+ DRW_shgroup_uniform_texture_ref(grp, "volumeScattering", &txl->volume_prop_scattering);
+ DRW_shgroup_uniform_texture_ref(grp, "volumeExtinction", &txl->volume_prop_extinction);
+ DRW_shgroup_uniform_texture_ref(grp, "volumeEmission", &txl->volume_prop_emission);
+ DRW_shgroup_uniform_texture_ref(grp, "volumePhase", &txl->volume_prop_phase);
+ DRW_shgroup_uniform_texture_ref(grp, "historyScattering", &txl->volume_scatter_history);
+ DRW_shgroup_uniform_texture_ref(grp, "historyTransmittance", &txl->volume_transmit_history);
+ DRW_shgroup_uniform_block(grp, "light_block", sldata->light_ubo);
+ DRW_shgroup_uniform_block(grp, "shadow_block", sldata->shadow_ubo);
+ DRW_shgroup_uniform_block(grp, "common_block", sldata->common_ubo);
+
+ DRW_shgroup_call_procedural_triangles(grp, common_data->vol_tex_size[2], NULL);
+
+ DRW_PASS_CREATE(psl->volumetric_integration_ps, DRW_STATE_WRITE_COLOR);
+ grp = DRW_shgroup_create(e_data.volumetric_integration_sh, psl->volumetric_integration_ps);
+ DRW_shgroup_uniform_texture_ref(grp, "volumeScattering", &txl->volume_scatter);
+ DRW_shgroup_uniform_texture_ref(grp, "volumeExtinction", &txl->volume_transmit);
+ DRW_shgroup_uniform_block(grp, "common_block", sldata->common_ubo);
+
+ DRW_shgroup_call_procedural_triangles(grp, common_data->vol_tex_size[2], NULL);
+
+ DRW_PASS_CREATE(psl->volumetric_resolve_ps, DRW_STATE_WRITE_COLOR);
+ grp = DRW_shgroup_create(e_data.volumetric_resolve_sh, psl->volumetric_resolve_ps);
+ DRW_shgroup_uniform_texture_ref(grp, "inScattering", &txl->volume_scatter);
+ DRW_shgroup_uniform_texture_ref(grp, "inTransmittance", &txl->volume_transmit);
+ DRW_shgroup_uniform_texture_ref(grp, "inSceneColor", &e_data.color_src);
+ DRW_shgroup_uniform_texture_ref(grp, "inSceneDepth", &e_data.depth_src);
+ DRW_shgroup_uniform_block(grp, "common_block", sldata->common_ubo);
+
+ DRW_shgroup_call_procedural_triangles(grp, 1, NULL);
+ }
+}
+
+void EEVEE_volumes_draw_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata)
+{
+ EEVEE_FramebufferList *fbl = vedata->fbl;
+ EEVEE_TextureList *txl = vedata->txl;
+ EEVEE_EffectsInfo *effects = vedata->stl->effects;
+ EEVEE_CommonUniformBuffer *common_data = &sldata->common_data;
+
+ if ((effects->enabled_effects & EFFECT_VOLUMETRIC) != 0) {
+ int *tex_size = common_data->vol_tex_size;
+
+ if (txl->volume_prop_scattering == NULL) {
+ /* Volume properties: We evaluate all volumetric objects
+ * and store their final properties into each froxel */
+ txl->volume_prop_scattering = DRW_texture_create_3d(
+ tex_size[0], tex_size[1], tex_size[2], GPU_R11F_G11F_B10F, DRW_TEX_FILTER, NULL);
+ txl->volume_prop_extinction = DRW_texture_create_3d(
+ tex_size[0], tex_size[1], tex_size[2], GPU_R11F_G11F_B10F, DRW_TEX_FILTER, NULL);
+ txl->volume_prop_emission = DRW_texture_create_3d(
+ tex_size[0], tex_size[1], tex_size[2], GPU_R11F_G11F_B10F, DRW_TEX_FILTER, NULL);
+ txl->volume_prop_phase = DRW_texture_create_3d(
+ tex_size[0], tex_size[1], tex_size[2], GPU_RG16F, DRW_TEX_FILTER, NULL);
+
+ /* Volume scattering: We compute for each froxel the
+ * Scattered light towards the view. We also resolve temporal
+ * super sampling during this stage. */
+ txl->volume_scatter = DRW_texture_create_3d(
+ tex_size[0], tex_size[1], tex_size[2], GPU_R11F_G11F_B10F, DRW_TEX_FILTER, NULL);
+ txl->volume_transmit = DRW_texture_create_3d(
+ tex_size[0], tex_size[1], tex_size[2], GPU_R11F_G11F_B10F, DRW_TEX_FILTER, NULL);
+
+ /* Final integration: We compute for each froxel the
+ * amount of scattered light and extinction coef at this
+ * given depth. We use theses textures as double buffer
+ * for the volumetric history. */
+ txl->volume_scatter_history = DRW_texture_create_3d(
+ tex_size[0], tex_size[1], tex_size[2], GPU_R11F_G11F_B10F, DRW_TEX_FILTER, NULL);
+ txl->volume_transmit_history = DRW_texture_create_3d(
+ tex_size[0], tex_size[1], tex_size[2], GPU_R11F_G11F_B10F, DRW_TEX_FILTER, NULL);
+ }
+
+ GPU_framebuffer_ensure_config(&fbl->volumetric_fb,
+ {GPU_ATTACHMENT_NONE,
+ GPU_ATTACHMENT_TEXTURE(txl->volume_prop_scattering),
+ GPU_ATTACHMENT_TEXTURE(txl->volume_prop_extinction),
+ GPU_ATTACHMENT_TEXTURE(txl->volume_prop_emission),
+ GPU_ATTACHMENT_TEXTURE(txl->volume_prop_phase)});
+ GPU_framebuffer_ensure_config(&fbl->volumetric_scat_fb,
+ {GPU_ATTACHMENT_NONE,
+ GPU_ATTACHMENT_TEXTURE(txl->volume_scatter),
+ GPU_ATTACHMENT_TEXTURE(txl->volume_transmit)});
+ GPU_framebuffer_ensure_config(&fbl->volumetric_integ_fb,
+ {GPU_ATTACHMENT_NONE,
+ GPU_ATTACHMENT_TEXTURE(txl->volume_scatter_history),
+ GPU_ATTACHMENT_TEXTURE(txl->volume_transmit_history)});
+
+ /* Usage happens after buffer have been swapped. */
+ effects->volume_scatter = txl->volume_scatter_history;
+ effects->volume_transmit = txl->volume_transmit_history;
+ }
+ else {
+ DRW_TEXTURE_FREE_SAFE(txl->volume_prop_scattering);
+ DRW_TEXTURE_FREE_SAFE(txl->volume_prop_extinction);
+ DRW_TEXTURE_FREE_SAFE(txl->volume_prop_emission);
+ DRW_TEXTURE_FREE_SAFE(txl->volume_prop_phase);
+ DRW_TEXTURE_FREE_SAFE(txl->volume_scatter);
+ DRW_TEXTURE_FREE_SAFE(txl->volume_transmit);
+ DRW_TEXTURE_FREE_SAFE(txl->volume_scatter_history);
+ DRW_TEXTURE_FREE_SAFE(txl->volume_transmit_history);
+ GPU_FRAMEBUFFER_FREE_SAFE(fbl->volumetric_fb);
+ GPU_FRAMEBUFFER_FREE_SAFE(fbl->volumetric_scat_fb);
+ GPU_FRAMEBUFFER_FREE_SAFE(fbl->volumetric_integ_fb);
+
+ effects->volume_scatter = e_data.dummy_scatter;
+ effects->volume_transmit = e_data.dummy_transmit;
+ }
}
void EEVEE_volumes_compute(EEVEE_ViewLayerData *UNUSED(sldata), EEVEE_Data *vedata)
@@ -590,23 +604,19 @@ void EEVEE_volumes_compute(EEVEE_ViewLayerData *UNUSED(sldata), EEVEE_Data *veda
if ((effects->enabled_effects & EFFECT_VOLUMETRIC) != 0) {
DRW_stats_group_start("Volumetrics");
- /* Step 1: Participating Media Properties */
GPU_framebuffer_bind(fbl->volumetric_fb);
DRW_draw_pass(psl->volumetric_world_ps);
DRW_draw_pass(psl->volumetric_objects_ps);
- /* Step 2: Scatter Light */
GPU_framebuffer_bind(fbl->volumetric_scat_fb);
DRW_draw_pass(psl->volumetric_scatter_ps);
- /* Step 3: Integration */
GPU_framebuffer_bind(fbl->volumetric_integ_fb);
DRW_draw_pass(psl->volumetric_integration_ps);
- /* Swap volume history buffers */
SWAP(struct GPUFrameBuffer *, fbl->volumetric_scat_fb, fbl->volumetric_integ_fb);
SWAP(GPUTexture *, txl->volume_scatter, txl->volume_scatter_history);
- SWAP(GPUTexture *, txl->volume_transmittance, txl->volume_transmittance_history);
+ SWAP(GPUTexture *, txl->volume_transmit, txl->volume_transmit_history);
/* Restore */
GPU_framebuffer_bind(fbl->main_fb);
@@ -660,12 +670,15 @@ void EEVEE_volumes_free(void)
MEM_SAFE_FREE(e_data.volumetric_common_lib);
MEM_SAFE_FREE(e_data.volumetric_common_lights_lib);
+ DRW_TEXTURE_FREE_SAFE(e_data.dummy_scatter);
+ DRW_TEXTURE_FREE_SAFE(e_data.dummy_transmit);
+
DRW_TEXTURE_FREE_SAFE(e_data.dummy_density);
DRW_TEXTURE_FREE_SAFE(e_data.dummy_flame);
DRW_SHADER_FREE_SAFE(e_data.volumetric_clear_sh);
- DRW_SHADER_FREE_SAFE(e_data.volumetric_scatter_sh);
- DRW_SHADER_FREE_SAFE(e_data.volumetric_scatter_with_lights_sh);
+ DRW_SHADER_FREE_SAFE(e_data.scatter_sh);
+ DRW_SHADER_FREE_SAFE(e_data.scatter_with_lights_sh);
DRW_SHADER_FREE_SAFE(e_data.volumetric_integration_sh);
DRW_SHADER_FREE_SAFE(e_data.volumetric_resolve_sh);
}
diff --git a/source/blender/draw/engines/eevee/shaders/bsdf_common_lib.glsl b/source/blender/draw/engines/eevee/shaders/bsdf_common_lib.glsl
index 3a5f20b952e..d7160aee340 100644
--- a/source/blender/draw/engines/eevee/shaders/bsdf_common_lib.glsl
+++ b/source/blender/draw/engines/eevee/shaders/bsdf_common_lib.glsl
@@ -15,7 +15,7 @@ uniform sampler2D maxzBuffer;
uniform sampler2D minzBuffer;
uniform sampler2DArray planarDepth;
-#define cameraForward normalize(ViewMatrixInverse[2].xyz)
+#define cameraForward ViewMatrixInverse[2].xyz
#define cameraPos ViewMatrixInverse[3].xyz
#define cameraVec \
((ProjectionMatrix[3][3] == 0.0) ? normalize(cameraPos - worldPosition) : cameraForward)
@@ -836,18 +836,22 @@ Closure closure_mix(Closure cl1, Closure cl2, float fac)
cl.radiance /= max(1e-8, cl.opacity);
# ifdef USE_SSS
- cl.sss_data.rgb = mix(cl1.sss_data.rgb, cl2.sss_data.rgb, fac);
- cl.sss_data.a = (cl1.sss_data.a > 0.0) ? cl1.sss_data.a : cl2.sss_data.a;
+ /* Apply Mix on input */
+ cl1.sss_data.rgb *= 1.0 - fac;
+ cl2.sss_data.rgb *= fac;
+
+ /* Select biggest radius. */
+ bool use_cl1 = (cl1.sss_data.a > cl2.sss_data.a);
+ cl.sss_data = (use_cl1) ? cl1.sss_data : cl2.sss_data;
# ifdef USE_SSS_ALBEDO
/* TODO Find a solution to this. Dither? */
- cl.sss_albedo = (cl1.sss_data.a > 0.0) ? cl1.sss_albedo : cl2.sss_albedo;
+ cl.sss_albedo = (use_cl1) ? cl1.sss_albedo : cl2.sss_albedo;
/* Add radiance that was supposed to be filtered but was rejected. */
- cl.radiance += (cl1.sss_data.a > 0.0) ? cl2.sss_data.rgb * cl2.sss_albedo :
- cl1.sss_data.rgb * cl1.sss_albedo;
+ cl.radiance += (use_cl1) ? cl2.sss_data.rgb * cl2.sss_albedo : cl1.sss_data.rgb * cl1.sss_albedo;
# else
/* Add radiance that was supposed to be filtered but was rejected. */
- cl.radiance += (cl1.sss_data.a > 0.0) ? cl2.sss_data.rgb : cl1.sss_data.rgb;
+ cl.radiance += (use_cl1) ? cl2.sss_data.rgb : cl1.sss_data.rgb;
# endif
# endif
@@ -894,7 +898,7 @@ layout(location = 4) out vec4 sssAlbedo;
Closure nodetree_exec(void); /* Prototype */
-# if defined(USE_ALPHA_BLEND_VOLUMETRICS)
+# if defined(USE_ALPHA_BLEND)
/* Prototype because this file is included before volumetric_lib.glsl */
vec4 volumetric_resolve(vec4 scene_color, vec2 frag_uvs, float frag_depth);
# endif
@@ -908,7 +912,7 @@ void main()
cl.opacity = 1.0;
# endif
-# if defined(USE_ALPHA_BLEND_VOLUMETRICS)
+# if defined(USE_ALPHA_BLEND)
/* XXX fragile, better use real viewport resolution */
vec2 uvs = gl_FragCoord.xy / vec2(2 * textureSize(maxzBuffer, 0).xy);
fragColor.rgb = volumetric_resolve(vec4(cl.radiance, cl.opacity), uvs, gl_FragCoord.z).rgb;
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/lightprobe_planar_downsample_vert.glsl b/source/blender/draw/engines/eevee/shaders/lightprobe_planar_downsample_vert.glsl
index 1c943bd51bc..588cd402bb3 100644
--- a/source/blender/draw/engines/eevee/shaders/lightprobe_planar_downsample_vert.glsl
+++ b/source/blender/draw/engines/eevee/shaders/lightprobe_planar_downsample_vert.glsl
@@ -1,11 +1,12 @@
-in vec2 pos;
-
out int instance;
out vec2 vPos;
void main()
{
- instance = gl_InstanceID;
- vPos = pos;
+ int v = gl_VertexID % 3;
+ vPos.x = -1.0 + float((v & 1) << 2);
+ vPos.y = -1.0 + float((v & 2) << 1);
+
+ instance = gl_VertexID / 3;
}
diff --git a/source/blender/draw/engines/eevee/shaders/lit_surface_frag.glsl b/source/blender/draw/engines/eevee/shaders/lit_surface_frag.glsl
index 37b0ebb33cf..fe3225b1086 100644
--- a/source/blender/draw/engines/eevee/shaders/lit_surface_frag.glsl
+++ b/source/blender/draw/engines/eevee/shaders/lit_surface_frag.glsl
@@ -13,13 +13,8 @@ uniform sampler2DArray utilTex;
in vec3 worldPosition;
in vec3 viewPosition;
-#ifdef USE_FLAT_NORMAL
-flat in vec3 worldNormal;
-flat in vec3 viewNormal;
-#else
in vec3 worldNormal;
in vec3 viewNormal;
-#endif
#ifdef HAIR_SHADER
in vec3 hairTangent; /* world space */
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 29ecbd694c9..cf20b3ff5b9 100644
--- a/source/blender/draw/engines/eevee/shaders/lit_surface_vert.glsl
+++ b/source/blender/draw/engines/eevee/shaders/lit_surface_vert.glsl
@@ -1,13 +1,4 @@
-uniform mat4 ModelViewProjectionMatrix;
-uniform mat4 ModelViewMatrix;
-uniform mat3 WorldNormalMatrix;
-#ifndef USE_ATTR
-uniform mat4 ModelMatrix;
-uniform mat3 NormalMatrix;
-uniform mat4 ModelMatrixInverse;
-#endif
-
#ifndef HAIR_SHADER
in vec3 pos;
in vec3 nor;
@@ -16,20 +7,8 @@ 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];
-};
-
-#ifdef USE_FLAT_NORMAL
-flat out vec3 worldNormal;
-flat out vec3 viewNormal;
-#else
out vec3 worldNormal;
out vec3 viewNormal;
-#endif
#ifdef HAIR_SHADER
out vec3 hairTangent;
@@ -61,23 +40,21 @@ void main()
hairTime,
hairThickness,
hairThickTime);
-
- gl_Position = ViewProjectionMatrix * vec4(pos, 1.0);
- viewPosition = (ViewMatrix * vec4(pos, 1.0)).xyz;
+ worldNormal = cross(hairTangent, binor);
worldPosition = pos;
- hairTangent = normalize(hairTangent);
- worldNormal = cross(binor, hairTangent);
- viewNormal = mat3(ViewMatrix) * worldNormal;
#else
- gl_Position = ModelViewProjectionMatrix * vec4(pos, 1.0);
- viewPosition = (ModelViewMatrix * vec4(pos, 1.0)).xyz;
- worldPosition = (ModelMatrix * vec4(pos, 1.0)).xyz;
- worldNormal = normalize(WorldNormalMatrix * nor);
- viewNormal = normalize(NormalMatrix * nor);
+ worldPosition = point_object_to_world(pos);
+ worldNormal = normalize(normal_object_to_world(nor));
#endif
+ /* No need to normalize since this is just a rotation. */
+ viewNormal = normal_world_to_view(worldNormal);
+
+ viewPosition = point_world_to_view(worldPosition);
+ gl_Position = point_world_to_ndc(worldPosition);
+
/* Used for planar reflections */
- gl_ClipDistance[0] = dot(vec4(worldPosition, 1.0), ClipPlanes[0]);
+ 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 9196253478a..2c7e0aca3fb 100644
--- a/source/blender/draw/engines/eevee/shaders/prepass_vert.glsl
+++ b/source/blender/draw/engines/eevee/shaders/prepass_vert.glsl
@@ -1,45 +1,38 @@
-uniform mat4 ModelViewProjectionMatrix;
-uniform mat4 ModelMatrix;
-uniform mat4 ModelMatrixInverse;
-
-#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
void main()
{
+#ifdef GPU_INTEL
+ /* Due to some shader compiler bug, we somewhat
+ * need to access gl_VertexID to make it work. even
+ * if it's actually dead code. */
+ gl_Position.x = float(gl_VertexID);
+#endif
+
#ifdef HAIR_SHADER
float time, thick_time, thickness;
- vec3 pos, tan, binor;
+ vec3 worldPosition, tan, binor;
hair_get_pos_tan_binor_time((ProjectionMatrix[3][3] == 0.0),
ModelMatrixInverse,
ViewMatrixInverse[3].xyz,
ViewMatrixInverse[2].xyz,
- pos,
+ worldPosition,
tan,
binor,
time,
thickness,
thick_time);
-
- gl_Position = ViewProjectionMatrix * vec4(pos, 1.0);
- vec4 worldPosition = vec4(pos, 1.0);
#else
- gl_Position = ModelViewProjectionMatrix * vec4(pos, 1.0);
- vec4 worldPosition = (ModelMatrix * vec4(pos, 1.0));
+ vec3 worldPosition = point_object_to_world(pos);
#endif
+ 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/eevee/shaders/shadow_vert.glsl b/source/blender/draw/engines/eevee/shaders/shadow_vert.glsl
index f9225cd100b..6b06aab34d2 100644
--- a/source/blender/draw/engines/eevee/shaders/shadow_vert.glsl
+++ b/source/blender/draw/engines/eevee/shaders/shadow_vert.glsl
@@ -1,14 +1,4 @@
-uniform mat4 ModelViewProjectionMatrix;
-#ifdef MESH_SHADER
-uniform mat4 ModelViewMatrix;
-uniform mat3 WorldNormalMatrix;
-# ifndef USE_ATTR
-uniform mat4 ModelMatrix;
-uniform mat3 NormalMatrix;
-# endif
-#endif
-
in vec3 pos;
in vec3 nor;
@@ -21,12 +11,22 @@ out vec3 viewNormal;
void main()
{
- gl_Position = ModelViewProjectionMatrix * vec4(pos, 1.0);
+#ifdef GPU_INTEL
+ /* Due to some shader compiler bug, we somewhat
+ * need to access gl_VertexID to make it work. even
+ * if it's actually dead code. */
+ gl_Position.x = float(gl_VertexID);
+#endif
+
+ vec3 world_pos = point_object_to_world(pos);
+ gl_Position = point_world_to_ndc(world_pos);
#ifdef MESH_SHADER
- viewPosition = (ModelViewMatrix * vec4(pos, 1.0)).xyz;
- worldPosition = (ModelMatrix * vec4(pos, 1.0)).xyz;
- viewNormal = normalize(NormalMatrix * nor);
- worldNormal = normalize(WorldNormalMatrix * nor);
+ worldPosition = world_pos;
+ viewPosition = point_world_to_view(worldPosition);
+
+ worldNormal = normalize(normal_object_to_world(nor));
+ /* No need to normalize since this is just a rotation. */
+ viewNormal = normal_world_to_view(worldNormal);
# ifdef USE_ATTR
pass_attr(pos);
# endif
diff --git a/source/blender/draw/engines/eevee/shaders/volumetric_frag.glsl b/source/blender/draw/engines/eevee/shaders/volumetric_frag.glsl
index 0164a04c64b..052fdbb43a2 100644
--- a/source/blender/draw/engines/eevee/shaders/volumetric_frag.glsl
+++ b/source/blender/draw/engines/eevee/shaders/volumetric_frag.glsl
@@ -5,7 +5,6 @@
#define NODETREE_EXEC
#ifdef MESH_SHADER
-uniform mat4 volumeObjectMatrix;
uniform vec3 volumeOrcoLoc;
uniform vec3 volumeOrcoSize;
#endif
@@ -33,9 +32,9 @@ void main()
vec3 ndc_cell = volume_to_ndc((vec3(volume_cell) + volJitter.xyz) * volInvTexSize.xyz);
viewPosition = get_view_space_from_depth(ndc_cell.xy, ndc_cell.z);
- worldPosition = transform_point(ViewMatrixInverse, viewPosition);
+ worldPosition = point_view_to_world(viewPosition);
#ifdef MESH_SHADER
- volumeObjectLocalCoord = transform_point(volumeObjectMatrix, worldPosition);
+ volumeObjectLocalCoord = point_world_to_object(worldPosition);
volumeObjectLocalCoord = (volumeObjectLocalCoord - volumeOrcoLoc + volumeOrcoSize) /
(volumeOrcoSize * 2.0);
diff --git a/source/blender/draw/engines/external/external_engine.c b/source/blender/draw/engines/external/external_engine.c
index ed8c609c01f..7e03ce525d7 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);
}
}
}
@@ -191,7 +188,7 @@ static void external_cache_populate(void *vedata, Object *ob)
struct GPUBatch *geom = DRW_cache_object_surface_get(ob);
if (geom) {
/* Depth Prepass */
- DRW_shgroup_call_add(stl->g_data->depth_shgrp, geom, ob->obmat);
+ DRW_shgroup_call(stl->g_data->depth_shgrp, geom, ob->obmat);
}
}
}
@@ -221,7 +218,7 @@ static void external_draw_scene_do(void *vedata)
RenderEngine *engine = RE_engine_create_ex(engine_type, true);
engine->tile_x = scene->r.tilex;
engine->tile_y = scene->r.tiley;
- engine_type->view_update(engine, draw_ctx->evil_C);
+ engine_type->view_update(engine, draw_ctx->evil_C, draw_ctx->depsgraph);
rv3d->render_engine = engine;
}
@@ -231,7 +228,7 @@ static void external_draw_scene_do(void *vedata)
/* Render result draw. */
type = rv3d->render_engine->type;
- type->view_draw(rv3d->render_engine, draw_ctx->evil_C);
+ type->view_draw(rv3d->render_engine, draw_ctx->evil_C, draw_ctx->depsgraph);
GPU_matrix_pop_projection();
@@ -270,8 +267,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_draw_cache_impl.c b/source/blender/draw/engines/gpencil/gpencil_draw_cache_impl.c
index 7dabbcf4c41..7b2c0ed168e 100644
--- a/source/blender/draw/engines/gpencil/gpencil_draw_cache_impl.c
+++ b/source/blender/draw/engines/gpencil/gpencil_draw_cache_impl.c
@@ -133,7 +133,8 @@ static void gpencil_vbo_ensure_size(GpencilBatchCacheElem *be, int totvertex)
void DRW_gpencil_get_point_geom(GpencilBatchCacheElem *be,
bGPDstroke *gps,
short thickness,
- const float ink[4])
+ const float ink[4],
+ const int alignment_mode)
{
int totvertex = gps->totpoints;
if (be->vbo == NULL) {
@@ -177,26 +178,34 @@ void DRW_gpencil_get_point_geom(GpencilBatchCacheElem *be,
/* use previous point to determine stroke direction */
bGPDspoint *pt2 = NULL;
float fpt[3];
- if (i == 0) {
- if (gps->totpoints > 1) {
- /* extrapolate a point before first point */
- pt2 = &gps->points[1];
- interp_v3_v3v3(fpt, &pt2->x, &pt->x, 1.5f);
- GPU_vertbuf_attr_set(be->vbo, be->prev_pos_id, be->vbo_len, fpt);
+ if (alignment_mode != GP_STYLE_FOLLOW_PATH) {
+ /* add small offset to get a vector */
+ copy_v3_v3(fpt, &pt->x);
+ fpt[0] += 0.00001f;
+ fpt[1] += 0.00001f;
+ GPU_vertbuf_attr_set(be->vbo, be->prev_pos_id, be->vbo_len, fpt);
+ }
+ else {
+ if (i == 0) {
+ if (gps->totpoints > 1) {
+ /* extrapolate a point before first point */
+ pt2 = &gps->points[1];
+ interp_v3_v3v3(fpt, &pt2->x, &pt->x, 1.5f);
+ GPU_vertbuf_attr_set(be->vbo, be->prev_pos_id, be->vbo_len, fpt);
+ }
+ else {
+ /* add small offset to get a vector */
+ copy_v3_v3(fpt, &pt->x);
+ fpt[0] += 0.00001f;
+ fpt[1] += 0.00001f;
+ GPU_vertbuf_attr_set(be->vbo, be->prev_pos_id, be->vbo_len, fpt);
+ }
}
else {
- /* add small offset to get a vector */
- copy_v3_v3(fpt, &pt->x);
- fpt[0] += 0.00001f;
- fpt[1] += 0.00001f;
- GPU_vertbuf_attr_set(be->vbo, be->prev_pos_id, be->vbo_len, fpt);
+ pt2 = &gps->points[i - 1];
+ GPU_vertbuf_attr_set(be->vbo, be->prev_pos_id, be->vbo_len, &pt2->x);
}
}
- else {
- pt2 = &gps->points[i - 1];
- GPU_vertbuf_attr_set(be->vbo, be->prev_pos_id, be->vbo_len, &pt2->x);
- }
-
be->vbo_len++;
}
}
diff --git a/source/blender/draw/engines/gpencil/gpencil_draw_utils.c b/source/blender/draw/engines/gpencil/gpencil_draw_utils.c
index 4b6c913785d..7f979c4fed1 100644
--- a/source/blender/draw/engines/gpencil/gpencil_draw_utils.c
+++ b/source/blender/draw/engines/gpencil/gpencil_draw_utils.c
@@ -465,7 +465,7 @@ static DRWShadingGroup *DRW_gpencil_shgroup_fill_create(GPENCIL_e_data *e_data,
BKE_image_release_ibuf(image, ibuf, NULL);
}
else {
- GPUTexture *texture = GPU_texture_from_blender(gp_style->ima, &iuser, GL_TEXTURE_2D, true);
+ GPUTexture *texture = GPU_texture_from_blender(gp_style->ima, &iuser, GL_TEXTURE_2D);
DRW_shgroup_uniform_texture(grp, "myTexture", texture);
stl->shgroups[id].texture_clamp = gp_style->flag & GP_STYLE_COLOR_TEX_CLAMP ? 1 : 0;
@@ -631,7 +631,7 @@ DRWShadingGroup *DRW_gpencil_shgroup_stroke_create(GPENCIL_e_data *e_data,
BKE_image_release_ibuf(image, ibuf, NULL);
}
else {
- GPUTexture *texture = GPU_texture_from_blender(gp_style->sima, &iuser, GL_TEXTURE_2D, true);
+ GPUTexture *texture = GPU_texture_from_blender(gp_style->sima, &iuser, GL_TEXTURE_2D);
DRW_shgroup_uniform_texture(grp, "myTexture", texture);
BKE_image_release_ibuf(image, ibuf, NULL);
@@ -725,8 +725,8 @@ static DRWShadingGroup *DRW_gpencil_shgroup_point_create(GPENCIL_e_data *e_data,
DRW_shgroup_uniform_float(grp, "mix_stroke_factor", &stl->shgroups[id].mix_stroke_factor, 1);
/* lock rotation of dots and boxes */
- stl->shgroups[id].use_follow_path = (gp_style->flag & GP_STYLE_COLOR_LOCK_DOTS) ? 0 : 1;
- DRW_shgroup_uniform_int(grp, "use_follow_path", &stl->shgroups[id].use_follow_path, 1);
+ stl->shgroups[id].alignment_mode = gp_style->alignment_mode;
+ DRW_shgroup_uniform_int(grp, "alignment_mode", &stl->shgroups[id].alignment_mode, 1);
}
else {
stl->storage->obj_scale = 1.0f;
@@ -758,7 +758,7 @@ static DRWShadingGroup *DRW_gpencil_shgroup_point_create(GPENCIL_e_data *e_data,
DRW_shgroup_uniform_float(grp, "mix_stroke_factor", &stl->storage->mix_stroke_factor, 1);
/* lock rotation of dots and boxes */
- DRW_shgroup_uniform_int(grp, "use_follow_path", &stl->storage->use_follow_path, 1);
+ DRW_shgroup_uniform_int(grp, "alignment_mode", &stl->storage->alignment_mode, 1);
}
DRW_shgroup_uniform_vec4(grp, "colormix", gp_style->stroke_rgba, 1);
@@ -787,7 +787,7 @@ static DRWShadingGroup *DRW_gpencil_shgroup_point_create(GPENCIL_e_data *e_data,
BKE_image_release_ibuf(image, ibuf, NULL);
}
else {
- GPUTexture *texture = GPU_texture_from_blender(gp_style->sima, &iuser, GL_TEXTURE_2D, true);
+ GPUTexture *texture = GPU_texture_from_blender(gp_style->sima, &iuser, GL_TEXTURE_2D);
DRW_shgroup_uniform_texture(grp, "myTexture", texture);
BKE_image_release_ibuf(image, ibuf, NULL);
@@ -870,6 +870,7 @@ static void gpencil_add_stroke_vertexdata(GpencilBatchCache *cache,
float ink[4];
short sthickness;
MaterialGPencilStyle *gp_style = BKE_material_gpencil_settings_get(ob, gps->mat_nr + 1);
+ const int alignment_mode = (gp_style) ? gp_style->alignment_mode : GP_STYLE_FOLLOW_PATH;
/* set color using base color, tint color and opacity */
if (cache->is_dirty) {
@@ -919,7 +920,7 @@ static void gpencil_add_stroke_vertexdata(GpencilBatchCache *cache,
else {
/* create vertex data */
const int old_len = cache->b_point.vbo_len;
- DRW_gpencil_get_point_geom(&cache->b_point, gps, sthickness, ink);
+ DRW_gpencil_get_point_geom(&cache->b_point, gps, sthickness, ink, alignment_mode);
/* add to list of groups */
if (old_len < cache->b_point.vbo_len) {
@@ -1228,6 +1229,7 @@ static void gpencil_draw_onionskins(GpencilBatchCache *cache,
int last = gpf->framenum;
colflag = (bool)gpd->onion_flag & GP_ONION_GHOST_PREVCOL;
+ const short onion_keytype = gpd->onion_keytype;
/* -------------------------------
* 1) Draw Previous Frames First
@@ -1248,6 +1250,10 @@ static void gpencil_draw_onionskins(GpencilBatchCache *cache,
if ((mode == GP_ONION_MODE_SELECTED) && ((gf->flag & GP_FRAME_SELECT) == 0)) {
continue;
}
+ /* verify keyframe type */
+ if ((onion_keytype > -1) && (gf->key_type != onion_keytype)) {
+ continue;
+ }
/* absolute range */
if (mode == GP_ONION_MODE_ABSOLUTE) {
if ((gpf->framenum - gf->framenum) > step) {
@@ -1304,6 +1310,10 @@ static void gpencil_draw_onionskins(GpencilBatchCache *cache,
if ((mode == GP_ONION_MODE_SELECTED) && ((gf->flag & GP_FRAME_SELECT) == 0)) {
continue;
}
+ /* verify keyframe type */
+ if ((onion_keytype > -1) && (gf->key_type != onion_keytype)) {
+ continue;
+ }
/* absolute range */
if (mode == GP_ONION_MODE_ABSOLUTE) {
if ((gf->framenum - gpf->framenum) > step) {
@@ -1490,7 +1500,7 @@ void DRW_gpencil_populate_buffer_strokes(GPENCIL_e_data *e_data,
/* save gradient info */
stl->storage->gradient_f = brush->gpencil_settings->gradient_f;
copy_v2_v2(stl->storage->gradient_s, brush->gpencil_settings->gradient_s);
- stl->storage->use_follow_path = (gp_style->flag & GP_STYLE_COLOR_LOCK_DOTS) ? 0 : 1;
+ stl->storage->alignment_mode = (gp_style) ? gp_style->alignment_mode : GP_STYLE_FOLLOW_PATH;
/* if only one point, don't need to draw buffer because the user has no time to see it */
if (gpd->runtime.sbuffer_size > 1) {
@@ -1543,9 +1553,9 @@ void DRW_gpencil_populate_buffer_strokes(GPENCIL_e_data *e_data,
}
/* buffer strokes, must show stroke always */
- DRW_shgroup_call_add(stl->g_data->shgrps_drawing_stroke,
- e_data->batch_buffer_stroke,
- stl->storage->unit_matrix);
+ DRW_shgroup_call(stl->g_data->shgrps_drawing_stroke,
+ e_data->batch_buffer_stroke,
+ stl->storage->unit_matrix);
if ((gpd->runtime.sbuffer_size >= 3) &&
(gpd->runtime.sfill[3] > GPENCIL_ALPHA_OPACITY_THRESH) &&
@@ -1567,9 +1577,9 @@ void DRW_gpencil_populate_buffer_strokes(GPENCIL_e_data *e_data,
}
e_data->batch_buffer_fill = DRW_gpencil_get_buffer_fill_geom(gpd);
- DRW_shgroup_call_add(stl->g_data->shgrps_drawing_fill,
- e_data->batch_buffer_fill,
- stl->storage->unit_matrix);
+ DRW_shgroup_call(stl->g_data->shgrps_drawing_fill,
+ e_data->batch_buffer_fill,
+ stl->storage->unit_matrix);
stl->storage->buffer_fill = true;
}
stl->storage->buffer_stroke = true;
@@ -1599,7 +1609,7 @@ void DRW_gpencil_populate_buffer_strokes(GPENCIL_e_data *e_data,
e_data->batch_buffer_ctrlpoint = DRW_gpencil_get_buffer_ctrlpoint_geom(gpd);
- DRW_shgroup_call_add(shgrp, e_data->batch_buffer_ctrlpoint, stl->storage->unit_matrix);
+ DRW_shgroup_call(shgrp, e_data->batch_buffer_ctrlpoint, stl->storage->unit_matrix);
stl->storage->buffer_ctrlpoint = true;
}
@@ -1721,12 +1731,12 @@ static void DRW_gpencil_shgroups_create(GPENCIL_e_data *e_data,
scale,
cache_ob->shading_type);
if ((do_onion) || (elm->onion == false)) {
- DRW_shgroup_call_range_add(shgrp,
- cache->b_stroke.batch,
- (!cache_ob->is_dup_ob) ? gpf->runtime.viewmatrix :
- cache_ob->obmat,
- start_stroke,
- len);
+ DRW_shgroup_call_range(shgrp,
+ cache->b_stroke.batch,
+ (!cache_ob->is_dup_ob) ? gpf->runtime.viewmatrix :
+ cache_ob->obmat,
+ start_stroke,
+ len);
}
stl->storage->shgroup_id++;
start_stroke = elm->vertex_idx;
@@ -1750,12 +1760,12 @@ static void DRW_gpencil_shgroups_create(GPENCIL_e_data *e_data,
cache_ob->shading_type);
if ((do_onion) || (elm->onion == false)) {
- DRW_shgroup_call_range_add(shgrp,
- cache->b_point.batch,
- (!cache_ob->is_dup_ob) ? gpf->runtime.viewmatrix :
- cache_ob->obmat,
- start_point,
- len);
+ DRW_shgroup_call_range(shgrp,
+ cache->b_point.batch,
+ (!cache_ob->is_dup_ob) ? gpf->runtime.viewmatrix :
+ cache_ob->obmat,
+ start_point,
+ len);
}
stl->storage->shgroup_id++;
start_point = elm->vertex_idx;
@@ -1776,12 +1786,12 @@ static void DRW_gpencil_shgroups_create(GPENCIL_e_data *e_data,
cache_ob->shading_type);
if ((do_onion) || (elm->onion == false)) {
- DRW_shgroup_call_range_add(shgrp,
- cache->b_fill.batch,
- (!cache_ob->is_dup_ob) ? gpf->runtime.viewmatrix :
- cache_ob->obmat,
- start_fill,
- len);
+ DRW_shgroup_call_range(shgrp,
+ cache->b_fill.batch,
+ (!cache_ob->is_dup_ob) ? gpf->runtime.viewmatrix :
+ cache_ob->obmat,
+ start_fill,
+ len);
}
stl->storage->shgroup_id++;
start_fill = elm->vertex_idx;
@@ -1791,12 +1801,12 @@ static void DRW_gpencil_shgroups_create(GPENCIL_e_data *e_data,
if (stl->g_data->shgrps_edit_point) {
const int len = elm->vertex_idx - start_edit;
/* use always the same group */
- DRW_shgroup_call_range_add(stl->g_data->shgrps_edit_point,
- cache->b_edit.batch,
- (!cache_ob->is_dup_ob) ? gpf->runtime.viewmatrix :
- cache_ob->obmat,
- start_edit,
- len);
+ DRW_shgroup_call_range(stl->g_data->shgrps_edit_point,
+ cache->b_edit.batch,
+ (!cache_ob->is_dup_ob) ? gpf->runtime.viewmatrix :
+ cache_ob->obmat,
+ start_edit,
+ len);
start_edit = elm->vertex_idx;
}
@@ -1806,12 +1816,12 @@ static void DRW_gpencil_shgroups_create(GPENCIL_e_data *e_data,
if (stl->g_data->shgrps_edit_line) {
const int len = elm->vertex_idx - start_edlin;
/* use always the same group */
- DRW_shgroup_call_range_add(stl->g_data->shgrps_edit_line,
- cache->b_edlin.batch,
- (!cache_ob->is_dup_ob) ? gpf->runtime.viewmatrix :
- cache_ob->obmat,
- start_edlin,
- len);
+ DRW_shgroup_call_range(stl->g_data->shgrps_edit_line,
+ cache->b_edlin.batch,
+ (!cache_ob->is_dup_ob) ? gpf->runtime.viewmatrix :
+ cache_ob->obmat,
+ start_edlin,
+ len);
start_edlin = elm->vertex_idx;
}
diff --git a/source/blender/draw/engines/gpencil/gpencil_engine.c b/source/blender/draw/engines/gpencil/gpencil_engine.c
index ea578187765..280702020df 100644
--- a/source/blender/draw/engines/gpencil/gpencil_engine.c
+++ b/source/blender/draw/engines/gpencil/gpencil_engine.c
@@ -61,6 +61,8 @@ extern char datatoc_gpencil_edit_point_geom_glsl[];
extern char datatoc_gpencil_edit_point_frag_glsl[];
extern char datatoc_gpencil_blend_frag_glsl[];
+extern char datatoc_common_view_lib_glsl[];
+
/* *********** STATIC *********** */
static GPENCIL_e_data e_data = {NULL}; /* Engine data */
@@ -167,31 +169,37 @@ static void GPENCIL_create_shaders(void)
{
/* normal fill shader */
if (!e_data.gpencil_fill_sh) {
- e_data.gpencil_fill_sh = DRW_shader_create(
- datatoc_gpencil_fill_vert_glsl, NULL, datatoc_gpencil_fill_frag_glsl, NULL);
+ e_data.gpencil_fill_sh = DRW_shader_create_with_lib(datatoc_gpencil_fill_vert_glsl,
+ NULL,
+ datatoc_gpencil_fill_frag_glsl,
+ datatoc_common_view_lib_glsl,
+ NULL);
}
/* normal stroke shader using geometry to display lines (line mode) */
if (!e_data.gpencil_stroke_sh) {
- e_data.gpencil_stroke_sh = DRW_shader_create(datatoc_gpencil_stroke_vert_glsl,
- datatoc_gpencil_stroke_geom_glsl,
- datatoc_gpencil_stroke_frag_glsl,
- NULL);
+ e_data.gpencil_stroke_sh = DRW_shader_create_with_lib(datatoc_gpencil_stroke_vert_glsl,
+ datatoc_gpencil_stroke_geom_glsl,
+ datatoc_gpencil_stroke_frag_glsl,
+ datatoc_common_view_lib_glsl,
+ NULL);
}
/* dot/rectangle mode for normal strokes using geometry */
if (!e_data.gpencil_point_sh) {
- e_data.gpencil_point_sh = DRW_shader_create(datatoc_gpencil_point_vert_glsl,
- datatoc_gpencil_point_geom_glsl,
- datatoc_gpencil_point_frag_glsl,
- NULL);
+ e_data.gpencil_point_sh = DRW_shader_create_with_lib(datatoc_gpencil_point_vert_glsl,
+ datatoc_gpencil_point_geom_glsl,
+ datatoc_gpencil_point_frag_glsl,
+ datatoc_common_view_lib_glsl,
+ NULL);
}
/* used for edit points or strokes with one point only */
if (!e_data.gpencil_edit_point_sh) {
- e_data.gpencil_edit_point_sh = DRW_shader_create(datatoc_gpencil_edit_point_vert_glsl,
- datatoc_gpencil_edit_point_geom_glsl,
- datatoc_gpencil_edit_point_frag_glsl,
- NULL);
+ e_data.gpencil_edit_point_sh = DRW_shader_create_with_lib(datatoc_gpencil_edit_point_vert_glsl,
+ datatoc_gpencil_edit_point_geom_glsl,
+ datatoc_gpencil_edit_point_frag_glsl,
+ datatoc_common_view_lib_glsl,
+ NULL);
}
/* used for edit lines for edit modes */
@@ -454,7 +462,7 @@ void GPENCIL_cache_init(void *vedata)
DRW_STATE_WRITE_COLOR | DRW_STATE_BLEND |
DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_LESS);
DRWShadingGroup *mix_shgrp = DRW_shgroup_create(e_data.gpencil_fullscreen_sh, psl->mix_pass);
- DRW_shgroup_call_add(mix_shgrp, quad, NULL);
+ DRW_shgroup_call(mix_shgrp, quad, NULL);
DRW_shgroup_uniform_texture_ref(mix_shgrp, "strokeColor", &e_data.input_color_tx);
DRW_shgroup_uniform_texture_ref(mix_shgrp, "strokeDepth", &e_data.input_depth_tx);
DRW_shgroup_uniform_int(mix_shgrp, "tonemapping", &stl->storage->tonemapping, 1);
@@ -472,7 +480,7 @@ void GPENCIL_cache_init(void *vedata)
DRW_STATE_DEPTH_LESS);
DRWShadingGroup *mix_shgrp_noblend = DRW_shgroup_create(e_data.gpencil_fullscreen_sh,
psl->mix_pass_noblend);
- DRW_shgroup_call_add(mix_shgrp_noblend, quad, NULL);
+ DRW_shgroup_call(mix_shgrp_noblend, quad, NULL);
DRW_shgroup_uniform_texture_ref(mix_shgrp_noblend, "strokeColor", &e_data.input_color_tx);
DRW_shgroup_uniform_texture_ref(mix_shgrp_noblend, "strokeDepth", &e_data.input_depth_tx);
DRW_shgroup_uniform_int(mix_shgrp_noblend, "tonemapping", &stl->storage->tonemapping, 1);
@@ -490,7 +498,7 @@ void GPENCIL_cache_init(void *vedata)
DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_LESS);
DRWShadingGroup *background_shgrp = DRW_shgroup_create(e_data.gpencil_background_sh,
psl->background_pass);
- DRW_shgroup_call_add(background_shgrp, quad, NULL);
+ DRW_shgroup_call(background_shgrp, quad, NULL);
DRW_shgroup_uniform_texture_ref(background_shgrp, "strokeColor", &e_data.background_color_tx);
DRW_shgroup_uniform_texture_ref(background_shgrp, "strokeDepth", &e_data.background_depth_tx);
@@ -503,7 +511,7 @@ void GPENCIL_cache_init(void *vedata)
psl->paper_pass = DRW_pass_create("GPencil Paper Pass",
DRW_STATE_WRITE_COLOR | DRW_STATE_BLEND);
DRWShadingGroup *paper_shgrp = DRW_shgroup_create(e_data.gpencil_paper_sh, psl->paper_pass);
- DRW_shgroup_call_add(paper_shgrp, quad, NULL);
+ DRW_shgroup_call(paper_shgrp, quad, NULL);
DRW_shgroup_uniform_vec3(paper_shgrp, "color", v3d->shading.background_color, 1);
DRW_shgroup_uniform_float(paper_shgrp, "opacity", &v3d->overlay.gpencil_paper_opacity, 1);
}
@@ -522,7 +530,7 @@ void GPENCIL_cache_init(void *vedata)
DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_LESS);
DRWShadingGroup *blend_shgrp = DRW_shgroup_create(e_data.gpencil_blend_fullscreen_sh,
psl->blend_pass);
- DRW_shgroup_call_add(blend_shgrp, quad, NULL);
+ DRW_shgroup_call(blend_shgrp, quad, NULL);
DRW_shgroup_uniform_texture_ref(blend_shgrp, "strokeColor", &e_data.temp_color_tx_a);
DRW_shgroup_uniform_texture_ref(blend_shgrp, "strokeDepth", &e_data.temp_depth_tx_a);
DRW_shgroup_uniform_texture_ref(blend_shgrp, "blendColor", &e_data.temp_color_tx_fx);
@@ -674,7 +682,7 @@ void GPENCIL_cache_populate(void *vedata, Object *ob)
copy_v3_v3(stl->storage->grid_matrix[3], ob->obmat[3]);
}
- DRW_shgroup_call_add(stl->g_data->shgrps_grid, e_data.batch_grid, stl->storage->grid_matrix);
+ DRW_shgroup_call(stl->g_data->shgrps_grid, e_data.batch_grid, stl->storage->grid_matrix);
}
}
}
diff --git a/source/blender/draw/engines/gpencil/gpencil_engine.h b/source/blender/draw/engines/gpencil/gpencil_engine.h
index 2ac1dc3211c..5dab0a56b63 100644
--- a/source/blender/draw/engines/gpencil/gpencil_engine.h
+++ b/source/blender/draw/engines/gpencil/gpencil_engine.h
@@ -129,7 +129,7 @@ typedef struct GPENCIL_shgroup {
int caps_mode[2];
float obj_scale;
int xray_mode;
- int use_follow_path;
+ int alignment_mode;
float gradient_f;
float gradient_s[2];
@@ -182,14 +182,12 @@ typedef struct GPENCIL_Storage {
float gradient_f;
float gradient_s[2];
- int use_follow_path;
+ int alignment_mode;
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];
@@ -437,7 +435,8 @@ void DRW_gpencil_multisample_ensure(struct GPENCIL_Data *vedata, int rect_w, int
void DRW_gpencil_get_point_geom(struct GpencilBatchCacheElem *be,
struct bGPDstroke *gps,
short thickness,
- const float ink[4]);
+ const float ink[4],
+ const int follow_mode);
void DRW_gpencil_get_stroke_geom(struct GpencilBatchCacheElem *be,
struct bGPDstroke *gps,
short thickness,
@@ -514,7 +513,7 @@ void GPENCIL_render_to_image(void *vedata,
/* Use of multisample framebuffers. */
#define MULTISAMPLE_GP_SYNC_ENABLE(lvl, fbl) \
{ \
- if ((lvl > 0) && (fbl->multisample_fb != NULL)) { \
+ if ((lvl > 0) && (fbl->multisample_fb != NULL) && (DRW_state_is_fbo())) { \
DRW_stats_query_start("GP Multisample Blit"); \
GPU_framebuffer_bind(fbl->multisample_fb); \
GPU_framebuffer_clear_color_depth(fbl->multisample_fb, (const float[4]){0.0f}, 1.0f); \
@@ -525,7 +524,7 @@ void GPENCIL_render_to_image(void *vedata,
#define MULTISAMPLE_GP_SYNC_DISABLE(lvl, fbl, fb, txl) \
{ \
- if ((lvl > 0) && (fbl->multisample_fb != NULL)) { \
+ if ((lvl > 0) && (fbl->multisample_fb != NULL) && (DRW_state_is_fbo())) { \
DRW_stats_query_start("GP Multisample Resolve"); \
GPU_framebuffer_bind(fb); \
DRW_multisamples_resolve(txl->multisample_depth, txl->multisample_color, true); \
diff --git a/source/blender/draw/engines/gpencil/gpencil_render.c b/source/blender/draw/engines/gpencil/gpencil_render.c
index e6a3f45d60d..8f3382fc138 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_persmat_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 355235618f6..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;
}
+ Camera *cam = camera->data;
- const DRWContextState *draw_ctx = DRW_context_state_get();
- Scene *scene = draw_ctx->scene;
- Camera *cam = (Camera *)camera->data;
-
- float fstop = cam->gpu_dof.fstop;
+ 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;
@@ -210,7 +201,7 @@ static void DRW_gpencil_fx_blur(ShaderFxData *fx,
GPUBatch *fxquad = DRW_cache_fullscreen_quad_get();
fx_shgrp = DRW_shgroup_create(e_data->gpencil_fx_blur_sh, psl->fx_shader_pass_blend);
- DRW_shgroup_call_add(fx_shgrp, fxquad, NULL);
+ DRW_shgroup_call(fx_shgrp, fxquad, NULL);
DRW_shgroup_uniform_texture_ref(fx_shgrp, "strokeColor", &e_data->temp_color_tx_a);
DRW_shgroup_uniform_texture_ref(fx_shgrp, "strokeDepth", &e_data->temp_depth_tx_a);
DRW_shgroup_uniform_vec2(fx_shgrp, "Viewport", DRW_viewport_size_get(), 1);
@@ -235,7 +226,7 @@ static void DRW_gpencil_fx_colorize(ShaderFxData *fx, GPENCIL_e_data *e_data, GP
GPUBatch *fxquad = DRW_cache_fullscreen_quad_get();
fx_shgrp = DRW_shgroup_create(e_data->gpencil_fx_colorize_sh, psl->fx_shader_pass);
- DRW_shgroup_call_add(fx_shgrp, fxquad, NULL);
+ DRW_shgroup_call(fx_shgrp, fxquad, NULL);
DRW_shgroup_uniform_texture_ref(fx_shgrp, "strokeColor", &e_data->temp_color_tx_a);
DRW_shgroup_uniform_texture_ref(fx_shgrp, "strokeDepth", &e_data->temp_depth_tx_a);
DRW_shgroup_uniform_vec4(fx_shgrp, "low_color", &fxd->low_color[0], 1);
@@ -267,7 +258,7 @@ static void DRW_gpencil_fx_flip(ShaderFxData *fx, GPENCIL_e_data *e_data, GPENCI
GPUBatch *fxquad = DRW_cache_fullscreen_quad_get();
fx_shgrp = DRW_shgroup_create(e_data->gpencil_fx_flip_sh, psl->fx_shader_pass);
- DRW_shgroup_call_add(fx_shgrp, fxquad, NULL);
+ DRW_shgroup_call(fx_shgrp, fxquad, NULL);
DRW_shgroup_uniform_texture_ref(fx_shgrp, "strokeColor", &e_data->temp_color_tx_a);
DRW_shgroup_uniform_texture_ref(fx_shgrp, "strokeDepth", &e_data->temp_depth_tx_a);
DRW_shgroup_uniform_int(fx_shgrp, "flipmode", &fxd->flipmode, 1);
@@ -297,7 +288,7 @@ static void DRW_gpencil_fx_light(ShaderFxData *fx,
GPUBatch *fxquad = DRW_cache_fullscreen_quad_get();
fx_shgrp = DRW_shgroup_create(e_data->gpencil_fx_light_sh, psl->fx_shader_pass);
- DRW_shgroup_call_add(fx_shgrp, fxquad, NULL);
+ DRW_shgroup_call(fx_shgrp, fxquad, NULL);
DRW_shgroup_uniform_texture_ref(fx_shgrp, "strokeColor", &e_data->temp_color_tx_a);
DRW_shgroup_uniform_texture_ref(fx_shgrp, "strokeDepth", &e_data->temp_depth_tx_a);
@@ -352,7 +343,7 @@ static void DRW_gpencil_fx_pixel(ShaderFxData *fx,
GPUBatch *fxquad = DRW_cache_fullscreen_quad_get();
fx_shgrp = DRW_shgroup_create(e_data->gpencil_fx_pixel_sh, psl->fx_shader_pass);
- DRW_shgroup_call_add(fx_shgrp, fxquad, NULL);
+ DRW_shgroup_call(fx_shgrp, fxquad, NULL);
DRW_shgroup_uniform_texture_ref(fx_shgrp, "strokeColor", &e_data->temp_color_tx_a);
DRW_shgroup_uniform_texture_ref(fx_shgrp, "strokeDepth", &e_data->temp_depth_tx_a);
DRW_shgroup_uniform_int(fx_shgrp, "size", &fxd->size[0], 3);
@@ -386,7 +377,7 @@ static void DRW_gpencil_fx_rim(ShaderFxData *fx,
/* prepare pass */
fx_shgrp = DRW_shgroup_create(e_data->gpencil_fx_rim_prepare_sh, psl->fx_shader_pass_blend);
- DRW_shgroup_call_add(fx_shgrp, fxquad, NULL);
+ DRW_shgroup_call(fx_shgrp, fxquad, NULL);
DRW_shgroup_uniform_texture_ref(fx_shgrp, "strokeColor", &e_data->temp_color_tx_a);
DRW_shgroup_uniform_texture_ref(fx_shgrp, "strokeDepth", &e_data->temp_depth_tx_a);
DRW_shgroup_uniform_vec2(fx_shgrp, "Viewport", DRW_viewport_size_get(), 1);
@@ -403,7 +394,7 @@ static void DRW_gpencil_fx_rim(ShaderFxData *fx,
/* blur pass */
fx_shgrp = DRW_shgroup_create(e_data->gpencil_fx_blur_sh, psl->fx_shader_pass_blend);
- DRW_shgroup_call_add(fx_shgrp, fxquad, NULL);
+ DRW_shgroup_call(fx_shgrp, fxquad, NULL);
DRW_shgroup_uniform_texture_ref(fx_shgrp, "strokeColor", &e_data->temp_color_tx_fx);
DRW_shgroup_uniform_texture_ref(fx_shgrp, "strokeDepth", &e_data->temp_depth_tx_fx);
DRW_shgroup_uniform_vec2(fx_shgrp, "Viewport", DRW_viewport_size_get(), 1);
@@ -417,7 +408,7 @@ static void DRW_gpencil_fx_rim(ShaderFxData *fx,
/* resolve pass */
fx_shgrp = DRW_shgroup_create(e_data->gpencil_fx_rim_resolve_sh, psl->fx_shader_pass_blend);
- DRW_shgroup_call_add(fx_shgrp, fxquad, NULL);
+ DRW_shgroup_call(fx_shgrp, fxquad, NULL);
DRW_shgroup_uniform_texture_ref(fx_shgrp, "strokeColor", &e_data->temp_color_tx_a);
DRW_shgroup_uniform_texture_ref(fx_shgrp, "strokeDepth", &e_data->temp_depth_tx_a);
DRW_shgroup_uniform_texture_ref(fx_shgrp, "strokeRim", &e_data->temp_color_tx_fx);
@@ -453,7 +444,7 @@ static void DRW_gpencil_fx_shadow(ShaderFxData *fx,
GPUBatch *fxquad = DRW_cache_fullscreen_quad_get();
/* prepare pass */
fx_shgrp = DRW_shgroup_create(e_data->gpencil_fx_shadow_prepare_sh, psl->fx_shader_pass_blend);
- DRW_shgroup_call_add(fx_shgrp, fxquad, NULL);
+ DRW_shgroup_call(fx_shgrp, fxquad, NULL);
DRW_shgroup_uniform_texture_ref(fx_shgrp, "strokeColor", &e_data->temp_color_tx_a);
DRW_shgroup_uniform_texture_ref(fx_shgrp, "strokeDepth", &e_data->temp_depth_tx_a);
DRW_shgroup_uniform_vec2(fx_shgrp, "Viewport", DRW_viewport_size_get(), 1);
@@ -488,7 +479,7 @@ static void DRW_gpencil_fx_shadow(ShaderFxData *fx,
/* blur pass */
fx_shgrp = DRW_shgroup_create(e_data->gpencil_fx_blur_sh, psl->fx_shader_pass_blend);
- DRW_shgroup_call_add(fx_shgrp, fxquad, NULL);
+ DRW_shgroup_call(fx_shgrp, fxquad, NULL);
DRW_shgroup_uniform_texture_ref(fx_shgrp, "strokeColor", &e_data->temp_color_tx_fx);
DRW_shgroup_uniform_texture_ref(fx_shgrp, "strokeDepth", &e_data->temp_depth_tx_fx);
DRW_shgroup_uniform_vec2(fx_shgrp, "Viewport", DRW_viewport_size_get(), 1);
@@ -502,7 +493,7 @@ static void DRW_gpencil_fx_shadow(ShaderFxData *fx,
/* resolve pass */
fx_shgrp = DRW_shgroup_create(e_data->gpencil_fx_shadow_resolve_sh, psl->fx_shader_pass_blend);
- DRW_shgroup_call_add(fx_shgrp, fxquad, NULL);
+ DRW_shgroup_call(fx_shgrp, fxquad, NULL);
DRW_shgroup_uniform_texture_ref(fx_shgrp, "strokeColor", &e_data->temp_color_tx_a);
DRW_shgroup_uniform_texture_ref(fx_shgrp, "strokeDepth", &e_data->temp_depth_tx_a);
DRW_shgroup_uniform_texture_ref(fx_shgrp, "shadowColor", &e_data->temp_color_tx_fx);
@@ -531,7 +522,7 @@ static void DRW_gpencil_fx_glow(ShaderFxData *fx,
GPUBatch *fxquad = DRW_cache_fullscreen_quad_get();
/* prepare pass */
fx_shgrp = DRW_shgroup_create(e_data->gpencil_fx_glow_prepare_sh, psl->fx_shader_pass_blend);
- DRW_shgroup_call_add(fx_shgrp, fxquad, NULL);
+ DRW_shgroup_call(fx_shgrp, fxquad, NULL);
DRW_shgroup_uniform_texture_ref(fx_shgrp, "strokeColor", &e_data->temp_color_tx_a);
DRW_shgroup_uniform_texture_ref(fx_shgrp, "strokeDepth", &e_data->temp_depth_tx_a);
@@ -544,7 +535,7 @@ static void DRW_gpencil_fx_glow(ShaderFxData *fx,
/* blur pass */
fx_shgrp = DRW_shgroup_create(e_data->gpencil_fx_blur_sh, psl->fx_shader_pass_blend);
- DRW_shgroup_call_add(fx_shgrp, fxquad, NULL);
+ DRW_shgroup_call(fx_shgrp, fxquad, NULL);
DRW_shgroup_uniform_texture_ref(fx_shgrp, "strokeColor", &e_data->temp_color_tx_fx);
DRW_shgroup_uniform_texture_ref(fx_shgrp, "strokeDepth", &e_data->temp_depth_tx_fx);
DRW_shgroup_uniform_vec2(fx_shgrp, "Viewport", DRW_viewport_size_get(), 1);
@@ -558,7 +549,7 @@ static void DRW_gpencil_fx_glow(ShaderFxData *fx,
/* resolve pass */
fx_shgrp = DRW_shgroup_create(e_data->gpencil_fx_glow_resolve_sh, psl->fx_shader_pass_blend);
- DRW_shgroup_call_add(fx_shgrp, fxquad, NULL);
+ DRW_shgroup_call(fx_shgrp, fxquad, NULL);
DRW_shgroup_uniform_texture_ref(fx_shgrp, "strokeColor", &e_data->temp_color_tx_a);
DRW_shgroup_uniform_texture_ref(fx_shgrp, "strokeDepth", &e_data->temp_depth_tx_a);
DRW_shgroup_uniform_texture_ref(fx_shgrp, "glowColor", &e_data->temp_color_tx_fx);
@@ -593,7 +584,7 @@ static void DRW_gpencil_fx_swirl(ShaderFxData *fx,
GPUBatch *fxquad = DRW_cache_fullscreen_quad_get();
fx_shgrp = DRW_shgroup_create(e_data->gpencil_fx_swirl_sh, psl->fx_shader_pass);
- DRW_shgroup_call_add(fx_shgrp, fxquad, NULL);
+ DRW_shgroup_call(fx_shgrp, fxquad, NULL);
DRW_shgroup_uniform_texture_ref(fx_shgrp, "strokeColor", &e_data->temp_color_tx_a);
DRW_shgroup_uniform_texture_ref(fx_shgrp, "strokeDepth", &e_data->temp_depth_tx_a);
@@ -624,7 +615,7 @@ static void DRW_gpencil_fx_wave(ShaderFxData *fx, GPENCIL_e_data *e_data, GPENCI
GPUBatch *fxquad = DRW_cache_fullscreen_quad_get();
DRWShadingGroup *fx_shgrp = DRW_shgroup_create(e_data->gpencil_fx_wave_sh, psl->fx_shader_pass);
- DRW_shgroup_call_add(fx_shgrp, fxquad, NULL);
+ DRW_shgroup_call(fx_shgrp, fxquad, NULL);
DRW_shgroup_uniform_texture_ref(fx_shgrp, "strokeColor", &e_data->temp_color_tx_a);
DRW_shgroup_uniform_texture_ref(fx_shgrp, "strokeDepth", &e_data->temp_depth_tx_a);
DRW_shgroup_uniform_float(fx_shgrp, "amplitude", &fxd->amplitude, 1);
diff --git a/source/blender/draw/engines/gpencil/shaders/gpencil_edit_point_geom.glsl b/source/blender/draw/engines/gpencil/shaders/gpencil_edit_point_geom.glsl
index 8c3fd022004..e0634a7d1a7 100644
--- a/source/blender/draw/engines/gpencil/shaders/gpencil_edit_point_geom.glsl
+++ b/source/blender/draw/engines/gpencil/shaders/gpencil_edit_point_geom.glsl
@@ -1,4 +1,3 @@
-uniform mat4 ModelViewProjectionMatrix;
uniform vec2 Viewport;
layout(points) in;
diff --git a/source/blender/draw/engines/gpencil/shaders/gpencil_edit_point_vert.glsl b/source/blender/draw/engines/gpencil/shaders/gpencil_edit_point_vert.glsl
index eea28755ae6..a1cfb2ae4ae 100644
--- a/source/blender/draw/engines/gpencil/shaders/gpencil_edit_point_vert.glsl
+++ b/source/blender/draw/engines/gpencil/shaders/gpencil_edit_point_vert.glsl
@@ -1,4 +1,3 @@
-uniform mat4 ModelViewProjectionMatrix;
in vec3 pos;
in vec4 color;
@@ -9,7 +8,7 @@ out float finalThickness;
void main()
{
- gl_Position = ModelViewProjectionMatrix * vec4(pos, 1.0);
+ gl_Position = point_object_to_ndc(pos);
finalColor = color;
finalThickness = size;
}
diff --git a/source/blender/draw/engines/gpencil/shaders/gpencil_fill_frag.glsl b/source/blender/draw/engines/gpencil/shaders/gpencil_fill_frag.glsl
index acf60fc2d59..192720a4e98 100644
--- a/source/blender/draw/engines/gpencil/shaders/gpencil_fill_frag.glsl
+++ b/source/blender/draw/engines/gpencil/shaders/gpencil_fill_frag.glsl
@@ -89,6 +89,27 @@ void set_color(in vec4 color,
ocolor.a *= layer_opacity;
}
+float linearrgb_to_srgb(float c)
+{
+ if (c < 0.0031308) {
+ return (c < 0.0) ? 0.0 : c * 12.92;
+ }
+ else {
+ return 1.055 * pow(c, 1.0 / 2.4) - 0.055;
+ }
+}
+
+vec4 texture_read_as_srgb(sampler2D tex, vec2 co)
+{
+ /* By convention image textures return scene linear colors, but
+ * grease pencil still works in srgb. */
+ vec4 color = texture(tex, co);
+ color.r = linearrgb_to_srgb(color.r);
+ color.g = linearrgb_to_srgb(color.g);
+ color.b = linearrgb_to_srgb(color.b);
+ return color;
+}
+
void main()
{
vec2 t_center = vec2(0.5, 0.5);
@@ -97,8 +118,8 @@ void main()
vec2 rot_tex = (matrot_tex * (texCoord_interp - t_center)) + t_center + texture_offset;
vec4 tmp_color;
tmp_color = (texture_clamp == 0) ?
- texture2D(myTexture, rot_tex * texture_scale) :
- texture2D(myTexture, clamp(rot_tex * texture_scale, 0.0, 1.0));
+ texture_read_as_srgb(myTexture, rot_tex * texture_scale) :
+ texture_read_as_srgb(myTexture, clamp(rot_tex * texture_scale, 0.0, 1.0));
vec4 text_color = vec4(tmp_color[0], tmp_color[1], tmp_color[2], tmp_color[3] * texture_opacity);
vec4 chesscolor;
diff --git a/source/blender/draw/engines/gpencil/shaders/gpencil_fill_vert.glsl b/source/blender/draw/engines/gpencil/shaders/gpencil_fill_vert.glsl
index d71f57eb98c..eb452f4c660 100644
--- a/source/blender/draw/engines/gpencil/shaders/gpencil_fill_vert.glsl
+++ b/source/blender/draw/engines/gpencil/shaders/gpencil_fill_vert.glsl
@@ -1,14 +1,14 @@
-uniform mat4 ModelViewProjectionMatrix;
in vec3 pos;
in vec4 color;
in vec2 texCoord;
+
out vec4 finalColor;
out vec2 texCoord_interp;
void main(void)
{
- gl_Position = ModelViewProjectionMatrix * vec4(pos, 1.0);
+ gl_Position = point_object_to_ndc(pos);
finalColor = color;
texCoord_interp = texCoord;
}
diff --git a/source/blender/draw/engines/gpencil/shaders/gpencil_paper_frag.glsl b/source/blender/draw/engines/gpencil/shaders/gpencil_paper_frag.glsl
index 3c1424f98ff..1d1cd6349dc 100644
--- a/source/blender/draw/engines/gpencil/shaders/gpencil_paper_frag.glsl
+++ b/source/blender/draw/engines/gpencil/shaders/gpencil_paper_frag.glsl
@@ -5,5 +5,5 @@ out vec4 FragColor;
void main()
{
- FragColor = vec4(color, opacity);
+ FragColor = vec4(color, 1.0 - opacity);
}
diff --git a/source/blender/draw/engines/gpencil/shaders/gpencil_point_frag.glsl b/source/blender/draw/engines/gpencil/shaders/gpencil_point_frag.glsl
index cc47e12b303..569a68679b4 100644
--- a/source/blender/draw/engines/gpencil/shaders/gpencil_point_frag.glsl
+++ b/source/blender/draw/engines/gpencil/shaders/gpencil_point_frag.glsl
@@ -47,6 +47,27 @@ vec2 check_box_point(vec2 pt, vec2 radius)
return rtn;
}
+float linearrgb_to_srgb(float c)
+{
+ if (c < 0.0031308) {
+ return (c < 0.0) ? 0.0 : c * 12.92;
+ }
+ else {
+ return 1.055 * pow(c, 1.0 / 2.4) - 0.055;
+ }
+}
+
+vec4 texture_read_as_srgb(sampler2D tex, vec2 co)
+{
+ /* By convention image textures return scene linear colors, but
+ * grease pencil still works in srgb. */
+ vec4 color = texture(tex, co);
+ color.r = linearrgb_to_srgb(color.r);
+ color.g = linearrgb_to_srgb(color.g);
+ color.b = linearrgb_to_srgb(color.b);
+ return color;
+}
+
void main()
{
vec2 centered = mTexCoord - vec2(0.5);
@@ -65,7 +86,7 @@ void main()
}
}
- vec4 tmp_color = texture2D(myTexture, mTexCoord);
+ vec4 tmp_color = texture_read_as_srgb(myTexture, mTexCoord);
/* Solid */
if ((color_type == GPENCIL_COLOR_SOLID) || (no_texture)) {
@@ -73,7 +94,7 @@ void main()
}
/* texture */
if ((color_type == GPENCIL_COLOR_TEXTURE) && (!no_texture)) {
- vec4 text_color = texture2D(myTexture, mTexCoord);
+ vec4 text_color = texture_read_as_srgb(myTexture, mTexCoord);
if (mix_stroke_factor > 0.0) {
fragColor.rgb = mix(text_color.rgb, colormix.rgb, mix_stroke_factor);
fragColor.a = text_color.a;
@@ -87,7 +108,7 @@ void main()
}
/* pattern */
if ((color_type == GPENCIL_COLOR_PATTERN) && (!no_texture)) {
- vec4 text_color = texture2D(myTexture, mTexCoord);
+ vec4 text_color = texture_read_as_srgb(myTexture, mTexCoord);
fragColor = mColor;
/* mult both alpha factor to use strength factor with color alpha limit */
fragColor.a = min(text_color.a * mColor.a, mColor.a);
diff --git a/source/blender/draw/engines/gpencil/shaders/gpencil_point_geom.glsl b/source/blender/draw/engines/gpencil/shaders/gpencil_point_geom.glsl
index a64a7ecb9be..a2f4c1f9b15 100644
--- a/source/blender/draw/engines/gpencil/shaders/gpencil_point_geom.glsl
+++ b/source/blender/draw/engines/gpencil/shaders/gpencil_point_geom.glsl
@@ -1,7 +1,6 @@
-uniform mat4 ModelViewProjectionMatrix;
uniform vec2 Viewport;
uniform int xraymode;
-uniform int use_follow_path;
+uniform int alignment_mode;
layout(points) in;
layout(triangle_strip, max_vertices = 4) out;
@@ -21,6 +20,9 @@ out vec2 mTexCoord;
#define M_2PI 6.28318530717958647692 /* 2*pi */
#define FALSE 0
+/* keep this definition equals to GP_STYLE_FOLLOW_FIXED value */
+#define FIXED 2
+
/* project 3d point to 2d on screen space */
vec2 toScreenSpace(vec4 vertex)
{
@@ -70,7 +72,7 @@ float getAngle(vec2 pt0, vec2 pt1)
return 0.0;
}
- if (use_follow_path == FALSE) {
+ if (alignment_mode == FIXED) {
return 0.0;
}
diff --git a/source/blender/draw/engines/gpencil/shaders/gpencil_point_vert.glsl b/source/blender/draw/engines/gpencil/shaders/gpencil_point_vert.glsl
index 9cef7601770..ef8b361373f 100644
--- a/source/blender/draw/engines/gpencil/shaders/gpencil_point_vert.glsl
+++ b/source/blender/draw/engines/gpencil/shaders/gpencil_point_vert.glsl
@@ -1,5 +1,3 @@
-uniform mat4 ModelViewProjectionMatrix;
-uniform mat4 ProjectionMatrix;
uniform float pixsize; /* rv3d->pixsize */
uniform int keep_size;
@@ -32,8 +30,8 @@ float defaultpixsize = pixsize * (1000.0 / pixfactor);
void main()
{
- gl_Position = ModelViewProjectionMatrix * vec4(pos, 1.0);
- finalprev_pos = ModelViewProjectionMatrix * vec4(prev_pos, 1.0);
+ gl_Position = point_object_to_ndc(pos);
+ finalprev_pos = point_object_to_ndc(prev_pos);
finalColor = color;
if (keep_size == TRUE) {
diff --git a/source/blender/draw/engines/gpencil/shaders/gpencil_stroke_frag.glsl b/source/blender/draw/engines/gpencil/shaders/gpencil_stroke_frag.glsl
index 6b7cee888ea..a5580e305d6 100644
--- a/source/blender/draw/engines/gpencil/shaders/gpencil_stroke_frag.glsl
+++ b/source/blender/draw/engines/gpencil/shaders/gpencil_stroke_frag.glsl
@@ -27,6 +27,27 @@ out vec4 fragColor;
bool no_texture = (shading_type[0] == OB_SOLID) && (shading_type[1] != V3D_SHADING_TEXTURE_COLOR);
+float linearrgb_to_srgb(float c)
+{
+ if (c < 0.0031308) {
+ return (c < 0.0) ? 0.0 : c * 12.92;
+ }
+ else {
+ return 1.055 * pow(c, 1.0 / 2.4) - 0.055;
+ }
+}
+
+vec4 texture_read_as_srgb(sampler2D tex, vec2 co)
+{
+ /* By convention image textures return scene linear colors, but
+ * grease pencil still works in srgb. */
+ vec4 color = texture(tex, co);
+ color.r = linearrgb_to_srgb(color.r);
+ color.g = linearrgb_to_srgb(color.g);
+ color.b = linearrgb_to_srgb(color.b);
+ return color;
+}
+
void main()
{
@@ -47,10 +68,10 @@ void main()
/* texture for endcaps */
vec4 text_color;
if (uvfac[1] == ENDCAP) {
- text_color = texture2D(myTexture, vec2(mTexCoord.x, mTexCoord.y));
+ text_color = texture_read_as_srgb(myTexture, vec2(mTexCoord.x, mTexCoord.y));
}
else {
- text_color = texture2D(myTexture, mTexCoord);
+ text_color = texture_read_as_srgb(myTexture, mTexCoord);
}
/* texture */
diff --git a/source/blender/draw/engines/gpencil/shaders/gpencil_stroke_geom.glsl b/source/blender/draw/engines/gpencil/shaders/gpencil_stroke_geom.glsl
index b90f5b33a57..9ea96806481 100644
--- a/source/blender/draw/engines/gpencil/shaders/gpencil_stroke_geom.glsl
+++ b/source/blender/draw/engines/gpencil/shaders/gpencil_stroke_geom.glsl
@@ -1,4 +1,3 @@
-uniform mat4 ModelViewProjectionMatrix;
uniform vec2 Viewport;
uniform int xraymode;
uniform int color_type;
diff --git a/source/blender/draw/engines/gpencil/shaders/gpencil_stroke_vert.glsl b/source/blender/draw/engines/gpencil/shaders/gpencil_stroke_vert.glsl
index 946b39c006a..c7089f357f9 100644
--- a/source/blender/draw/engines/gpencil/shaders/gpencil_stroke_vert.glsl
+++ b/source/blender/draw/engines/gpencil/shaders/gpencil_stroke_vert.glsl
@@ -1,5 +1,3 @@
-uniform mat4 ModelViewProjectionMatrix;
-uniform mat4 ProjectionMatrix;
uniform float pixsize; /* rv3d->pixsize */
uniform int keep_size;
@@ -30,7 +28,7 @@ float defaultpixsize = pixsize * (1000.0 / pixfactor);
void main(void)
{
- gl_Position = ModelViewProjectionMatrix * vec4(pos, 1.0);
+ gl_Position = point_object_to_ndc(pos);
finalColor = color;
if (keep_size == TRUE) {
diff --git a/source/blender/draw/engines/workbench/shaders/workbench_common_lib.glsl b/source/blender/draw/engines/workbench/shaders/workbench_common_lib.glsl
index c76ad8c1d7b..96f8f6e4c7a 100644
--- a/source/blender/draw/engines/workbench/shaders/workbench_common_lib.glsl
+++ b/source/blender/draw/engines/workbench/shaders/workbench_common_lib.glsl
@@ -140,32 +140,18 @@ vec2 matcap_uv_compute(vec3 I, vec3 N, bool flipped)
return matcap_uv * 0.496 + 0.5;
}
-float srgb_to_linearrgb(float c)
-{
- if (c < 0.04045) {
- return (c < 0.0) ? 0.0 : c * (1.0 / 12.92);
- }
- else {
- return pow((c + 0.055) * (1.0 / 1.055), 2.4);
- }
-}
-
-vec4 srgb_to_linearrgb(vec4 col_from)
-{
- vec4 col_to;
- col_to.r = srgb_to_linearrgb(col_from.r);
- col_to.g = srgb_to_linearrgb(col_from.g);
- col_to.b = srgb_to_linearrgb(col_from.b);
- col_to.a = col_from.a;
- return col_to;
-}
-
-vec4 workbench_sample_texture(sampler2D image, vec2 coord, bool srgb, bool nearest_sampling)
+vec4 workbench_sample_texture(sampler2D image, vec2 coord, bool nearest_sampling)
{
vec2 tex_size = vec2(textureSize(image, 0).xy);
/* TODO(fclem) We could do the same with sampler objects.
* But this is a quick workaround instead of messing with the GPUTexture itself. */
vec2 uv = nearest_sampling ? (floor(coord * tex_size) + 0.5) / tex_size : coord;
vec4 color = texture(image, uv);
- return (srgb) ? srgb_to_linearrgb(color) : color;
+
+ /* Unpremultiply, ideally shaders would be added so this is not needed. */
+ if (!(color.a == 0.0 || color.a == 1.0)) {
+ color.rgb = color.rgb / color.a;
+ }
+
+ return color;
}
diff --git a/source/blender/draw/engines/workbench/shaders/workbench_deferred_composite_frag.glsl b/source/blender/draw/engines/workbench/shaders/workbench_deferred_composite_frag.glsl
index 65196c1a836..a1f80440404 100644
--- a/source/blender/draw/engines/workbench/shaders/workbench_deferred_composite_frag.glsl
+++ b/source/blender/draw/engines/workbench/shaders/workbench_deferred_composite_frag.glsl
@@ -1,8 +1,5 @@
out vec4 fragColor;
-uniform mat4 ProjectionMatrix;
-uniform mat4 ViewMatrixInverse;
-
uniform usampler2D objectId;
uniform sampler2D materialBuffer;
uniform sampler2D normalBuffer;
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_forward_transparent_accum_frag.glsl b/source/blender/draw/engines/workbench/shaders/workbench_forward_transparent_accum_frag.glsl
index 5eff0b41e20..51bce639b63 100644
--- a/source/blender/draw/engines/workbench/shaders/workbench_forward_transparent_accum_frag.glsl
+++ b/source/blender/draw/engines/workbench/shaders/workbench_forward_transparent_accum_frag.glsl
@@ -1,11 +1,8 @@
uniform float ImageTransparencyCutoff = 0.1;
uniform sampler2D image;
-uniform bool imageSrgb;
uniform bool imageNearest;
-uniform mat4 ProjectionMatrix;
-uniform mat4 ViewMatrixInverse;
uniform float alpha = 0.5;
uniform vec2 invertedViewportSize;
uniform vec4 viewvecs[3];
@@ -46,7 +43,7 @@ void main()
vec4 diffuse_color;
#if defined(V3D_SHADING_TEXTURE_COLOR)
- diffuse_color = workbench_sample_texture(image, uv_interp, imageSrgb, imageNearest);
+ diffuse_color = workbench_sample_texture(image, uv_interp, imageNearest);
if (diffuse_color.a < ImageTransparencyCutoff) {
discard;
}
diff --git a/source/blender/draw/engines/workbench/shaders/workbench_prepass_frag.glsl b/source/blender/draw/engines/workbench/shaders/workbench_prepass_frag.glsl
index 2596fc4cf88..af9f1d14f4a 100644
--- a/source/blender/draw/engines/workbench/shaders/workbench_prepass_frag.glsl
+++ b/source/blender/draw/engines/workbench/shaders/workbench_prepass_frag.glsl
@@ -6,7 +6,6 @@ uniform float materialRoughness;
uniform sampler2D image;
uniform float ImageTransparencyCutoff = 0.1;
-uniform bool imageSrgb;
uniform bool imageNearest;
#ifdef NORMAL_VIEWPORT_PASS_ENABLED
@@ -41,7 +40,7 @@ void main()
vec4 color;
# if defined(V3D_SHADING_TEXTURE_COLOR)
- color = workbench_sample_texture(image, uv_interp, imageSrgb, imageNearest);
+ color = workbench_sample_texture(image, uv_interp, imageNearest);
if (color.a < ImageTransparencyCutoff) {
discard;
}
diff --git a/source/blender/draw/engines/workbench/shaders/workbench_prepass_vert.glsl b/source/blender/draw/engines/workbench/shaders/workbench_prepass_vert.glsl
index f2c684cdb6a..7872c1380ed 100644
--- a/source/blender/draw/engines/workbench/shaders/workbench_prepass_vert.glsl
+++ b/source/blender/draw/engines/workbench/shaders/workbench_prepass_vert.glsl
@@ -1,10 +1,3 @@
-uniform mat4 ModelViewProjectionMatrix;
-uniform mat4 ModelMatrix;
-uniform mat4 ModelMatrixInverse;
-uniform mat4 ProjectionMatrix;
-uniform mat4 ViewProjectionMatrix;
-uniform mat4 ViewMatrixInverse;
-uniform mat3 NormalMatrix;
#ifndef HAIR_SHADER
in vec3 pos;
@@ -50,6 +43,17 @@ vec3 srgb_to_linear_attr(vec3 c)
}
#endif
+vec3 workbench_hair_hair_normal(vec3 tan, vec3 binor, float rand)
+{
+ /* To "simulate" anisotropic shading, randomize hair normal per strand. */
+ vec3 nor = cross(tan, binor);
+ nor = normalize(mix(nor, -tan, rand * 0.1));
+ float cos_theta = (rand * 2.0 - 1.0) * 0.2;
+ float sin_theta = sqrt(max(0.0, 1.0 - cos_theta * cos_theta));
+ nor = nor * sin_theta + binor * cos_theta;
+ return nor;
+}
+
void main()
{
#ifdef HAIR_SHADER
@@ -57,29 +61,25 @@ void main()
vec2 uv = hair_get_customdata_vec2(u);
# endif
float time, thick_time, thickness;
- vec3 pos, tan, binor;
+ vec3 world_pos, tan, binor;
hair_get_pos_tan_binor_time((ProjectionMatrix[3][3] == 0.0),
ModelMatrixInverse,
ViewMatrixInverse[3].xyz,
ViewMatrixInverse[2].xyz,
- pos,
+ world_pos,
tan,
binor,
time,
thickness,
thick_time);
- /* To "simulate" anisotropic shading, randomize hair normal per strand. */
+
hair_rand = integer_noise(hair_get_strand_id());
- tan = normalize(tan);
- vec3 nor = normalize(cross(binor, tan));
- nor = normalize(mix(nor, -tan, hair_rand * 0.10));
- float cos_theta = (hair_rand * 2.0 - 1.0) * 0.20;
- float sin_theta = sqrt(max(0.0, 1.0f - cos_theta * cos_theta));
- nor = nor * sin_theta + binor * cos_theta;
- gl_Position = ViewProjectionMatrix * vec4(pos, 1.0);
+ vec3 nor = workbench_hair_hair_normal(tan, binor, hair_rand);
#else
- gl_Position = ModelViewProjectionMatrix * vec4(pos, 1.0);
+ vec3 world_pos = point_object_to_world(pos);
#endif
+ gl_Position = point_world_to_ndc(world_pos);
+
#ifdef V3D_SHADING_TEXTURE_COLOR
uv_interp = uv;
#endif
@@ -91,13 +91,13 @@ void main()
#endif
#ifdef NORMAL_VIEWPORT_PASS_ENABLED
- normal_viewport = NormalMatrix * nor;
+ normal_viewport = normal_object_to_view(nor);
# ifndef HAIR_SHADER
normal_viewport = normalize(normal_viewport);
# endif
#endif
#ifdef USE_WORLD_CLIP_PLANES
- world_clip_planes_calc_clip_distance((ModelMatrix * vec4(pos, 1.0)).xyz);
+ world_clip_planes_calc_clip_distance(world_pos);
#endif
}
diff --git a/source/blender/draw/engines/workbench/shaders/workbench_shadow_vert.glsl b/source/blender/draw/engines/workbench/shaders/workbench_shadow_vert.glsl
index afd704a7d3a..e07f87525e2 100644
--- a/source/blender/draw/engines/workbench/shaders/workbench_shadow_vert.glsl
+++ b/source/blender/draw/engines/workbench/shaders/workbench_shadow_vert.glsl
@@ -1,7 +1,5 @@
#define INFINITE 1000.0
-uniform mat4 ModelViewProjectionMatrix;
-
uniform vec3 lightDirection = vec3(0.57, 0.57, -0.57);
uniform float lightDistance = 1e4;
@@ -18,6 +16,6 @@ vData;
void main()
{
vData.pos = pos;
- vData.frontPosition = ModelViewProjectionMatrix * vec4(pos, 1.0);
- vData.backPosition = ModelViewProjectionMatrix * vec4(pos + lightDirection * lightDistance, 1.0);
+ vData.frontPosition = point_object_to_ndc(pos);
+ vData.backPosition = point_object_to_ndc(pos + lightDirection * lightDistance);
}
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 a1c269d5a65..fd06c85747f 100644
--- a/source/blender/draw/engines/workbench/shaders/workbench_volume_frag.glsl
+++ b/source/blender/draw/engines/workbench/shaders/workbench_volume_frag.glsl
@@ -1,8 +1,4 @@
-uniform mat4 ProjectionMatrix;
-uniform mat4 ModelMatrixInverse;
-uniform mat4 ModelViewMatrixInverse;
-uniform mat4 ModelMatrix;
uniform vec3 OrcoTexCoFactors[2];
uniform sampler2D depthBuffer;
@@ -219,9 +215,11 @@ void main()
vec3 vs_ray_dir = (is_persp) ? (vs_ray_end - vs_ray_ori) : vec3(0.0, 0.0, -1.0);
vs_ray_dir /= abs(vs_ray_dir.z);
- vec3 ls_ray_dir = mat3(ModelViewMatrixInverse) * vs_ray_dir * OrcoTexCoFactors[1] * 2.0;
- vec3 ls_ray_ori = (ModelViewMatrixInverse * vec4(vs_ray_ori, 1.0)).xyz;
- vec3 ls_ray_end = (ModelViewMatrixInverse * vec4(vs_ray_end, 1.0)).xyz;
+ /* TODO(fclem) Precompute the matrix/ */
+ 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);
ls_ray_ori = (OrcoTexCoFactors[0] + ls_ray_ori * OrcoTexCoFactors[1]) * 2.0 - 1.0;
ls_ray_end = (OrcoTexCoFactors[0] + ls_ray_end * OrcoTexCoFactors[1]) * 2.0 - 1.0;
diff --git a/source/blender/draw/engines/workbench/shaders/workbench_volume_vert.glsl b/source/blender/draw/engines/workbench/shaders/workbench_volume_vert.glsl
index 7a418243fd3..6f0bb56fafd 100644
--- a/source/blender/draw/engines/workbench/shaders/workbench_volume_vert.glsl
+++ b/source/blender/draw/engines/workbench/shaders/workbench_volume_vert.glsl
@@ -1,5 +1,4 @@
-uniform mat4 ModelViewProjectionMatrix;
uniform vec3 OrcoTexCoFactors[2];
uniform float slicePosition;
uniform int sliceAxis; /* -1 is no slice, 0 is X, 1 is Y, 2 is Z. */
@@ -29,5 +28,5 @@ void main()
vec3 final_pos = pos;
#endif
final_pos = ((final_pos * 0.5 + 0.5) - OrcoTexCoFactors[0]) / OrcoTexCoFactors[1];
- gl_Position = ModelViewProjectionMatrix * vec4(final_pos, 1.0);
+ gl_Position = point_object_to_ndc(final_pos);
}
diff --git a/source/blender/draw/engines/workbench/solid_mode.c b/source/blender/draw/engines/workbench/solid_mode.c
index a01b14f17fb..e1050751830 100644
--- a/source/blender/draw/engines/workbench/solid_mode.c
+++ b/source/blender/draw/engines/workbench/solid_mode.c
@@ -61,8 +61,12 @@ static void workbench_solid_cache_finish(void *vedata)
static void workbench_solid_draw_background(void *vedata)
{
WORKBENCH_Data *data = vedata;
- workbench_deferred_draw_background(data);
- workbench_deferred_draw_scene(data);
+ const int num_samples = workbench_num_viewport_rendering_iterations(data);
+
+ for (int sample = 0; sample < num_samples; sample++) {
+ workbench_deferred_draw_background(data);
+ workbench_deferred_draw_scene(data);
+ }
workbench_deferred_draw_finish(data);
}
diff --git a/source/blender/draw/engines/workbench/transparent_mode.c b/source/blender/draw/engines/workbench/transparent_mode.c
index 0f4150ff986..bd2fb24dd85 100644
--- a/source/blender/draw/engines/workbench/transparent_mode.c
+++ b/source/blender/draw/engines/workbench/transparent_mode.c
@@ -59,8 +59,12 @@ static void workbench_transparent_cache_finish(void *vedata)
static void workbench_transparent_draw_background(void *vedata)
{
WORKBENCH_Data *data = vedata;
- workbench_forward_draw_background(data);
- workbench_forward_draw_scene(data);
+ const int num_samples = workbench_num_viewport_rendering_iterations(data);
+
+ for (int sample = 0; sample < num_samples; sample++) {
+ workbench_forward_draw_background(data);
+ workbench_forward_draw_scene(data);
+ }
workbench_forward_draw_finish(data);
}
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 5d7bdc72546..eacd319cc4a 100644
--- a/source/blender/draw/engines/workbench/workbench_deferred.c
+++ b/source/blender/draw/engines/workbench/workbench_deferred.c
@@ -91,6 +91,7 @@ static struct {
/* Shaders */
extern char datatoc_common_hair_lib_glsl[];
+extern char datatoc_common_view_lib_glsl[];
extern char datatoc_workbench_prepass_vert_glsl[];
extern char datatoc_workbench_prepass_frag_glsl[];
@@ -119,6 +120,7 @@ static char *workbench_build_composite_frag(WORKBENCH_PrivateData *wpd)
{
DynStr *ds = BLI_dynstr_new();
+ BLI_dynstr_append(ds, datatoc_common_view_lib_glsl);
BLI_dynstr_append(ds, datatoc_workbench_data_lib_glsl);
BLI_dynstr_append(ds, datatoc_workbench_common_lib_glsl);
BLI_dynstr_append(ds, datatoc_workbench_background_lib_glsl);
@@ -159,6 +161,7 @@ static char *workbench_build_prepass_vert(bool is_hair)
if (is_hair) {
BLI_dynstr_append(ds, datatoc_common_hair_lib_glsl);
}
+ BLI_dynstr_append(ds, datatoc_common_view_lib_glsl);
BLI_dynstr_append(ds, datatoc_workbench_prepass_vert_glsl);
char *str = BLI_dynstr_get_cstring(ds);
BLI_dynstr_free(ds);
@@ -382,33 +385,60 @@ void workbench_deferred_engine_init(WORKBENCH_Data *vedata)
const char *shadow_frag = datatoc_gpu_shader_depth_only_frag_glsl;
#endif
/* TODO only compile on demand */
- e_data.shadow_pass_sh = DRW_shader_create(datatoc_workbench_shadow_vert_glsl,
- datatoc_workbench_shadow_geom_glsl,
- shadow_frag,
- "#define SHADOW_PASS\n"
- "#define DOUBLE_MANIFOLD\n");
- e_data.shadow_pass_manifold_sh = DRW_shader_create(datatoc_workbench_shadow_vert_glsl,
- datatoc_workbench_shadow_geom_glsl,
- shadow_frag,
- "#define SHADOW_PASS\n");
- e_data.shadow_fail_sh = DRW_shader_create(datatoc_workbench_shadow_vert_glsl,
- datatoc_workbench_shadow_geom_glsl,
- shadow_frag,
- "#define SHADOW_FAIL\n"
- "#define DOUBLE_MANIFOLD\n");
- e_data.shadow_fail_manifold_sh = DRW_shader_create(datatoc_workbench_shadow_vert_glsl,
- datatoc_workbench_shadow_geom_glsl,
- shadow_frag,
- "#define SHADOW_FAIL\n");
- e_data.shadow_caps_sh = DRW_shader_create(datatoc_workbench_shadow_vert_glsl,
- datatoc_workbench_shadow_caps_geom_glsl,
- shadow_frag,
- "#define SHADOW_FAIL\n"
- "#define DOUBLE_MANIFOLD\n");
- e_data.shadow_caps_manifold_sh = DRW_shader_create(datatoc_workbench_shadow_vert_glsl,
- datatoc_workbench_shadow_caps_geom_glsl,
- shadow_frag,
- "#define SHADOW_FAIL\n");
+ e_data.shadow_pass_sh = GPU_shader_create_from_arrays({
+ .vert = (const char *[]){datatoc_common_view_lib_glsl,
+ datatoc_workbench_shadow_vert_glsl,
+ NULL},
+ .geom = (const char *[]){datatoc_workbench_shadow_geom_glsl, NULL},
+ .frag = (const char *[]){shadow_frag, NULL},
+ .defs = (const char *[]){"#define SHADOW_PASS\n"
+ "#define DOUBLE_MANIFOLD\n",
+ NULL},
+ });
+ e_data.shadow_pass_manifold_sh = GPU_shader_create_from_arrays({
+ .vert = (const char *[]){datatoc_common_view_lib_glsl,
+ datatoc_workbench_shadow_vert_glsl,
+ NULL},
+ .geom = (const char *[]){datatoc_workbench_shadow_geom_glsl, NULL},
+ .frag = (const char *[]){shadow_frag, NULL},
+ .defs = (const char *[]){"#define SHADOW_PASS\n", NULL},
+ });
+ e_data.shadow_fail_sh = GPU_shader_create_from_arrays({
+ .vert = (const char *[]){datatoc_common_view_lib_glsl,
+ datatoc_workbench_shadow_vert_glsl,
+ NULL},
+ .geom = (const char *[]){datatoc_workbench_shadow_geom_glsl, NULL},
+ .frag = (const char *[]){shadow_frag, NULL},
+ .defs = (const char *[]){"#define SHADOW_FAIL\n"
+ "#define DOUBLE_MANIFOLD\n",
+ NULL},
+ });
+ e_data.shadow_fail_manifold_sh = GPU_shader_create_from_arrays({
+ .vert = (const char *[]){datatoc_common_view_lib_glsl,
+ datatoc_workbench_shadow_vert_glsl,
+ NULL},
+ .geom = (const char *[]){datatoc_workbench_shadow_geom_glsl, NULL},
+ .frag = (const char *[]){shadow_frag, NULL},
+ .defs = (const char *[]){"#define SHADOW_FAIL\n", NULL},
+ });
+ e_data.shadow_caps_sh = GPU_shader_create_from_arrays({
+ .vert = (const char *[]){datatoc_common_view_lib_glsl,
+ datatoc_workbench_shadow_vert_glsl,
+ NULL},
+ .geom = (const char *[]){datatoc_workbench_shadow_caps_geom_glsl, NULL},
+ .frag = (const char *[]){shadow_frag, NULL},
+ .defs = (const char *[]){"#define SHADOW_FAIL\n"
+ "#define DOUBLE_MANIFOLD\n",
+ NULL},
+ });
+ e_data.shadow_caps_manifold_sh = GPU_shader_create_from_arrays({
+ .vert = (const char *[]){datatoc_common_view_lib_glsl,
+ datatoc_workbench_shadow_vert_glsl,
+ NULL},
+ .geom = (const char *[]){datatoc_workbench_shadow_caps_geom_glsl, NULL},
+ .frag = (const char *[]){shadow_frag, NULL},
+ .defs = (const char *[]){"#define SHADOW_FAIL\n", NULL},
+ });
e_data.ghost_resolve_sh = DRW_shader_create_fullscreen(
datatoc_workbench_ghost_resolve_frag_glsl, NULL);
@@ -549,7 +579,7 @@ void workbench_deferred_engine_init(WORKBENCH_Data *vedata)
DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_ALWAYS);
grp = DRW_shgroup_create(e_data.ghost_resolve_sh, psl->ghost_resolve_pass);
DRW_shgroup_uniform_texture_ref(grp, "depthBuffer", &e_data.ghost_depth_tx);
- DRW_shgroup_call_add(grp, DRW_cache_fullscreen_quad_get(), NULL);
+ DRW_shgroup_call(grp, DRW_cache_fullscreen_quad_get(), NULL);
}
{
@@ -583,7 +613,7 @@ void workbench_deferred_engine_init(WORKBENCH_Data *vedata)
DRW_shgroup_uniform_vec2(grp, "curvature_settings", &wpd->world_data.curvature_ridge, 1);
}
- DRW_shgroup_call_add(grp, DRW_cache_fullscreen_quad_get(), NULL);
+ DRW_shgroup_call(grp, DRW_cache_fullscreen_quad_get(), NULL);
}
}
@@ -694,13 +724,13 @@ void workbench_deferred_cache_init(WORKBENCH_Data *vedata)
if (OBJECT_OUTLINE_ENABLED(wpd)) {
DRW_shgroup_uniform_texture_ref(grp, "objectId", &e_data.object_id_tx);
}
- DRW_shgroup_call_add(grp, DRW_cache_fullscreen_quad_get(), NULL);
+ DRW_shgroup_call(grp, DRW_cache_fullscreen_quad_get(), NULL);
if (draw_ctx->rv3d && (draw_ctx->rv3d->rflag & RV3D_CLIPPING) && draw_ctx->rv3d->clipbb) {
GPUShader *shader = GPU_shader_get_builtin_shader(GPU_SHADER_3D_UNIFORM_COLOR_BACKGROUND);
grp = DRW_shgroup_create(shader, psl->background_pass);
wpd->world_clip_planes_batch = DRW_draw_background_clipping_batch_from_rv3d(draw_ctx->rv3d);
- DRW_shgroup_call_add(grp, wpd->world_clip_planes_batch, NULL);
+ DRW_shgroup_call(grp, wpd->world_clip_planes_batch, NULL);
DRW_shgroup_uniform_vec4(grp, "color", &wpd->world_clip_planes_color[0], 1);
}
}
@@ -720,7 +750,7 @@ void workbench_deferred_cache_init(WORKBENCH_Data *vedata)
DRW_shgroup_uniform_float(grp, "shadowMultiplier", &wpd->shadow_multiplier, 1);
DRW_shgroup_uniform_float_copy(grp, "shadowShift", scene->display.shadow_shift);
DRW_shgroup_uniform_float_copy(grp, "shadowFocus", wpd->shadow_focus);
- DRW_shgroup_call_add(grp, DRW_cache_fullscreen_quad_get(), NULL);
+ DRW_shgroup_call(grp, DRW_cache_fullscreen_quad_get(), NULL);
/* Stencil Shadow passes. */
#ifdef DEBUG_SHADOW_VOLUME
@@ -765,7 +795,7 @@ void workbench_deferred_cache_init(WORKBENCH_Data *vedata)
DRW_shgroup_uniform_float(grp, "shadowMultiplier", &wpd->shadow_multiplier, 1);
DRW_shgroup_uniform_float_copy(grp, "shadowShift", scene->display.shadow_shift);
DRW_shgroup_uniform_float_copy(grp, "shadowFocus", wpd->shadow_focus);
- DRW_shgroup_call_add(grp, DRW_cache_fullscreen_quad_get(), NULL);
+ DRW_shgroup_call(grp, DRW_cache_fullscreen_quad_get(), NULL);
#endif
}
else {
@@ -773,7 +803,7 @@ void workbench_deferred_cache_init(WORKBENCH_Data *vedata)
DRW_STATE_WRITE_COLOR | DRW_STATE_DEPTH_GREATER);
grp = DRW_shgroup_create(wpd->composite_sh, psl->composite_pass);
workbench_composite_uniforms(wpd, grp);
- DRW_shgroup_call_add(grp, DRW_cache_fullscreen_quad_get(), NULL);
+ DRW_shgroup_call(grp, DRW_cache_fullscreen_quad_get(), NULL);
}
}
@@ -807,7 +837,7 @@ void workbench_deferred_cache_init(WORKBENCH_Data *vedata)
DRW_shgroup_uniform_texture_ref(grp, "transparentAccum", &e_data.oit_accum_tx);
DRW_shgroup_uniform_texture_ref(grp, "transparentRevealage", &e_data.oit_revealage_tx);
DRW_shgroup_uniform_vec2(grp, "invertedViewportSize", DRW_viewport_invert_size_get(), 1);
- DRW_shgroup_call_add(grp, DRW_cache_fullscreen_quad_get(), NULL);
+ DRW_shgroup_call(grp, DRW_cache_fullscreen_quad_get(), NULL);
}
}
}
@@ -935,13 +965,13 @@ void workbench_deferred_solid_cache_populate(WORKBENCH_Data *vedata, Object *ob)
WORKBENCH_MaterialData *material;
if (ELEM(ob->type, OB_MESH, OB_CURVE, OB_SURF, OB_FONT, OB_MBALL)) {
const bool is_active = (ob == draw_ctx->obact);
- const bool is_sculpt_mode = (ob->sculpt != NULL);
+ const bool is_sculpt_mode = DRW_object_use_pbvh_drawing(ob);
const bool use_hide = is_active && DRW_object_use_hide_faces(ob);
- const int materials_len = MAX2(1, (is_sculpt_mode ? 1 : ob->totcol));
+ const int materials_len = MAX2(1, ob->totcol);
const Mesh *me = (ob->type == OB_MESH) ? ob->data : NULL;
bool has_transp_mat = false;
- if (!is_sculpt_mode && me && me->mloopuv && TEXTURE_DRAWING_ENABLED(wpd)) {
+ if (!is_sculpt_mode && TEXTURE_DRAWING_ENABLED(wpd) && me && me->mloopuv) {
/* Draw textured */
struct GPUBatch **geom_array = DRW_cache_mesh_surface_texpaint_get(ob);
for (int i = 0; i < materials_len; i++) {
@@ -961,7 +991,7 @@ void workbench_deferred_solid_cache_populate(WORKBENCH_Data *vedata, Object *ob)
material = get_or_create_material_data(
vedata, ob, mat, image, iuser, color_type, interp);
}
- DRW_shgroup_call_object_add(material->shgrp, geom_array[i], ob);
+ DRW_shgroup_call_object(material->shgrp, geom_array[i], ob);
}
}
}
@@ -983,8 +1013,10 @@ void workbench_deferred_solid_cache_populate(WORKBENCH_Data *vedata, Object *ob)
/* Draw solid color */
material = get_or_create_material_data(vedata, ob, NULL, NULL, NULL, color_type, 0);
}
+
if (is_sculpt_mode) {
- DRW_shgroup_call_sculpt_add(material->shgrp, ob, ob->obmat);
+ bool use_vcol = (color_type == V3D_SHADING_VERTEX_COLOR);
+ DRW_shgroup_call_sculpt(material->shgrp, ob, false, false, use_vcol);
}
else {
struct GPUBatch *geom;
@@ -996,18 +1028,31 @@ void workbench_deferred_solid_cache_populate(WORKBENCH_Data *vedata, Object *ob)
}
if (geom) {
- DRW_shgroup_call_object_add(material->shgrp, geom, ob);
+ DRW_shgroup_call_object(material->shgrp, geom, ob);
}
}
}
else {
/* Draw material color */
if (is_sculpt_mode) {
- /* Multiple materials are not supported in sculpt mode yet. */
- Material *mat = give_current_material(ob, 1);
- material = get_or_create_material_data(
- vedata, ob, mat, NULL, NULL, V3D_SHADING_MATERIAL_COLOR, 0);
- DRW_shgroup_call_sculpt_add(material->shgrp, ob, ob->obmat);
+ struct DRWShadingGroup **shgrps = BLI_array_alloca(shgrps, materials_len);
+
+ for (int i = 0; i < materials_len; ++i) {
+ struct Material *mat = give_current_material(ob, i + 1);
+ if (mat != NULL && mat->a < 1.0f) {
+ /* Hack */
+ wpd->shading.xray_alpha = mat->a;
+ material = workbench_forward_get_or_create_material_data(
+ vedata, ob, mat, NULL, NULL, V3D_SHADING_MATERIAL_COLOR, 0, is_sculpt_mode);
+ has_transp_mat = true;
+ }
+ else {
+ material = get_or_create_material_data(
+ vedata, ob, mat, NULL, NULL, V3D_SHADING_MATERIAL_COLOR, 0);
+ }
+ shgrps[i] = material->shgrp;
+ }
+ DRW_shgroup_call_sculpt_with_materials(shgrps, ob, false);
}
else {
struct GPUBatch **geoms;
@@ -1030,7 +1075,7 @@ void workbench_deferred_solid_cache_populate(WORKBENCH_Data *vedata, Object *ob)
material = get_or_create_material_data(
vedata, ob, mat, NULL, NULL, V3D_SHADING_MATERIAL_COLOR, 0);
}
- DRW_shgroup_call_object_add(material->shgrp, geoms[i], ob);
+ DRW_shgroup_call_object(material->shgrp, geoms[i], ob);
}
}
}
@@ -1044,7 +1089,7 @@ void workbench_deferred_solid_cache_populate(WORKBENCH_Data *vedata, Object *ob)
/* Currently unsupported in sculpt mode. We could revert to the slow
* method in this case but I'm not sure if it's a good idea given that
* sculpted meshes are heavy to begin with. */
- // DRW_shgroup_call_sculpt_add(wpd->shadow_shgrp, ob, ob->obmat);
+ // DRW_shgroup_call_sculpt(wpd->shadow_shgrp, ob, ob->obmat);
}
else {
WORKBENCH_ObjectData *engine_object_data = (WORKBENCH_ObjectData *)DRW_drawdata_ensure(
@@ -1056,7 +1101,6 @@ void workbench_deferred_solid_cache_populate(WORKBENCH_Data *vedata, Object *ob)
if (studiolight_object_cast_visible_shadow(wpd, ob, engine_object_data)) {
- invert_m4_m4(ob->imat, ob->obmat);
mul_v3_mat3_m4v3(
engine_object_data->shadow_dir, ob->imat, e_data.display.light_direction);
@@ -1074,7 +1118,7 @@ void workbench_deferred_solid_cache_populate(WORKBENCH_Data *vedata, Object *ob)
}
DRW_shgroup_uniform_vec3(grp, "lightDirection", engine_object_data->shadow_dir, 1);
DRW_shgroup_uniform_float_copy(grp, "lightDistance", 1e5f);
- DRW_shgroup_call_add(grp, geom_shadow, ob->obmat);
+ DRW_shgroup_call(grp, geom_shadow, ob->obmat);
#ifdef DEBUG_SHADOW_VOLUME
DRW_debug_bbox(&engine_object_data->shadow_bbox, (float[4]){1.0f, 0.0f, 0.0f, 1.0f});
#endif
@@ -1096,7 +1140,7 @@ void workbench_deferred_solid_cache_populate(WORKBENCH_Data *vedata, Object *ob)
}
DRW_shgroup_uniform_vec3(grp, "lightDirection", engine_object_data->shadow_dir, 1);
DRW_shgroup_uniform_float_copy(grp, "lightDistance", extrude_distance);
- DRW_shgroup_call_add(grp, DRW_cache_object_surface_get(ob), ob->obmat);
+ DRW_shgroup_call(grp, DRW_cache_object_surface_get(ob), ob->obmat);
}
if (is_manifold) {
@@ -1108,7 +1152,7 @@ void workbench_deferred_solid_cache_populate(WORKBENCH_Data *vedata, Object *ob)
}
DRW_shgroup_uniform_vec3(grp, "lightDirection", engine_object_data->shadow_dir, 1);
DRW_shgroup_uniform_float_copy(grp, "lightDistance", extrude_distance);
- DRW_shgroup_call_add(grp, geom_shadow, ob->obmat);
+ DRW_shgroup_call(grp, geom_shadow, ob->obmat);
#ifdef DEBUG_SHADOW_VOLUME
DRW_debug_bbox(&engine_object_data->shadow_bbox, (float[4]){0.0f, 1.0f, 0.0f, 1.0f});
#endif
@@ -1156,7 +1200,7 @@ void workbench_deferred_draw_scene(WORKBENCH_Data *vedata)
WORKBENCH_PrivateData *wpd = stl->g_data;
DefaultFramebufferList *dfbl = DRW_viewport_framebuffer_list_get();
- if (TAA_ENABLED(wpd)) {
+ if (workbench_is_taa_enabled(wpd)) {
workbench_taa_draw_scene_start(vedata);
}
diff --git a/source/blender/draw/engines/workbench/workbench_effect_aa.c b/source/blender/draw/engines/workbench/workbench_effect_aa.c
index a80f6ce338b..965f5a5ca4f 100644
--- a/source/blender/draw/engines/workbench/workbench_effect_aa.c
+++ b/source/blender/draw/engines/workbench/workbench_effect_aa.c
@@ -40,15 +40,16 @@ void workbench_aa_create_pass(WORKBENCH_Data *vedata, GPUTexture **tx)
wpd->is_playback = false;
}
- if (TAA_ENABLED(wpd)) {
+ if (workbench_is_taa_enabled(wpd)) {
psl->effect_aa_pass = workbench_taa_create_pass(vedata, tx);
}
- else if (FXAA_ENABLED(wpd)) {
+ else if (workbench_is_fxaa_enabled(wpd)) {
psl->effect_aa_pass = workbench_fxaa_create_pass(tx);
effect_info->jitter_index = 0;
}
else {
psl->effect_aa_pass = NULL;
+ effect_info->jitter_index = 0;
}
}
@@ -73,13 +74,13 @@ void workbench_aa_draw_pass(WORKBENCH_Data *vedata, GPUTexture *tx)
WORKBENCH_EffectInfo *effect_info = stl->effects;
DefaultFramebufferList *dfbl = DRW_viewport_framebuffer_list_get();
- if (FXAA_ENABLED(wpd)) {
+ if (workbench_is_fxaa_enabled(wpd)) {
GPU_framebuffer_bind(fbl->effect_fb);
workspace_aa_draw_transform(tx, wpd);
GPU_framebuffer_bind(dfbl->color_only_fb);
DRW_draw_pass(psl->effect_aa_pass);
}
- else if (TAA_ENABLED(wpd)) {
+ else if (workbench_is_taa_enabled(wpd)) {
/*
* when drawing the first TAA frame, we transform directly to the
* color_only_fb as the TAA shader is just performing a direct copy.
diff --git a/source/blender/draw/engines/workbench/workbench_effect_dof.c b/source/blender/draw/engines/workbench/workbench_effect_dof.c
index 3dea99a76cf..e24536759db 100644
--- a/source/blender/draw/engines/workbench/workbench_effect_dof.c
+++ b/source/blender/draw/engines/workbench/workbench_effect_dof.c
@@ -136,7 +136,9 @@ void workbench_dof_engine_init(WORKBENCH_Data *vedata, Object *camera)
WORKBENCH_PrivateData *wpd = stl->g_data;
WORKBENCH_FramebufferList *fbl = vedata->fbl;
- if ((wpd->shading.flag & V3D_SHADING_DEPTH_OF_FIELD) == 0 || (camera == NULL)) {
+ Camera *cam = camera != NULL ? camera->data : NULL;
+ if ((wpd->shading.flag & V3D_SHADING_DEPTH_OF_FIELD) == 0 || (cam == NULL) ||
+ ((cam->dof.flag & CAM_DOF_ENABLED) == 0)) {
wpd->dof_enabled = false;
return;
}
@@ -229,26 +231,17 @@ 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;
- Camera *cam = (Camera *)camera->data;
/* Parameters */
/* TODO UI Options */
- float fstop = cam->gpu_dof.fstop;
+ float fstop = cam->dof.aperture_fstop;
float sensor = BKE_camera_sensor_size(cam->sensor_fit, cam->sensor_x, cam->sensor_y);
float focus_dist = BKE_camera_object_dof_distance(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;
@@ -265,9 +258,9 @@ void workbench_dof_engine_init(WORKBENCH_Data *vedata, Object *camera)
wpd->dof_near_far[0] = -cam->clip_start;
wpd->dof_near_far[1] = -cam->clip_end;
- float blades = cam->gpu_dof.num_blades;
- float rotation = cam->gpu_dof.rotation;
- float ratio = 1.0f / cam->gpu_dof.ratio;
+ float blades = cam->dof.aperture_blades;
+ float rotation = cam->dof.aperture_rotation;
+ float ratio = 1.0f / cam->dof.aperture_ratio;
if (wpd->dof_ubo == NULL || blades != wpd->dof_blades || rotation != wpd->dof_rotation ||
ratio != wpd->dof_ratio) {
@@ -314,37 +307,37 @@ void workbench_dof_create_pass(WORKBENCH_Data *vedata,
DRW_shgroup_uniform_vec2(grp, "invertedViewportSize", DRW_viewport_invert_size_get(), 1);
DRW_shgroup_uniform_vec3(grp, "dofParams", &wpd->dof_aperturesize, 1);
DRW_shgroup_uniform_vec2(grp, "nearFar", wpd->dof_near_far, 1);
- DRW_shgroup_call_add(grp, quad, NULL);
+ DRW_shgroup_call(grp, quad, NULL);
}
{
DRWShadingGroup *grp = DRW_shgroup_create(e_data.effect_dof_downsample_sh, psl->dof_down2_ps);
DRW_shgroup_uniform_texture(grp, "sceneColorTex", txl->dof_source_tx);
DRW_shgroup_uniform_texture(grp, "inputCocTex", txl->coc_halfres_tx);
- DRW_shgroup_call_add(grp, quad, NULL);
+ DRW_shgroup_call(grp, quad, NULL);
}
#if 0
{
DRWShadingGroup *grp = DRW_shgroup_create(e_data.effect_dof_flatten_h_sh,
psl->dof_flatten_h_ps);
DRW_shgroup_uniform_texture(grp, "inputCocTex", txl->coc_halfres_tx);
- DRW_shgroup_call_add(grp, quad, NULL);
+ DRW_shgroup_call(grp, quad, NULL);
}
{
DRWShadingGroup *grp = DRW_shgroup_create(e_data.effect_dof_flatten_v_sh,
psl->dof_flatten_v_ps);
DRW_shgroup_uniform_texture(grp, "inputCocTex", wpd->coc_temp_tx);
- DRW_shgroup_call_add(grp, quad, NULL);
+ DRW_shgroup_call(grp, quad, NULL);
}
{
DRWShadingGroup *grp = DRW_shgroup_create(e_data.effect_dof_dilate_v_sh, psl->dof_dilate_v_ps);
DRW_shgroup_uniform_texture(grp, "inputCocTex", wpd->coc_tiles_tx[0]);
- DRW_shgroup_call_add(grp, quad, NULL);
+ DRW_shgroup_call(grp, quad, NULL);
}
{
DRWShadingGroup *grp = DRW_shgroup_create(e_data.effect_dof_dilate_h_sh, psl->dof_dilate_h_ps);
DRW_shgroup_uniform_texture(grp, "inputCocTex", wpd->coc_tiles_tx[1]);
- DRW_shgroup_call_add(grp, quad, NULL);
+ DRW_shgroup_call(grp, quad, NULL);
}
#endif
{
@@ -357,14 +350,14 @@ void workbench_dof_create_pass(WORKBENCH_Data *vedata,
DRW_shgroup_uniform_texture(grp, "halfResColorTex", txl->dof_source_tx);
DRW_shgroup_uniform_vec2(grp, "invertedViewportSize", DRW_viewport_invert_size_get(), 1);
DRW_shgroup_uniform_float_copy(grp, "noiseOffset", offset);
- DRW_shgroup_call_add(grp, quad, NULL);
+ DRW_shgroup_call(grp, quad, NULL);
}
{
DRWShadingGroup *grp = DRW_shgroup_create(e_data.effect_dof_blur2_sh, psl->dof_blur2_ps);
DRW_shgroup_uniform_texture(grp, "inputCocTex", txl->coc_halfres_tx);
DRW_shgroup_uniform_texture(grp, "blurTex", wpd->dof_blur_tx);
DRW_shgroup_uniform_vec2(grp, "invertedViewportSize", DRW_viewport_invert_size_get(), 1);
- DRW_shgroup_call_add(grp, quad, NULL);
+ DRW_shgroup_call(grp, quad, NULL);
}
{
DRWShadingGroup *grp = DRW_shgroup_create(e_data.effect_dof_resolve_sh, psl->dof_resolve_ps);
@@ -373,7 +366,7 @@ void workbench_dof_create_pass(WORKBENCH_Data *vedata,
DRW_shgroup_uniform_vec2(grp, "invertedViewportSize", DRW_viewport_invert_size_get(), 1);
DRW_shgroup_uniform_vec3(grp, "dofParams", &wpd->dof_aperturesize, 1);
DRW_shgroup_uniform_vec2(grp, "nearFar", wpd->dof_near_far, 1);
- DRW_shgroup_call_add(grp, quad, NULL);
+ DRW_shgroup_call(grp, quad, NULL);
}
}
diff --git a/source/blender/draw/engines/workbench/workbench_effect_fxaa.c b/source/blender/draw/engines/workbench/workbench_effect_fxaa.c
index 47355f324a8..6e3bf1658ab 100644
--- a/source/blender/draw/engines/workbench/workbench_effect_fxaa.c
+++ b/source/blender/draw/engines/workbench/workbench_effect_fxaa.c
@@ -49,7 +49,7 @@ DRWPass *workbench_fxaa_create_pass(GPUTexture **color_buffer_tx)
DRWShadingGroup *grp = DRW_shgroup_create(e_data.effect_fxaa_sh, pass);
DRW_shgroup_uniform_texture_ref(grp, "colorBuffer", color_buffer_tx);
DRW_shgroup_uniform_vec2(grp, "invertedViewportSize", DRW_viewport_invert_size_get(), 1);
- DRW_shgroup_call_add(grp, DRW_cache_fullscreen_quad_get(), NULL);
+ DRW_shgroup_call(grp, DRW_cache_fullscreen_quad_get(), NULL);
return pass;
}
diff --git a/source/blender/draw/engines/workbench/workbench_effect_taa.c b/source/blender/draw/engines/workbench/workbench_effect_taa.c
index 0435a804fab..7fd68babc13 100644
--- a/source/blender/draw/engines/workbench/workbench_effect_taa.c
+++ b/source/blender/draw/engines/workbench/workbench_effect_taa.c
@@ -90,26 +90,36 @@ int workbench_taa_calculate_num_iterations(WORKBENCH_Data *vedata)
{
WORKBENCH_StorageList *stl = vedata->stl;
WORKBENCH_PrivateData *wpd = stl->g_data;
- int result = 1;
- if (TAA_ENABLED(wpd)) {
+ const Scene *scene = DRW_context_state_get()->scene;
+ int result;
+ if (workbench_is_taa_enabled(wpd)) {
if (DRW_state_is_image_render()) {
- const Scene *scene = DRW_context_state_get()->scene;
- result = (scene->r.mode & R_OSA) ? scene->r.osa : 1;
- }
- else if (IN_RANGE_INCL(wpd->preferences->gpu_viewport_quality,
- GPU_VIEWPORT_QUALITY_TAA8,
- GPU_VIEWPORT_QUALITY_TAA16)) {
- result = 8;
- }
- else if (IN_RANGE_INCL(wpd->preferences->gpu_viewport_quality,
- GPU_VIEWPORT_QUALITY_TAA16,
- GPU_VIEWPORT_QUALITY_TAA32)) {
- result = 16;
+ const DRWContextState *draw_ctx = DRW_context_state_get();
+ if (draw_ctx->v3d) {
+ result = scene->display.viewport_aa;
+ }
+ else {
+ result = scene->display.render_aa;
+ }
}
else {
- result = 32;
+ result = wpd->preferences->viewport_aa;
}
}
+ else {
+ /* when no TAA is disabled return 1 to render a single sample
+ * see `workbench_render.c` */
+ result = 1;
+ }
+ return result;
+}
+
+int workbench_num_viewport_rendering_iterations(WORKBENCH_Data *UNUSED(vedata))
+{
+ const DRWContextState *draw_ctx = DRW_context_state_get();
+ const Scene *scene = draw_ctx->scene;
+ int result = DRW_state_is_image_render() ? scene->display.viewport_aa : 1;
+ result = MAX2(result, 1);
return result;
}
@@ -125,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) {
@@ -138,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;
}
}
@@ -191,7 +201,7 @@ DRWPass *workbench_taa_create_pass(WORKBENCH_Data *vedata, GPUTexture **color_bu
DRW_shgroup_uniform_texture_ref(grp, "colorBuffer", color_buffer_tx);
DRW_shgroup_uniform_texture_ref(grp, "historyBuffer", &txl->history_buffer_tx);
DRW_shgroup_uniform_float(grp, "mixFactor", &effect_info->taa_mix_factor, 1);
- DRW_shgroup_call_add(grp, DRW_cache_fullscreen_quad_get(), NULL);
+ DRW_shgroup_call(grp, DRW_cache_fullscreen_quad_get(), NULL);
/*
* Set the offset for the cavity shader so every iteration different
@@ -207,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) {
@@ -231,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
@@ -286,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 00590940ac3..f12902b6801 100644
--- a/source/blender/draw/engines/workbench/workbench_forward.c
+++ b/source/blender/draw/engines/workbench/workbench_forward.c
@@ -68,6 +68,7 @@ static struct {
/* Shaders */
extern char datatoc_common_hair_lib_glsl[];
+extern char datatoc_common_view_lib_glsl[];
extern char datatoc_workbench_forward_composite_frag_glsl[];
extern char datatoc_workbench_forward_depth_frag_glsl[];
@@ -88,6 +89,7 @@ static char *workbench_build_forward_vert(bool is_hair)
if (is_hair) {
BLI_dynstr_append(ds, datatoc_common_hair_lib_glsl);
}
+ BLI_dynstr_append(ds, datatoc_common_view_lib_glsl);
BLI_dynstr_append(ds, datatoc_workbench_prepass_vert_glsl);
char *str = BLI_dynstr_get_cstring(ds);
@@ -99,6 +101,7 @@ static char *workbench_build_forward_transparent_accum_frag(void)
{
DynStr *ds = BLI_dynstr_new();
+ BLI_dynstr_append(ds, datatoc_common_view_lib_glsl);
BLI_dynstr_append(ds, datatoc_workbench_data_lib_glsl);
BLI_dynstr_append(ds, datatoc_workbench_common_lib_glsl);
BLI_dynstr_append(ds, datatoc_workbench_world_light_lib_glsl);
@@ -199,8 +202,7 @@ WORKBENCH_MaterialData *workbench_forward_get_or_create_material_data(WORKBENCH_
V3D_SHADING_TEXTURE_COLOR) {
material->shgrp_object_outline = DRW_shgroup_create(sh_data->object_outline_texture_sh,
psl->object_outline_pass);
- GPUTexture *tex = GPU_texture_from_blender(
- material->ima, material->iuser, GL_TEXTURE_2D, false);
+ GPUTexture *tex = GPU_texture_from_blender(material->ima, material->iuser, GL_TEXTURE_2D);
DRW_shgroup_uniform_texture(material->shgrp_object_outline, "image", tex);
}
else {
@@ -399,7 +401,7 @@ void workbench_forward_engine_init(WORKBENCH_Data *vedata)
DRW_shgroup_uniform_texture_ref(grp, "transparentRevealage", &e_data.transparent_revealage_tx);
DRW_shgroup_uniform_block(grp, "world_block", wpd->world_ubo);
DRW_shgroup_uniform_vec2(grp, "invertedViewportSize", DRW_viewport_invert_size_get(), 1);
- DRW_shgroup_call_add(grp, DRW_cache_fullscreen_quad_get(), NULL);
+ DRW_shgroup_call(grp, DRW_cache_fullscreen_quad_get(), NULL);
}
/* TODO(campbell): displays but masks geometry,
@@ -411,7 +413,7 @@ void workbench_forward_engine_init(WORKBENCH_Data *vedata)
GPUShader *shader = GPU_shader_get_builtin_shader(GPU_SHADER_3D_UNIFORM_COLOR_BACKGROUND);
grp = DRW_shgroup_create(shader, psl->background_pass);
wpd->world_clip_planes_batch = DRW_draw_background_clipping_batch_from_rv3d(draw_ctx->rv3d);
- DRW_shgroup_call_add(grp, wpd->world_clip_planes_batch, NULL);
+ DRW_shgroup_call(grp, wpd->world_clip_planes_batch, NULL);
DRW_shgroup_uniform_vec4(grp, "color", &wpd->world_clip_planes_color[0], 1);
}
@@ -441,7 +443,7 @@ void workbench_forward_engine_init(WORKBENCH_Data *vedata)
int state = DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_ALWAYS;
psl->checker_depth_pass = DRW_pass_create("Checker Depth", state);
grp = DRW_shgroup_create(e_data.checker_depth_sh, psl->checker_depth_pass);
- DRW_shgroup_call_add(grp, DRW_cache_fullscreen_quad_get(), NULL);
+ DRW_shgroup_call(grp, DRW_cache_fullscreen_quad_get(), NULL);
DRW_shgroup_uniform_float_copy(grp, "threshold", blend_threshold);
DRW_shgroup_uniform_float_copy(grp, "offset", noise_offset);
}
@@ -565,70 +567,78 @@ void workbench_forward_cache_populate(WORKBENCH_Data *vedata, Object *ob)
WORKBENCH_MaterialData *material;
if (ELEM(ob->type, OB_MESH, OB_CURVE, OB_SURF, OB_FONT, OB_MBALL)) {
- const bool is_sculpt_mode = (ob->sculpt != NULL);
- bool is_drawn = false;
-
- if (!is_sculpt_mode && TEXTURE_DRAWING_ENABLED(wpd) && ELEM(ob->type, OB_MESH)) {
- const Mesh *me = ob->data;
- if (me->mloopuv) {
- const int materials_len = MAX2(1, (is_sculpt_mode ? 1 : ob->totcol));
- struct GPUBatch **geom_array = DRW_cache_mesh_surface_texpaint_get(ob);
- for (int i = 0; i < materials_len; i++) {
- Material *mat;
- Image *image;
- ImageUser *iuser;
- int interp;
- 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);
- material = workbench_forward_get_or_create_material_data(
- vedata, ob, mat, image, iuser, color_type, interp, is_sculpt_mode);
- DRW_shgroup_call_object_add(material->shgrp_object_outline, geom_array[i], ob);
- DRW_shgroup_call_object_add(material->shgrp, geom_array[i], ob);
- }
- is_drawn = true;
+ const bool is_sculpt_mode = DRW_object_use_pbvh_drawing(ob);
+ const int materials_len = MAX2(1, ob->totcol);
+ const Mesh *me = (ob->type == OB_MESH) ? ob->data : NULL;
+
+ if (!is_sculpt_mode && TEXTURE_DRAWING_ENABLED(wpd) && me && me->mloopuv) {
+ struct GPUBatch **geom_array = DRW_cache_mesh_surface_texpaint_get(ob);
+ for (int i = 0; i < materials_len; i++) {
+ Material *mat;
+ Image *image;
+ ImageUser *iuser;
+ int interp;
+ 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);
+ material = workbench_forward_get_or_create_material_data(
+ vedata, ob, mat, image, iuser, color_type, interp, is_sculpt_mode);
+ DRW_shgroup_call_object(material->shgrp_object_outline, geom_array[i], ob);
+ DRW_shgroup_call_object(material->shgrp, geom_array[i], ob);
}
}
-
- /* Fallback from not drawn OB_TEXTURE mode or just OB_SOLID mode */
- if (!is_drawn) {
- if (ELEM(wpd->shading.color_type,
- V3D_SHADING_SINGLE_COLOR,
- V3D_SHADING_OBJECT_COLOR,
- V3D_SHADING_RANDOM_COLOR,
- V3D_SHADING_VERTEX_COLOR)) {
- /* No material split needed */
- int color_type = workbench_material_determine_color_type(wpd, NULL, ob, is_sculpt_mode);
-
- struct GPUBatch *geom;
- if (color_type == V3D_SHADING_VERTEX_COLOR) {
- geom = DRW_cache_mesh_surface_vertpaint_get(ob);
- }
- else {
- geom = DRW_cache_object_surface_get(ob);
+ else if (ELEM(wpd->shading.color_type,
+ V3D_SHADING_SINGLE_COLOR,
+ V3D_SHADING_OBJECT_COLOR,
+ V3D_SHADING_RANDOM_COLOR,
+ V3D_SHADING_VERTEX_COLOR)) {
+ /* No material split needed */
+ int color_type = workbench_material_determine_color_type(wpd, NULL, ob, is_sculpt_mode);
+
+ if (is_sculpt_mode) {
+ material = workbench_forward_get_or_create_material_data(
+ vedata, ob, NULL, NULL, NULL, color_type, 0, is_sculpt_mode);
+ bool use_vcol = (color_type == V3D_SHADING_VERTEX_COLOR);
+ /* TODO(fclem) make this call optional */
+ DRW_shgroup_call_sculpt(material->shgrp_object_outline, ob, false, false, false);
+ if (!is_wire) {
+ DRW_shgroup_call_sculpt(material->shgrp, ob, false, false, use_vcol);
}
+ }
+ else {
+ struct GPUBatch *geom = (color_type == V3D_SHADING_VERTEX_COLOR) ?
+ DRW_cache_mesh_surface_vertpaint_get(ob) :
+ DRW_cache_object_surface_get(ob);
if (geom) {
material = workbench_forward_get_or_create_material_data(
vedata, ob, NULL, NULL, NULL, color_type, 0, is_sculpt_mode);
- if (is_sculpt_mode) {
- DRW_shgroup_call_sculpt_add(material->shgrp_object_outline, ob, ob->obmat);
- if (!is_wire) {
- DRW_shgroup_call_sculpt_add(material->shgrp, ob, ob->obmat);
- }
- }
- else {
- DRW_shgroup_call_object_add(material->shgrp_object_outline, geom, ob);
- if (!is_wire) {
- DRW_shgroup_call_object_add(material->shgrp, geom, ob);
- }
+ /* TODO(fclem) make this call optional */
+ DRW_shgroup_call_object(material->shgrp_object_outline, geom, ob);
+ if (!is_wire) {
+ DRW_shgroup_call_object(material->shgrp, geom, ob);
}
}
}
+ }
+ else {
+ /* Draw material color */
+ if (is_sculpt_mode) {
+ struct DRWShadingGroup **shgrps = BLI_array_alloca(shgrps, materials_len);
+
+ for (int i = 0; i < materials_len; ++i) {
+ struct Material *mat = give_current_material(ob, i + 1);
+ material = workbench_forward_get_or_create_material_data(
+ vedata, ob, mat, NULL, NULL, V3D_SHADING_MATERIAL_COLOR, 0, is_sculpt_mode);
+ shgrps[i] = material->shgrp;
+ }
+ /* TODO(fclem) make this call optional */
+ DRW_shgroup_call_sculpt(material->shgrp_object_outline, ob, false, false, false);
+ if (!is_wire) {
+ DRW_shgroup_call_sculpt_with_materials(shgrps, ob, false);
+ }
+ }
else {
- const int materials_len = MAX2(1, (is_sculpt_mode ? 1 : ob->totcol));
struct GPUMaterial **gpumat_array = BLI_array_alloca(gpumat_array, materials_len);
- for (int i = 0; i < materials_len; i++) {
- gpumat_array[i] = NULL;
- }
+ memset(gpumat_array, 0, sizeof(*gpumat_array) * materials_len);
struct GPUBatch **mat_geom = DRW_cache_object_surface_material_get(
ob, gpumat_array, materials_len, NULL, NULL, NULL);
@@ -641,17 +651,10 @@ void workbench_forward_cache_populate(WORKBENCH_Data *vedata, Object *ob)
Material *mat = give_current_material(ob, i + 1);
material = workbench_forward_get_or_create_material_data(
vedata, ob, mat, NULL, NULL, V3D_SHADING_MATERIAL_COLOR, 0, is_sculpt_mode);
- if (is_sculpt_mode) {
- DRW_shgroup_call_sculpt_add(material->shgrp_object_outline, ob, ob->obmat);
- if (!is_wire) {
- DRW_shgroup_call_sculpt_add(material->shgrp, ob, ob->obmat);
- }
- }
- else {
- DRW_shgroup_call_object_add(material->shgrp_object_outline, mat_geom[i], ob);
- if (!is_wire) {
- DRW_shgroup_call_object_add(material->shgrp, mat_geom[i], ob);
- }
+ /* TODO(fclem) make this call optional */
+ DRW_shgroup_call_object(material->shgrp_object_outline, mat_geom[i], ob);
+ if (!is_wire) {
+ DRW_shgroup_call_object(material->shgrp, mat_geom[i], ob);
}
}
}
@@ -682,7 +685,7 @@ void workbench_forward_draw_scene(WORKBENCH_Data *vedata)
WORKBENCH_PrivateData *wpd = stl->g_data;
DefaultFramebufferList *dfbl = DRW_viewport_framebuffer_list_get();
- if (TAA_ENABLED(wpd)) {
+ if (workbench_is_taa_enabled(wpd)) {
workbench_taa_draw_scene_start(vedata);
}
diff --git a/source/blender/draw/engines/workbench/workbench_materials.c b/source/blender/draw/engines/workbench/workbench_materials.c
index c403e358d6a..b280b6fd01a 100644
--- a/source/blender/draw/engines/workbench/workbench_materials.c
+++ b/source/blender/draw/engines/workbench/workbench_materials.c
@@ -294,15 +294,8 @@ void workbench_material_shgroup_uniform(WORKBENCH_PrivateData *wpd,
if (workbench_material_determine_color_type(wpd, material->ima, ob, false) ==
V3D_SHADING_TEXTURE_COLOR) {
- ImBuf *ibuf = BKE_image_acquire_ibuf(material->ima, material->iuser, NULL);
- const bool do_color_correction = wpd->use_color_management &&
- (ibuf &&
- (ibuf->colormanage_flag & IMB_COLORMANAGE_IS_DATA) == 0);
- BKE_image_release_ibuf(material->ima, ibuf, NULL);
- GPUTexture *tex = GPU_texture_from_blender(
- material->ima, material->iuser, GL_TEXTURE_2D, false);
+ GPUTexture *tex = GPU_texture_from_blender(material->ima, material->iuser, GL_TEXTURE_2D);
DRW_shgroup_uniform_texture(grp, "image", tex);
- DRW_shgroup_uniform_bool_copy(grp, "imageSrgb", do_color_correction);
DRW_shgroup_uniform_bool_copy(grp, "imageNearest", (interp == SHD_INTERP_CLOSEST));
}
else {
diff --git a/source/blender/draw/engines/workbench/workbench_private.h b/source/blender/draw/engines/workbench/workbench_private.h
index 3cfb1283416..240d06c1e79 100644
--- a/source/blender/draw/engines/workbench/workbench_private.h
+++ b/source/blender/draw/engines/workbench/workbench_private.h
@@ -75,18 +75,7 @@
#define IS_NAVIGATING(wpd) \
((DRW_context_state_get()->rv3d) && (DRW_context_state_get()->rv3d->rflag & RV3D_NAVIGATING))
-#define FXAA_ENABLED(wpd) \
- ((!DRW_state_is_opengl_render()) && \
- (IN_RANGE(wpd->preferences->gpu_viewport_quality, \
- GPU_VIEWPORT_QUALITY_FXAA, \
- GPU_VIEWPORT_QUALITY_TAA8) || \
- ((IS_NAVIGATING(wpd) || wpd->is_playback) && \
- (wpd->preferences->gpu_viewport_quality >= GPU_VIEWPORT_QUALITY_TAA8))))
-#define TAA_ENABLED(wpd) \
- ((DRW_state_is_image_render() && DRW_context_state_get()->scene->r.mode & R_OSA) || \
- (!DRW_state_is_image_render() && \
- wpd->preferences->gpu_viewport_quality >= GPU_VIEWPORT_QUALITY_TAA8 && !IS_NAVIGATING(wpd) && \
- !wpd->is_playback))
+
#define SPECULAR_HIGHLIGHT_ENABLED(wpd) \
(STUDIOLIGHT_ENABLED(wpd) && (wpd->shading.flag & V3D_SHADING_SPECULAR_HIGHLIGHT) && \
(!STUDIOLIGHT_TYPE_MATCAP_ENABLED(wpd)))
@@ -284,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;
@@ -326,6 +313,46 @@ typedef struct WORKBENCH_ObjectData {
int object_id;
} WORKBENCH_ObjectData;
+/* inline helper functions */
+BLI_INLINE bool workbench_is_taa_enabled(WORKBENCH_PrivateData *wpd)
+{
+ if (DRW_state_is_image_render()) {
+ const DRWContextState *draw_ctx = DRW_context_state_get();
+ if (draw_ctx->v3d) {
+ return draw_ctx->scene->display.viewport_aa > SCE_DISPLAY_AA_FXAA;
+ }
+ else {
+ return draw_ctx->scene->display.render_aa > SCE_DISPLAY_AA_FXAA;
+ }
+ }
+ else {
+ return !(IS_NAVIGATING(wpd) || wpd->is_playback) &&
+ wpd->preferences->viewport_aa > SCE_DISPLAY_AA_FXAA;
+ }
+}
+
+BLI_INLINE bool workbench_is_fxaa_enabled(WORKBENCH_PrivateData *wpd)
+{
+ if (DRW_state_is_image_render()) {
+ const DRWContextState *draw_ctx = DRW_context_state_get();
+ if (draw_ctx->v3d) {
+ return draw_ctx->scene->display.viewport_aa == SCE_DISPLAY_AA_FXAA;
+ }
+ else {
+ return draw_ctx->scene->display.render_aa == SCE_DISPLAY_AA_FXAA;
+ }
+ }
+ else {
+ if (wpd->preferences->viewport_aa == SCE_DISPLAY_AA_FXAA) {
+ return true;
+ }
+
+ /* 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;
+ }
+}
+
/* workbench_deferred.c */
void workbench_deferred_engine_init(WORKBENCH_Data *vedata);
void workbench_deferred_engine_free(void);
@@ -375,6 +402,7 @@ void workbench_taa_draw_scene_start(WORKBENCH_Data *vedata);
void workbench_taa_draw_scene_end(WORKBENCH_Data *vedata);
void workbench_taa_view_updated(WORKBENCH_Data *vedata);
int workbench_taa_calculate_num_iterations(WORKBENCH_Data *vedata);
+int workbench_num_viewport_rendering_iterations(WORKBENCH_Data *vedata);
/* workbench_effect_dof.c */
void workbench_dof_engine_init(WORKBENCH_Data *vedata, Object *camera);
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 accc7e91576..2b5fc8c0e47 100644
--- a/source/blender/draw/engines/workbench/workbench_volume.c
+++ b/source/blender/draw/engines/workbench/workbench_volume.c
@@ -53,6 +53,7 @@ static struct {
extern char datatoc_workbench_volume_vert_glsl[];
extern char datatoc_workbench_volume_frag_glsl[];
+extern char datatoc_common_view_lib_glsl[];
static GPUShader *volume_shader_get(bool slice, bool coba, bool cubic)
{
@@ -77,8 +78,11 @@ static GPUShader *volume_shader_get(bool slice, bool coba, bool cubic)
char *defines = BLI_dynstr_get_cstring(ds);
BLI_dynstr_free(ds);
- e_data.volume_sh[id] = DRW_shader_create(
- datatoc_workbench_volume_vert_glsl, NULL, datatoc_workbench_volume_frag_glsl, defines);
+ e_data.volume_sh[id] = DRW_shader_create_with_lib(datatoc_workbench_volume_vert_glsl,
+ NULL,
+ datatoc_workbench_volume_frag_glsl,
+ datatoc_common_view_lib_glsl,
+ defines);
MEM_freeN(defines);
}
@@ -150,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]) :
@@ -207,10 +211,10 @@ void workbench_volume_cache_populate(WORKBENCH_Data *vedata,
DRW_shgroup_uniform_float_copy(grp, "densityScale", 10.0f * sds->display_thickness);
if (use_slice) {
- DRW_shgroup_call_object_add(grp, DRW_cache_quad_get(), ob);
+ DRW_shgroup_call_object(grp, DRW_cache_quad_get(), ob);
}
else {
- DRW_shgroup_call_object_add(grp, DRW_cache_cube_get(), ob);
+ DRW_shgroup_call_object(grp, DRW_cache_cube_get(), ob);
}
BLI_addtail(&wpd->smoke_domains, BLI_genericNodeN(smd));
diff --git a/source/blender/draw/intern/DRW_render.h b/source/blender/draw/intern/DRW_render.h
index 4d8fefbbc06..0f019df9d86 100644
--- a/source/blender/draw/intern/DRW_render.h
+++ b/source/blender/draw/intern/DRW_render.h
@@ -44,6 +44,7 @@
#include "DNA_world_types.h"
#include "GPU_framebuffer.h"
+#include "GPU_primitive.h"
#include "GPU_texture.h"
#include "GPU_shader.h"
@@ -80,9 +81,13 @@ struct rcti;
typedef struct DRWInterface DRWInterface;
typedef struct DRWPass DRWPass;
+typedef struct DRWView DRWView;
typedef struct DRWShadingGroup DRWShadingGroup;
typedef struct DRWUniform DRWUniform;
+/* Opaque type to avoid usage as a DRWCall but it is exactly the same thing. */
+typedef struct DRWCallBuffer DRWCallBuffer;
+
/* TODO Put it somewhere else? */
typedef struct BoundSphere {
float center[3], radius;
@@ -105,7 +110,7 @@ typedef char DRWViewportEmptyList;
/* Use of multisample framebuffers. */
#define MULTISAMPLE_SYNC_ENABLE(dfbl, dtxl) \
{ \
- if (dfbl->multisample_fb != NULL) { \
+ if (dfbl->multisample_fb != NULL && DRW_state_is_fbo()) { \
DRW_stats_query_start("Multisample Blit"); \
GPU_framebuffer_bind(dfbl->multisample_fb); \
/* TODO clear only depth but need to do alpha to coverage for transparencies. */ \
@@ -117,7 +122,7 @@ typedef char DRWViewportEmptyList;
#define MULTISAMPLE_SYNC_DISABLE(dfbl, dtxl) \
{ \
- if (dfbl->multisample_fb != NULL) { \
+ if (dfbl->multisample_fb != NULL && DRW_state_is_fbo()) { \
DRW_stats_query_start("Multisample Resolve"); \
GPU_framebuffer_bind(dfbl->default_fb); \
DRW_multisamples_resolve(dtxl->multisample_depth, dtxl->multisample_color, true); \
@@ -128,7 +133,7 @@ typedef char DRWViewportEmptyList;
#define MULTISAMPLE_SYNC_DISABLE_NO_DEPTH(dfbl, dtxl) \
{ \
- if (dfbl->multisample_fb != NULL) { \
+ if (dfbl->multisample_fb != NULL && DRW_state_is_fbo()) { \
DRW_stats_query_start("Multisample Resolve"); \
GPU_framebuffer_bind(dfbl->default_fb); \
DRW_multisamples_resolve(dtxl->multisample_depth, dtxl->multisample_color, false); \
@@ -309,43 +314,47 @@ void DRW_shader_free(struct GPUShader *shader);
/* Batches */
typedef enum {
+ /** Wrtie mask */
DRW_STATE_WRITE_DEPTH = (1 << 0),
DRW_STATE_WRITE_COLOR = (1 << 1),
- DRW_STATE_DEPTH_ALWAYS = (1 << 2),
- DRW_STATE_DEPTH_LESS = (1 << 3),
- DRW_STATE_DEPTH_LESS_EQUAL = (1 << 4),
- DRW_STATE_DEPTH_EQUAL = (1 << 5),
- DRW_STATE_DEPTH_GREATER = (1 << 6),
- DRW_STATE_DEPTH_GREATER_EQUAL = (1 << 7),
- DRW_STATE_CULL_BACK = (1 << 8),
- DRW_STATE_CULL_FRONT = (1 << 9),
- DRW_STATE_WIRE = (1 << 10),
- DRW_STATE_POINT = (1 << 11),
+ DRW_STATE_WRITE_STENCIL = (1 << 2),
+ DRW_STATE_WRITE_STENCIL_SHADOW_PASS = (1 << 3),
+ DRW_STATE_WRITE_STENCIL_SHADOW_FAIL = (1 << 4),
+
+ /** Depth test */
+ DRW_STATE_DEPTH_ALWAYS = (1 << 5),
+ DRW_STATE_DEPTH_LESS = (1 << 6),
+ DRW_STATE_DEPTH_LESS_EQUAL = (1 << 7),
+ DRW_STATE_DEPTH_EQUAL = (1 << 8),
+ DRW_STATE_DEPTH_GREATER = (1 << 9),
+ DRW_STATE_DEPTH_GREATER_EQUAL = (1 << 10),
+ /** Culling test */
+ DRW_STATE_CULL_BACK = (1 << 11),
+ DRW_STATE_CULL_FRONT = (1 << 12),
+ /** Stencil test */
+ DRW_STATE_STENCIL_EQUAL = (1 << 13),
+ DRW_STATE_STENCIL_NEQUAL = (1 << 14),
+
+ /** Blend state */
+ DRW_STATE_ADDITIVE = (1 << 15),
+ /** Same as additive but let alpha accumulate without premult. */
+ DRW_STATE_ADDITIVE_FULL = (1 << 16),
+ DRW_STATE_BLEND = (1 << 17),
+ /** Use that if color is already premult by alpha. */
+ DRW_STATE_BLEND_PREMUL = (1 << 18),
+ DRW_STATE_BLEND_PREMUL_UNDER = (1 << 19),
+ DRW_STATE_BLEND_OIT = (1 << 20),
+ DRW_STATE_MULTIPLY = (1 << 21),
+
+ 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 << 12),
+ DRW_STATE_OFFSET_POSITIVE = (1 << 25),
/** Polygon offset. Does not work with lines and points. */
- DRW_STATE_OFFSET_NEGATIVE = (1 << 13),
- DRW_STATE_WIRE_WIDE = (1 << 14),
- DRW_STATE_BLEND = (1 << 15),
- DRW_STATE_ADDITIVE = (1 << 16),
- DRW_STATE_MULTIPLY = (1 << 17),
- DRW_STATE_BLEND_PREMUL_UNDER = (1 << 18),
- DRW_STATE_CLIP_PLANES = (1 << 19),
- /** Same as DRW_STATE_ADDITIVE but let alpha accumulate without premult. */
- DRW_STATE_ADDITIVE_FULL = (1 << 20),
- /** Use that if color is already premult by alpha. */
- DRW_STATE_BLEND_PREMUL = (1 << 21),
- DRW_STATE_WIRE_SMOOTH = (1 << 22),
- DRW_STATE_TRANS_FEEDBACK = (1 << 23),
- DRW_STATE_BLEND_OIT = (1 << 24),
- DRW_STATE_FIRST_VERTEX_CONVENTION = (1 << 25),
-
- DRW_STATE_WRITE_STENCIL = (1 << 27),
- DRW_STATE_WRITE_STENCIL_SHADOW_PASS = (1 << 28),
- DRW_STATE_WRITE_STENCIL_SHADOW_FAIL = (1 << 29),
- DRW_STATE_STENCIL_EQUAL = (1 << 30),
- DRW_STATE_STENCIL_NEQUAL = (1 << 31),
+ DRW_STATE_OFFSET_NEGATIVE = (1 << 26),
} DRWState;
+
#define DRW_STATE_DEFAULT \
(DRW_STATE_WRITE_DEPTH | DRW_STATE_WRITE_COLOR | DRW_STATE_DEPTH_LESS_EQUAL)
#define DRW_STATE_RASTERIZER_ENABLED \
@@ -377,97 +386,64 @@ struct GPUVertFormat *DRW_shgroup_instance_format_array(const DRWInstanceAttrFor
DRWShadingGroup *DRW_shgroup_create(struct GPUShader *shader, DRWPass *pass);
DRWShadingGroup *DRW_shgroup_create_sub(DRWShadingGroup *shgroup);
DRWShadingGroup *DRW_shgroup_material_create(struct GPUMaterial *material, DRWPass *pass);
-DRWShadingGroup *DRW_shgroup_material_instance_create(struct GPUMaterial *material,
- DRWPass *pass,
- struct GPUBatch *geom,
- struct Object *ob,
- struct GPUVertFormat *format);
-DRWShadingGroup *DRW_shgroup_material_empty_tri_batch_create(struct GPUMaterial *material,
- DRWPass *pass,
- int size);
-DRWShadingGroup *DRW_shgroup_instance_create(struct GPUShader *shader,
- DRWPass *pass,
- struct GPUBatch *geom,
- struct GPUVertFormat *format);
-DRWShadingGroup *DRW_shgroup_point_batch_create(struct GPUShader *shader, DRWPass *pass);
-DRWShadingGroup *DRW_shgroup_line_batch_create_with_format(struct GPUShader *shader,
- DRWPass *pass,
- struct GPUVertFormat *format);
-DRWShadingGroup *DRW_shgroup_line_batch_create(struct GPUShader *shader, DRWPass *pass);
-DRWShadingGroup *DRW_shgroup_empty_tri_batch_create(struct GPUShader *shader,
- DRWPass *pass,
- int size);
DRWShadingGroup *DRW_shgroup_transform_feedback_create(struct GPUShader *shader,
DRWPass *pass,
struct GPUVertBuf *tf_target);
-typedef void(DRWCallGenerateFn)(DRWShadingGroup *shgroup,
- void (*draw_fn)(DRWShadingGroup *shgroup, struct GPUBatch *geom),
- void *user_data);
-
/* return final visibility */
typedef bool(DRWCallVisibilityFn)(bool vis_in, void *user_data);
-void DRW_shgroup_instance_batch(DRWShadingGroup *shgroup, struct GPUBatch *batch);
-
-void DRW_shgroup_call_add(DRWShadingGroup *shgroup, struct GPUBatch *geom, float (*obmat)[4]);
-void DRW_shgroup_call_range_add(
- DRWShadingGroup *shgroup, struct GPUBatch *geom, float (*obmat)[4], uint v_sta, uint v_count);
-void DRW_shgroup_call_procedural_points_add(DRWShadingGroup *shgroup,
- uint point_len,
- float (*obmat)[4]);
-void DRW_shgroup_call_procedural_lines_add(DRWShadingGroup *shgroup,
- uint line_count,
- float (*obmat)[4]);
-void DRW_shgroup_call_procedural_triangles_add(DRWShadingGroup *shgroup,
- uint tria_count,
- float (*obmat)[4]);
-void DRW_shgroup_call_object_procedural_triangles_culled_add(DRWShadingGroup *shgroup,
- uint tria_count,
- struct Object *ob);
-void DRW_shgroup_call_object_add_ex(DRWShadingGroup *shgroup,
- struct GPUBatch *geom,
- struct Object *ob,
- struct Material *ma,
- bool bypass_culling);
-#define DRW_shgroup_call_object_add(shgroup, geom, ob) \
- DRW_shgroup_call_object_add_ex(shgroup, geom, ob, NULL, false)
-#define DRW_shgroup_call_object_add_no_cull(shgroup, geom, ob) \
- DRW_shgroup_call_object_add_ex(shgroup, geom, ob, NULL, true)
-void DRW_shgroup_call_object_add_with_callback(DRWShadingGroup *shgroup,
- struct GPUBatch *geom,
- struct Object *ob,
- struct Material *ma,
- DRWCallVisibilityFn *callback,
- void *user_data);
-/* Used for drawing a batch with instancing without instance attributes. */
-void DRW_shgroup_call_instances_add(DRWShadingGroup *shgroup,
- struct GPUBatch *geom,
- float (*obmat)[4],
- uint *count);
-void DRW_shgroup_call_object_instances_add(DRWShadingGroup *shgroup,
+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);
+
+void DRW_shgroup_call_procedural_points(DRWShadingGroup *sh, uint point_ct, float (*obmat)[4]);
+void DRW_shgroup_call_procedural_lines(DRWShadingGroup *sh, uint line_ct, float (*obmat)[4]);
+void DRW_shgroup_call_procedural_triangles(DRWShadingGroup *sh, uint tri_ct, float (*obmat)[4]);
+
+void DRW_shgroup_call_object_ex(DRWShadingGroup *shgroup,
+ struct GPUBatch *geom,
+ struct Object *ob,
+ bool bypass_culling);
+#define DRW_shgroup_call_object(shgroup, geom, ob) \
+ DRW_shgroup_call_object_ex(shgroup, geom, ob, false)
+#define DRW_shgroup_call_object_no_cull(shgroup, geom, ob) \
+ 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,
- uint *count);
-void DRW_shgroup_call_sculpt_add(DRWShadingGroup *shgroup, struct Object *ob, float (*obmat)[4]);
-void DRW_shgroup_call_sculpt_wires_add(DRWShadingGroup *shgroup,
- struct Object *ob,
- float (*obmat)[4]);
-void DRW_shgroup_call_generate_add(DRWShadingGroup *shgroup,
- DRWCallGenerateFn *geometry_fn,
- void *user_data,
- float (*obmat)[4]);
-void DRW_shgroup_call_dynamic_add_array(DRWShadingGroup *shgroup,
- const void *attr[],
- uint attr_len);
-#define DRW_shgroup_call_dynamic_add(shgroup, ...) \
+ void *user_data);
+
+void DRW_shgroup_call_instances(DRWShadingGroup *shgroup,
+ struct GPUBatch *geom,
+ float (*obmat)[4],
+ uint count);
+void DRW_shgroup_call_instances_with_attribs(DRWShadingGroup *shgroup,
+ struct GPUBatch *geom,
+ float (*obmat)[4],
+ struct GPUBatch *inst_attributes);
+
+void DRW_shgroup_call_sculpt(DRWShadingGroup *sh, Object *ob, bool wire, bool mask, bool vcol);
+void DRW_shgroup_call_sculpt_with_materials(DRWShadingGroup **sh, Object *ob, bool vcol);
+
+DRWCallBuffer *DRW_shgroup_call_buffer(DRWShadingGroup *shading_group,
+ struct GPUVertFormat *format,
+ GPUPrimType prim_type);
+DRWCallBuffer *DRW_shgroup_call_buffer_instance(DRWShadingGroup *shading_group,
+ struct GPUVertFormat *format,
+ struct GPUBatch *geom);
+
+void DRW_buffer_add_entry_array(DRWCallBuffer *buffer, const void *attr[], uint attr_len);
+
+#define DRW_buffer_add_entry(buffer, ...) \
do { \
const void *array[] = {__VA_ARGS__}; \
- DRW_shgroup_call_dynamic_add_array(shgroup, array, (sizeof(array) / sizeof(*array))); \
+ DRW_buffer_add_entry_array(buffer, array, (sizeof(array) / sizeof(*array))); \
} while (0)
-uint DRW_shgroup_get_instance_count(const DRWShadingGroup *shgroup);
-
void DRW_shgroup_state_enable(DRWShadingGroup *shgroup, DRWState state);
void DRW_shgroup_state_disable(DRWShadingGroup *shgroup, DRWState state);
void DRW_shgroup_stencil_mask(DRWShadingGroup *shgroup, uint mask);
@@ -503,14 +479,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,
@@ -538,11 +506,13 @@ void DRW_shgroup_uniform_mat4(DRWShadingGroup *shgroup, const char *name, const
void DRW_shgroup_uniform_int_copy(DRWShadingGroup *shgroup, const char *name, const int value);
void DRW_shgroup_uniform_bool_copy(DRWShadingGroup *shgroup, const char *name, const bool value);
void DRW_shgroup_uniform_float_copy(DRWShadingGroup *shgroup, const char *name, const float value);
+void DRW_shgroup_uniform_vec2_copy(DRWShadingGroup *shgroup, const char *name, const float *value);
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);
@@ -553,51 +523,61 @@ void DRW_pass_sort_shgroup_z(DRWPass *pass);
bool DRW_pass_is_empty(DRWPass *pass);
-/* 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.
+#define DRW_PASS_CREATE(pass, state) (pass = DRW_pass_create(#pass, state))
+
+/* 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);
@@ -635,12 +615,14 @@ DrawData *DRW_drawdata_ensure(ID *id,
size_t size,
DrawDataInitCb init_cb,
DrawDataFreeCb free_cb);
+void **DRW_duplidata_get(void *vedata);
/* Settings */
bool DRW_object_is_renderable(const struct Object *ob);
int DRW_object_visibility_in_active_context(const struct Object *ob);
bool DRW_object_is_flat_normal(const struct Object *ob);
bool DRW_object_use_hide_faces(const struct Object *ob);
+bool DRW_object_use_pbvh_drawing(const struct Object *ob);
bool DRW_object_is_visible_psys_in_active_context(const struct Object *object,
const struct ParticleSystem *psys);
@@ -659,20 +641,6 @@ void DRW_state_reset_ex(DRWState state);
void DRW_state_reset(void);
void DRW_state_lock(DRWState state);
-void DRW_state_invert_facing(void);
-
-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_anim_viz.c b/source/blender/draw/intern/draw_anim_viz.c
index a6026c9da3a..72459309133 100644
--- a/source/blender/draw/intern/draw_anim_viz.c
+++ b/source/blender/draw/intern/draw_anim_viz.c
@@ -139,7 +139,7 @@ static void MPATH_cache_init(void *vedata)
}
{
- DRWState state = DRW_STATE_WRITE_COLOR | DRW_STATE_POINT;
+ DRWState state = DRW_STATE_WRITE_COLOR;
psl->points = DRW_pass_create("Motionpath Point Pass", state);
}
}
@@ -215,7 +215,7 @@ static void MPATH_cache_motion_path(MPATH_PassList *psl,
DRW_shgroup_uniform_vec3(shgrp, "customColor", mpath->color, 1);
}
/* Only draw the required range. */
- DRW_shgroup_call_range_add(shgrp, mpath_batch_line_get(mpath), NULL, start_index, len);
+ DRW_shgroup_call_range(shgrp, mpath_batch_line_get(mpath), NULL, start_index, len);
}
/* Draw points. */
@@ -231,7 +231,7 @@ static void MPATH_cache_motion_path(MPATH_PassList *psl,
DRW_shgroup_uniform_vec3(shgrp, "customColor", mpath->color, 1);
}
/* Only draw the required range. */
- DRW_shgroup_call_range_add(shgrp, mpath_batch_points_get(mpath), NULL, start_index, len);
+ DRW_shgroup_call_range(shgrp, mpath_batch_points_get(mpath), NULL, start_index, len);
/* Draw frame numbers at each framestep value */
bool show_kf_no = (avs->path_viewflag & MOTIONPATH_VIEW_KFNOS) != 0;
diff --git a/source/blender/draw/intern/draw_armature.c b/source/blender/draw/intern/draw_armature.c
index 9b52f282944..3f651b27dd0 100644
--- a/source/blender/draw/intern/draw_armature.c
+++ b/source/blender/draw/intern/draw_armature.c
@@ -37,6 +37,8 @@
#include "BKE_armature.h"
+#include "DEG_depsgraph_query.h"
+
#include "ED_armature.h"
#include "UI_resources.h"
@@ -57,26 +59,26 @@ static struct {
/* Current armature object */
Object *ob;
/* Reset when changing current_armature */
- DRWShadingGroup *bone_octahedral_solid;
- DRWShadingGroup *bone_octahedral_wire;
- DRWShadingGroup *bone_octahedral_outline;
- DRWShadingGroup *bone_box_solid;
- DRWShadingGroup *bone_box_wire;
- DRWShadingGroup *bone_box_outline;
- DRWShadingGroup *bone_wire;
- DRWShadingGroup *bone_stick;
- DRWShadingGroup *bone_dof_sphere;
- DRWShadingGroup *bone_dof_lines;
- DRWShadingGroup *bone_envelope_solid;
- DRWShadingGroup *bone_envelope_distance;
- DRWShadingGroup *bone_envelope_wire;
- DRWShadingGroup *bone_point_solid;
- DRWShadingGroup *bone_point_wire;
- DRWShadingGroup *bone_axes;
- DRWShadingGroup *lines_relationship;
- DRWShadingGroup *lines_ik;
- DRWShadingGroup *lines_ik_no_target;
- DRWShadingGroup *lines_ik_spline;
+ DRWCallBuffer *bone_octahedral_solid;
+ DRWCallBuffer *bone_octahedral_wire;
+ DRWCallBuffer *bone_octahedral_outline;
+ DRWCallBuffer *bone_box_solid;
+ DRWCallBuffer *bone_box_wire;
+ DRWCallBuffer *bone_box_outline;
+ DRWCallBuffer *bone_wire;
+ DRWCallBuffer *bone_stick;
+ DRWCallBuffer *bone_dof_sphere;
+ DRWCallBuffer *bone_dof_lines;
+ DRWCallBuffer *bone_envelope_solid;
+ DRWCallBuffer *bone_envelope_distance;
+ DRWCallBuffer *bone_envelope_wire;
+ DRWCallBuffer *bone_point_solid;
+ DRWCallBuffer *bone_point_wire;
+ DRWCallBuffer *bone_axes;
+ DRWCallBuffer *lines_relationship;
+ DRWCallBuffer *lines_ik;
+ DRWCallBuffer *lines_ik_no_target;
+ DRWCallBuffer *lines_ik_spline;
DRWArmaturePasses passes;
@@ -120,22 +122,21 @@ static void drw_shgroup_bone_octahedral(const float (*bone_mat)[4],
{
if (g_data.bone_octahedral_outline == NULL) {
struct GPUBatch *geom = DRW_cache_bone_octahedral_wire_get();
- g_data.bone_octahedral_outline = shgroup_instance_bone_shape_outline(
+ g_data.bone_octahedral_outline = buffer_instance_bone_shape_outline(
g_data.passes.bone_outline, geom, sh_cfg);
}
if (g_data.bone_octahedral_solid == NULL && g_data.passes.bone_solid != NULL) {
struct GPUBatch *geom = DRW_cache_bone_octahedral_get();
- g_data.bone_octahedral_solid = shgroup_instance_bone_shape_solid(
+ g_data.bone_octahedral_solid = buffer_instance_bone_shape_solid(
g_data.passes.bone_solid, geom, g_data.transparent, sh_cfg);
}
float final_bonemat[4][4];
mul_m4_m4m4(final_bonemat, g_data.ob->obmat, bone_mat);
if (g_data.bone_octahedral_solid != NULL) {
- DRW_shgroup_call_dynamic_add(
- g_data.bone_octahedral_solid, final_bonemat, bone_color, hint_color);
+ DRW_buffer_add_entry(g_data.bone_octahedral_solid, final_bonemat, bone_color, hint_color);
}
if (outline_color[3] > 0.0f) {
- DRW_shgroup_call_dynamic_add(g_data.bone_octahedral_outline, final_bonemat, outline_color);
+ DRW_buffer_add_entry(g_data.bone_octahedral_outline, final_bonemat, outline_color);
}
}
@@ -148,21 +149,21 @@ static void drw_shgroup_bone_box(const float (*bone_mat)[4],
{
if (g_data.bone_box_wire == NULL) {
struct GPUBatch *geom = DRW_cache_bone_box_wire_get();
- g_data.bone_box_outline = shgroup_instance_bone_shape_outline(
+ g_data.bone_box_outline = buffer_instance_bone_shape_outline(
g_data.passes.bone_outline, geom, sh_cfg);
}
if (g_data.bone_box_solid == NULL && g_data.passes.bone_solid != NULL) {
struct GPUBatch *geom = DRW_cache_bone_box_get();
- g_data.bone_box_solid = shgroup_instance_bone_shape_solid(
+ g_data.bone_box_solid = buffer_instance_bone_shape_solid(
g_data.passes.bone_solid, geom, g_data.transparent, sh_cfg);
}
float final_bonemat[4][4];
mul_m4_m4m4(final_bonemat, g_data.ob->obmat, bone_mat);
if (g_data.bone_box_solid != NULL) {
- DRW_shgroup_call_dynamic_add(g_data.bone_box_solid, final_bonemat, bone_color, hint_color);
+ DRW_buffer_add_entry(g_data.bone_box_solid, final_bonemat, bone_color, hint_color);
}
if (outline_color[3] > 0.0f) {
- DRW_shgroup_call_dynamic_add(g_data.bone_box_outline, final_bonemat, outline_color);
+ DRW_buffer_add_entry(g_data.bone_box_outline, final_bonemat, outline_color);
}
}
@@ -172,15 +173,15 @@ static void drw_shgroup_bone_wire(const float (*bone_mat)[4],
const eGPUShaderConfig sh_cfg)
{
if (g_data.bone_wire == NULL) {
- g_data.bone_wire = shgroup_dynlines_flat_color(g_data.passes.bone_wire, sh_cfg);
+ g_data.bone_wire = buffer_dynlines_flat_color(g_data.passes.bone_wire, sh_cfg);
}
float head[3], tail[3];
mul_v3_m4v3(head, g_data.ob->obmat, bone_mat[3]);
- DRW_shgroup_call_dynamic_add(g_data.bone_wire, head, color);
+ DRW_buffer_add_entry(g_data.bone_wire, head, color);
add_v3_v3v3(tail, bone_mat[3], bone_mat[1]);
mul_m4_v3(g_data.ob->obmat, tail);
- DRW_shgroup_call_dynamic_add(g_data.bone_wire, tail, color);
+ DRW_buffer_add_entry(g_data.bone_wire, tail, color);
}
/* Stick */
@@ -192,12 +193,12 @@ static void drw_shgroup_bone_stick(const float (*bone_mat)[4],
const eGPUShaderConfig sh_cfg)
{
if (g_data.bone_stick == NULL) {
- g_data.bone_stick = shgroup_instance_bone_stick(g_data.passes.bone_wire, sh_cfg);
+ g_data.bone_stick = buffer_instance_bone_stick(g_data.passes.bone_wire, sh_cfg);
}
float final_bonemat[4][4], tail[4];
mul_m4_m4m4(final_bonemat, g_data.ob->obmat, bone_mat);
add_v3_v3v3(tail, final_bonemat[3], final_bonemat[1]);
- DRW_shgroup_call_dynamic_add(
+ DRW_buffer_add_entry(
g_data.bone_stick, final_bonemat[3], tail, col_wire, col_bone, col_head, col_tail);
}
@@ -210,7 +211,7 @@ static void drw_shgroup_bone_envelope_distance(const float (*bone_mat)[4],
{
if (g_data.passes.bone_envelope != NULL) {
if (g_data.bone_envelope_distance == NULL) {
- g_data.bone_envelope_distance = shgroup_instance_bone_envelope_distance(
+ g_data.bone_envelope_distance = buffer_instance_bone_envelope_distance(
g_data.passes.bone_envelope, sh_cfg);
/* passes.bone_envelope should have the DRW_STATE_CULL_FRONT state enabled. */
}
@@ -225,7 +226,7 @@ static void drw_shgroup_bone_envelope_distance(const float (*bone_mat)[4],
head_sphere[3] += *distance;
tail_sphere[3] = *radius_tail;
tail_sphere[3] += *distance;
- DRW_shgroup_call_dynamic_add(
+ DRW_buffer_add_entry(
g_data.bone_envelope_distance, head_sphere, tail_sphere, final_bonemat[0]);
}
}
@@ -239,22 +240,19 @@ static void drw_shgroup_bone_envelope(const float (*bone_mat)[4],
const eGPUShaderConfig sh_cfg)
{
if (g_data.bone_point_wire == NULL) {
- g_data.bone_point_wire = shgroup_instance_bone_sphere_outline(g_data.passes.bone_wire, sh_cfg);
+ g_data.bone_point_wire = buffer_instance_bone_sphere_outline(g_data.passes.bone_wire, sh_cfg);
}
if (g_data.bone_point_solid == NULL && g_data.passes.bone_solid != NULL) {
- g_data.bone_point_solid = shgroup_instance_bone_sphere_solid(
+ g_data.bone_point_solid = buffer_instance_bone_sphere_solid(
g_data.passes.bone_solid, g_data.transparent, sh_cfg);
}
if (g_data.bone_envelope_wire == NULL) {
- g_data.bone_envelope_wire = shgroup_instance_bone_envelope_outline(g_data.passes.bone_wire,
- sh_cfg);
+ g_data.bone_envelope_wire = buffer_instance_bone_envelope_outline(g_data.passes.bone_wire,
+ sh_cfg);
}
if (g_data.bone_envelope_solid == NULL && g_data.passes.bone_solid != NULL) {
- g_data.bone_envelope_solid = shgroup_instance_bone_envelope_solid(
+ g_data.bone_envelope_solid = buffer_instance_bone_envelope_solid(
g_data.passes.bone_solid, g_data.transparent, sh_cfg);
- /* We can have a lot of overdraw if we don't do this. Also envelope are not subject to
- * inverted matrix. */
- DRW_shgroup_state_enable(g_data.bone_envelope_solid, DRW_STATE_CULL_BACK);
}
float head_sphere[4] = {0.0f, 0.0f, 0.0f, 1.0f}, tail_sphere[4] = {0.0f, 1.0f, 0.0f, 1.0f};
@@ -272,10 +270,10 @@ static void drw_shgroup_bone_envelope(const float (*bone_mat)[4],
tmp[3][3] = 1.0f;
copy_v3_v3(tmp[3], tail_sphere);
if (g_data.bone_point_solid != NULL) {
- DRW_shgroup_call_dynamic_add(g_data.bone_point_solid, tmp, bone_color, hint_color);
+ DRW_buffer_add_entry(g_data.bone_point_solid, tmp, bone_color, hint_color);
}
if (outline_color[3] > 0.0f) {
- DRW_shgroup_call_dynamic_add(g_data.bone_point_wire, tmp, outline_color);
+ DRW_buffer_add_entry(g_data.bone_point_wire, tmp, outline_color);
}
}
else if (tail_sphere[3] < 0.0f) {
@@ -285,10 +283,10 @@ static void drw_shgroup_bone_envelope(const float (*bone_mat)[4],
tmp[3][3] = 1.0f;
copy_v3_v3(tmp[3], head_sphere);
if (g_data.bone_point_solid != NULL) {
- DRW_shgroup_call_dynamic_add(g_data.bone_point_solid, tmp, bone_color, hint_color);
+ DRW_buffer_add_entry(g_data.bone_point_solid, tmp, bone_color, hint_color);
}
if (outline_color[3] > 0.0f) {
- DRW_shgroup_call_dynamic_add(g_data.bone_point_wire, tmp, outline_color);
+ DRW_buffer_add_entry(g_data.bone_point_wire, tmp, outline_color);
}
}
else {
@@ -305,15 +303,15 @@ static void drw_shgroup_bone_envelope(const float (*bone_mat)[4],
interp_v4_v4v4(head_sphere, tail_sphere, head_sphere, fac_head);
interp_v4_v4v4(tail_sphere, tmp_sphere, tail_sphere, fac_tail);
if (g_data.bone_envelope_solid != NULL) {
- DRW_shgroup_call_dynamic_add(g_data.bone_envelope_solid,
- head_sphere,
- tail_sphere,
- bone_color,
- hint_color,
- final_bonemat[0]);
+ DRW_buffer_add_entry(g_data.bone_envelope_solid,
+ head_sphere,
+ tail_sphere,
+ bone_color,
+ hint_color,
+ final_bonemat[0]);
}
if (outline_color[3] > 0.0f) {
- DRW_shgroup_call_dynamic_add(
+ DRW_buffer_add_entry(
g_data.bone_envelope_wire, head_sphere, tail_sphere, outline_color, final_bonemat[0]);
}
}
@@ -325,10 +323,10 @@ static void drw_shgroup_bone_envelope(const float (*bone_mat)[4],
tmp[3][3] = 1.0f;
copy_v3_v3(tmp[3], tmp_sphere);
if (g_data.bone_point_solid != NULL) {
- DRW_shgroup_call_dynamic_add(g_data.bone_point_solid, tmp, bone_color, hint_color);
+ DRW_buffer_add_entry(g_data.bone_point_solid, tmp, bone_color, hint_color);
}
if (outline_color[3] > 0.0f) {
- DRW_shgroup_call_dynamic_add(g_data.bone_point_wire, tmp, outline_color);
+ DRW_buffer_add_entry(g_data.bone_point_wire, tmp, outline_color);
}
}
}
@@ -336,6 +334,7 @@ static void drw_shgroup_bone_envelope(const float (*bone_mat)[4],
/* Custom (geometry) */
+extern void drw_batch_cache_validate(Object *custom);
extern void drw_batch_cache_generate_requested(Object *custom);
static void drw_shgroup_bone_custom_solid(const float (*bone_mat)[4],
@@ -345,6 +344,10 @@ static void drw_shgroup_bone_custom_solid(const float (*bone_mat)[4],
const eGPUShaderConfig sh_cfg,
Object *custom)
{
+ /* TODO(fclem) arg... less than ideal but we never iter on this object
+ * to assure batch cache is valid. */
+ drw_batch_cache_validate(custom);
+
struct GPUBatch *surf = DRW_cache_object_surface_get(custom);
struct GPUBatch *edges = DRW_cache_object_edge_detection_get(custom, NULL);
struct GPUBatch *ledges = DRW_cache_object_loose_edges_get(custom);
@@ -357,50 +360,50 @@ static void drw_shgroup_bone_custom_solid(const float (*bone_mat)[4],
BLI_assert(g_data.passes.custom_shapes != NULL);
if (surf && g_data.passes.bone_solid != NULL) {
- DRWShadingGroup *shgrp_geom_solid = BLI_ghash_lookup(g_data.passes.custom_shapes, surf);
+ DRWCallBuffer *buf_geom_solid = BLI_ghash_lookup(g_data.passes.custom_shapes, surf);
- if (shgrp_geom_solid == NULL) {
+ if (buf_geom_solid == NULL) {
/* TODO(fclem) needs to be moved elsewhere. */
drw_batch_cache_generate_requested(custom);
/* NOTE! g_data.transparent require a separate shading group if the
* object is transparent. This is done by passing a different ghash
* for transparent armature in pose mode. */
- shgrp_geom_solid = shgroup_instance_bone_shape_solid(
+ buf_geom_solid = buffer_instance_bone_shape_solid(
g_data.passes.bone_solid, surf, g_data.transparent, sh_cfg);
- BLI_ghash_insert(g_data.passes.custom_shapes, surf, shgrp_geom_solid);
+ BLI_ghash_insert(g_data.passes.custom_shapes, surf, buf_geom_solid);
}
- DRW_shgroup_call_dynamic_add(shgrp_geom_solid, final_bonemat, bone_color, hint_color);
+ DRW_buffer_add_entry(buf_geom_solid, final_bonemat, bone_color, hint_color);
}
if (edges && outline_color[3] > 0.0f) {
- DRWShadingGroup *shgrp_geom_wire = BLI_ghash_lookup(g_data.passes.custom_shapes, edges);
+ DRWCallBuffer *buf_geom_wire = BLI_ghash_lookup(g_data.passes.custom_shapes, edges);
- if (shgrp_geom_wire == NULL) {
+ if (buf_geom_wire == NULL) {
/* TODO(fclem) needs to be moved elsewhere. */
drw_batch_cache_generate_requested(custom);
- shgrp_geom_wire = shgroup_instance_bone_shape_outline(
+ buf_geom_wire = buffer_instance_bone_shape_outline(
g_data.passes.bone_outline, edges, sh_cfg);
- BLI_ghash_insert(g_data.passes.custom_shapes, edges, shgrp_geom_wire);
+ BLI_ghash_insert(g_data.passes.custom_shapes, edges, buf_geom_wire);
}
- DRW_shgroup_call_dynamic_add(shgrp_geom_wire, final_bonemat, outline_color);
+ DRW_buffer_add_entry(buf_geom_wire, final_bonemat, outline_color);
}
if (ledges) {
- DRWShadingGroup *shgrp_geom_ledges = BLI_ghash_lookup(g_data.passes.custom_shapes, ledges);
+ DRWCallBuffer *buf_geom_ledges = BLI_ghash_lookup(g_data.passes.custom_shapes, ledges);
- if (shgrp_geom_ledges == NULL) {
+ if (buf_geom_ledges == NULL) {
/* TODO(fclem) needs to be moved elsewhere. */
drw_batch_cache_generate_requested(custom);
- shgrp_geom_ledges = shgroup_instance_wire(g_data.passes.bone_wire, ledges);
+ buf_geom_ledges = buffer_instance_wire(g_data.passes.bone_wire, ledges);
- BLI_ghash_insert(g_data.passes.custom_shapes, ledges, shgrp_geom_ledges);
+ BLI_ghash_insert(g_data.passes.custom_shapes, ledges, buf_geom_ledges);
}
float final_color[4] = {outline_color[0], outline_color[1], outline_color[2], 1.0f};
- DRW_shgroup_call_dynamic_add(shgrp_geom_ledges, final_bonemat, final_color);
+ DRW_buffer_add_entry(buf_geom_ledges, final_bonemat, final_color);
}
}
@@ -408,23 +411,27 @@ static void drw_shgroup_bone_custom_wire(const float (*bone_mat)[4],
const float color[4],
Object *custom)
{
+ /* TODO(fclem) arg... less than ideal but we never iter on this object
+ * to assure batch cache is valid. */
+ drw_batch_cache_validate(custom);
+
struct GPUBatch *geom = DRW_cache_object_all_edges_get(custom);
if (geom) {
- DRWShadingGroup *shgrp_geom_wire = BLI_ghash_lookup(g_data.passes.custom_shapes, geom);
+ DRWCallBuffer *buf_geom_wire = BLI_ghash_lookup(g_data.passes.custom_shapes, geom);
- if (shgrp_geom_wire == NULL) {
+ if (buf_geom_wire == NULL) {
/* TODO(fclem) needs to be moved elsewhere. */
drw_batch_cache_generate_requested(custom);
- shgrp_geom_wire = shgroup_instance_wire(g_data.passes.bone_wire, geom);
+ buf_geom_wire = buffer_instance_wire(g_data.passes.bone_wire, geom);
- BLI_ghash_insert(g_data.passes.custom_shapes, geom, shgrp_geom_wire);
+ BLI_ghash_insert(g_data.passes.custom_shapes, geom, buf_geom_wire);
}
float final_color[4] = {color[0], color[1], color[2], 1.0f};
float final_bonemat[4][4];
mul_m4_m4m4(final_bonemat, g_data.ob->obmat, bone_mat);
- DRW_shgroup_call_dynamic_add(shgrp_geom_wire, final_bonemat, final_color);
+ DRW_buffer_add_entry(buf_geom_wire, final_bonemat, final_color);
}
}
@@ -436,19 +443,19 @@ static void drw_shgroup_bone_point(const float (*bone_mat)[4],
const eGPUShaderConfig sh_cfg)
{
if (g_data.bone_point_wire == NULL) {
- g_data.bone_point_wire = shgroup_instance_bone_sphere_outline(g_data.passes.bone_wire, sh_cfg);
+ g_data.bone_point_wire = buffer_instance_bone_sphere_outline(g_data.passes.bone_wire, sh_cfg);
}
if (g_data.bone_point_solid == NULL && g_data.passes.bone_solid != NULL) {
- g_data.bone_point_solid = shgroup_instance_bone_sphere_solid(
+ g_data.bone_point_solid = buffer_instance_bone_sphere_solid(
g_data.passes.bone_solid, g_data.transparent, sh_cfg);
}
float final_bonemat[4][4];
mul_m4_m4m4(final_bonemat, g_data.ob->obmat, bone_mat);
if (g_data.bone_point_solid != NULL) {
- DRW_shgroup_call_dynamic_add(g_data.bone_point_solid, final_bonemat, bone_color, hint_color);
+ DRW_buffer_add_entry(g_data.bone_point_solid, final_bonemat, bone_color, hint_color);
}
if (outline_color[3] > 0.0f) {
- DRW_shgroup_call_dynamic_add(g_data.bone_point_wire, final_bonemat, outline_color);
+ DRW_buffer_add_entry(g_data.bone_point_wire, final_bonemat, outline_color);
}
}
@@ -458,11 +465,11 @@ static void drw_shgroup_bone_axes(const float (*bone_mat)[4],
const eGPUShaderConfig sh_cfg)
{
if (g_data.bone_axes == NULL) {
- g_data.bone_axes = shgroup_instance_bone_axes(g_data.passes.bone_axes, sh_cfg);
+ g_data.bone_axes = buffer_instance_bone_axes(g_data.passes.bone_axes, sh_cfg);
}
float final_bonemat[4][4];
mul_m4_m4m4(final_bonemat, g_data.ob->obmat, bone_mat);
- DRW_shgroup_call_dynamic_add(g_data.bone_axes, final_bonemat, color);
+ DRW_buffer_add_entry(g_data.bone_axes, final_bonemat, color);
}
/* Relationship lines */
@@ -471,15 +478,15 @@ static void drw_shgroup_bone_relationship_lines(const float start[3],
const eGPUShaderConfig sh_cfg)
{
if (g_data.lines_relationship == NULL) {
- g_data.lines_relationship = shgroup_dynlines_dashed_uniform_color(
+ g_data.lines_relationship = buffer_dynlines_dashed_uniform_color(
g_data.passes.relationship_lines, g_theme.wire_color, sh_cfg);
}
/* reverse order to have less stipple overlap */
float v[3];
mul_v3_m4v3(v, g_data.ob->obmat, end);
- DRW_shgroup_call_dynamic_add(g_data.lines_relationship, v);
+ DRW_buffer_add_entry(g_data.lines_relationship, v);
mul_v3_m4v3(v, g_data.ob->obmat, start);
- DRW_shgroup_call_dynamic_add(g_data.lines_relationship, v);
+ DRW_buffer_add_entry(g_data.lines_relationship, v);
}
static void drw_shgroup_bone_ik_lines(const float start[3],
@@ -488,15 +495,15 @@ static void drw_shgroup_bone_ik_lines(const float start[3],
{
if (g_data.lines_ik == NULL) {
static float fcolor[4] = {0.8f, 0.5f, 0.0f, 1.0f}; /* add theme! */
- g_data.lines_ik = shgroup_dynlines_dashed_uniform_color(
+ g_data.lines_ik = buffer_dynlines_dashed_uniform_color(
g_data.passes.relationship_lines, fcolor, sh_cfg);
}
/* reverse order to have less stipple overlap */
float v[3];
mul_v3_m4v3(v, g_data.ob->obmat, end);
- DRW_shgroup_call_dynamic_add(g_data.lines_ik, v);
+ DRW_buffer_add_entry(g_data.lines_ik, v);
mul_v3_m4v3(v, g_data.ob->obmat, start);
- DRW_shgroup_call_dynamic_add(g_data.lines_ik, v);
+ DRW_buffer_add_entry(g_data.lines_ik, v);
}
static void drw_shgroup_bone_ik_no_target_lines(const float start[3],
@@ -505,15 +512,15 @@ static void drw_shgroup_bone_ik_no_target_lines(const float start[3],
{
if (g_data.lines_ik_no_target == NULL) {
static float fcolor[4] = {0.8f, 0.8f, 0.2f, 1.0f}; /* add theme! */
- g_data.lines_ik_no_target = shgroup_dynlines_dashed_uniform_color(
+ g_data.lines_ik_no_target = buffer_dynlines_dashed_uniform_color(
g_data.passes.relationship_lines, fcolor, sh_cfg);
}
/* reverse order to have less stipple overlap */
float v[3];
mul_v3_m4v3(v, g_data.ob->obmat, end);
- DRW_shgroup_call_dynamic_add(g_data.lines_ik_no_target, v);
+ DRW_buffer_add_entry(g_data.lines_ik_no_target, v);
mul_v3_m4v3(v, g_data.ob->obmat, start);
- DRW_shgroup_call_dynamic_add(g_data.lines_ik_no_target, v);
+ DRW_buffer_add_entry(g_data.lines_ik_no_target, v);
}
static void drw_shgroup_bone_ik_spline_lines(const float start[3],
@@ -522,15 +529,15 @@ static void drw_shgroup_bone_ik_spline_lines(const float start[3],
{
if (g_data.lines_ik_spline == NULL) {
static float fcolor[4] = {0.8f, 0.8f, 0.2f, 1.0f}; /* add theme! */
- g_data.lines_ik_spline = shgroup_dynlines_dashed_uniform_color(
+ g_data.lines_ik_spline = buffer_dynlines_dashed_uniform_color(
g_data.passes.relationship_lines, fcolor, sh_cfg);
}
/* reverse order to have less stipple overlap */
float v[3];
mul_v3_m4v3(v, g_data.ob->obmat, end);
- DRW_shgroup_call_dynamic_add(g_data.lines_ik_spline, v);
+ DRW_buffer_add_entry(g_data.lines_ik_spline, v);
mul_v3_m4v3(v, g_data.ob->obmat, start);
- DRW_shgroup_call_dynamic_add(g_data.lines_ik_spline, v);
+ DRW_buffer_add_entry(g_data.lines_ik_spline, v);
}
/** \} */
@@ -1634,12 +1641,10 @@ static void draw_bone_dofs(bPoseChannel *pchan)
}
if (g_data.bone_dof_sphere == NULL) {
- g_data.bone_dof_lines = shgroup_instance_bone_dof(g_data.passes.bone_wire,
- DRW_cache_bone_dof_lines_get());
- g_data.bone_dof_sphere = shgroup_instance_bone_dof(g_data.passes.bone_envelope,
- DRW_cache_bone_dof_sphere_get());
- DRW_shgroup_state_enable(g_data.bone_dof_sphere, DRW_STATE_BLEND);
- DRW_shgroup_state_disable(g_data.bone_dof_sphere, DRW_STATE_CULL_FRONT);
+ g_data.bone_dof_lines = buffer_instance_bone_dof(
+ g_data.passes.bone_wire, DRW_cache_bone_dof_lines_get(), false);
+ g_data.bone_dof_sphere = buffer_instance_bone_dof(
+ g_data.passes.bone_envelope, DRW_cache_bone_dof_sphere_get(), true);
}
/* *0.5f here comes from M_PI/360.0f when rotations were still in degrees */
@@ -1672,20 +1677,20 @@ static void draw_bone_dofs(bPoseChannel *pchan)
amax[0] = xminmax[1];
amin[1] = zminmax[0];
amax[1] = zminmax[1];
- DRW_shgroup_call_dynamic_add(g_data.bone_dof_sphere, final_bonemat, col_sphere, amin, amax);
- DRW_shgroup_call_dynamic_add(g_data.bone_dof_lines, final_bonemat, col_lines, amin, amax);
+ DRW_buffer_add_entry(g_data.bone_dof_sphere, final_bonemat, col_sphere, amin, amax);
+ DRW_buffer_add_entry(g_data.bone_dof_lines, final_bonemat, col_lines, amin, amax);
}
if (pchan->ikflag & BONE_IK_XLIMIT) {
amin[0] = xminmax[0];
amax[0] = xminmax[1];
amin[1] = amax[1] = 0.0f;
- DRW_shgroup_call_dynamic_add(g_data.bone_dof_lines, final_bonemat, col_xaxis, amin, amax);
+ DRW_buffer_add_entry(g_data.bone_dof_lines, final_bonemat, col_xaxis, amin, amax);
}
if (pchan->ikflag & BONE_IK_ZLIMIT) {
amin[1] = zminmax[0];
amax[1] = zminmax[1];
amin[0] = amax[0] = 0.0f;
- DRW_shgroup_call_dynamic_add(g_data.bone_dof_lines, final_bonemat, col_zaxis, amin, amax);
+ DRW_buffer_add_entry(g_data.bone_dof_lines, final_bonemat, col_zaxis, amin, amax);
}
}
@@ -1839,7 +1844,9 @@ static void draw_armature_edit(Object *ob)
const bool show_text = DRW_state_show_text();
const bool show_relations = ((draw_ctx->v3d->flag & V3D_HIDE_HELPLINES) == 0);
- for (eBone = arm->edbo->first, index = ob->select_id; eBone;
+ const Object *orig_object = DEG_get_original_object(ob);
+
+ for (eBone = arm->edbo->first, index = orig_object->runtime.select_id; eBone;
eBone = eBone->next, index += 0x10000) {
if (eBone->layer & arm->layer) {
if ((eBone->flag & BONE_HIDDEN_A) == 0) {
@@ -1934,7 +1941,8 @@ static void draw_armature_pose(Object *ob, const float const_color[4])
}
if (arm->flag & ARM_POSEMODE) {
- index = ob->select_id;
+ const Object *orig_object = DEG_get_original_object(ob);
+ index = orig_object->runtime.select_id;
}
}
diff --git a/source/blender/draw/intern/draw_cache.c b/source/blender/draw/intern/draw_cache.c
index 6b4c4cef9c8..c40e9772340 100644
--- a/source/blender/draw/intern/draw_cache.c
+++ b/source/blender/draw/intern/draw_cache.c
@@ -46,6 +46,9 @@
/* Batch's only (free'd as an array) */
static struct DRWShapeCache {
+ GPUBatch *drw_procedural_verts;
+ GPUBatch *drw_procedural_lines;
+ GPUBatch *drw_procedural_tris;
GPUBatch *drw_single_vertice;
GPUBatch *drw_cursor;
GPUBatch *drw_cursor_only_circle;
@@ -138,6 +141,54 @@ void DRW_shape_cache_reset(void)
}
/* -------------------------------------------------------------------- */
+/** \name Procedural Batches
+ * \{ */
+
+GPUBatch *drw_cache_procedural_points_get(void)
+{
+ if (!SHC.drw_procedural_verts) {
+ /* TODO(fclem) get rid of this dummy VBO. */
+ GPUVertFormat format = {0};
+ GPU_vertformat_attr_add(&format, "dummy", GPU_COMP_F32, 1, GPU_FETCH_FLOAT);
+ GPUVertBuf *vbo = GPU_vertbuf_create_with_format(&format);
+ GPU_vertbuf_data_alloc(vbo, 1);
+
+ SHC.drw_procedural_verts = GPU_batch_create_ex(GPU_PRIM_POINTS, vbo, NULL, GPU_BATCH_OWNS_VBO);
+ }
+ return SHC.drw_procedural_verts;
+}
+
+GPUBatch *drw_cache_procedural_lines_get(void)
+{
+ if (!SHC.drw_procedural_lines) {
+ /* TODO(fclem) get rid of this dummy VBO. */
+ GPUVertFormat format = {0};
+ GPU_vertformat_attr_add(&format, "dummy", GPU_COMP_F32, 1, GPU_FETCH_FLOAT);
+ GPUVertBuf *vbo = GPU_vertbuf_create_with_format(&format);
+ GPU_vertbuf_data_alloc(vbo, 1);
+
+ SHC.drw_procedural_lines = GPU_batch_create_ex(GPU_PRIM_LINES, vbo, NULL, GPU_BATCH_OWNS_VBO);
+ }
+ return SHC.drw_procedural_lines;
+}
+
+GPUBatch *drw_cache_procedural_triangles_get(void)
+{
+ if (!SHC.drw_procedural_tris) {
+ /* TODO(fclem) get rid of this dummy VBO. */
+ GPUVertFormat format = {0};
+ GPU_vertformat_attr_add(&format, "dummy", GPU_COMP_F32, 1, GPU_FETCH_FLOAT);
+ GPUVertBuf *vbo = GPU_vertbuf_create_with_format(&format);
+ GPU_vertbuf_data_alloc(vbo, 1);
+
+ SHC.drw_procedural_tris = GPU_batch_create_ex(GPU_PRIM_TRIS, vbo, NULL, GPU_BATCH_OWNS_VBO);
+ }
+ return SHC.drw_procedural_tris;
+}
+
+/** \} */
+
+/* -------------------------------------------------------------------- */
/** \name Helper functions
* \{ */
@@ -3290,14 +3341,6 @@ GPUBatch *DRW_cache_mesh_surface_mesh_analysis_get(Object *ob)
return DRW_mesh_batch_cache_get_edit_mesh_analysis(ob->data);
}
-void DRW_cache_mesh_sculpt_coords_ensure(Object *ob)
-{
- BLI_assert(ob->type == OB_MESH);
-
- Mesh *me = ob->data;
- DRW_mesh_cache_sculpt_coords_ensure(me);
-}
-
/** \} */
/* -------------------------------------------------------------------- */
@@ -3961,68 +4004,32 @@ GPUBatch *DRW_cache_cursor_get(bool crosshair_lines)
/** \name Batch Cache Impl. common
* \{ */
-GPUBatch *DRW_batch_request(GPUBatch **batch)
-{
- /* XXX TODO(fclem): We are writting to batch cache here. Need to make this thread safe. */
- if (*batch == NULL) {
- *batch = MEM_callocN(sizeof(GPUBatch), "GPUBatch");
- }
- return *batch;
-}
-
-bool DRW_batch_requested(GPUBatch *batch, int prim_type)
+void drw_batch_cache_validate(Object *ob)
{
- /* Batch has been requested if it has been created but not initialized. */
- if (batch != NULL && batch->verts[0] == NULL) {
- /* HACK. We init without a valid VBO and let the first vbo binding
- * fill verts[0]. */
- GPU_batch_init_ex(batch, prim_type, (GPUVertBuf *)1, NULL, 0);
- batch->verts[0] = NULL;
- return true;
- }
- return false;
-}
-
-void DRW_ibo_request(GPUBatch *batch, GPUIndexBuf **ibo)
-{
- if (*ibo == NULL) {
- *ibo = MEM_callocN(sizeof(GPUIndexBuf), "GPUIndexBuf");
- }
- GPU_batch_vao_cache_clear(batch);
- batch->elem = *ibo;
-}
-
-bool DRW_ibo_requested(GPUIndexBuf *ibo)
-{
- /* TODO do not rely on data uploaded. This prevents multithreading.
- * (need access to a gl context) */
- return (ibo != NULL && ibo->ibo_id == 0 && ibo->data == NULL);
-}
-
-void DRW_vbo_request(GPUBatch *batch, GPUVertBuf **vbo)
-{
- if (*vbo == NULL) {
- *vbo = MEM_callocN(sizeof(GPUVertBuf), "GPUVertBuf");
- }
- /* HACK set first vbo if not init. */
- if (batch->verts[0] == NULL) {
- GPU_batch_vao_cache_clear(batch);
- batch->verts[0] = *vbo;
- }
- else {
- /* HACK: bypass assert */
- int vbo_vert_len = (*vbo)->vertex_len;
- (*vbo)->vertex_len = batch->verts[0]->vertex_len;
- GPU_batch_vertbuf_add(batch, *vbo);
- (*vbo)->vertex_len = vbo_vert_len;
+ struct Mesh *mesh_eval = ob->runtime.mesh_eval;
+ switch (ob->type) {
+ case OB_MESH:
+ DRW_mesh_batch_cache_validate((Mesh *)ob->data);
+ break;
+ case OB_CURVE:
+ case OB_FONT:
+ case OB_SURF:
+ if (mesh_eval != NULL) {
+ DRW_mesh_batch_cache_validate(mesh_eval);
+ }
+ DRW_curve_batch_cache_validate((Curve *)ob->data);
+ break;
+ case OB_MBALL:
+ DRW_mball_batch_cache_validate((MetaBall *)ob->data);
+ break;
+ case OB_LATTICE:
+ DRW_lattice_batch_cache_validate((Lattice *)ob->data);
+ break;
+ default:
+ break;
}
}
-bool DRW_vbo_requested(GPUVertBuf *vbo)
-{
- return (vbo != NULL && vbo->format.attr_len == 0);
-}
-
void drw_batch_cache_generate_requested(Object *ob)
{
const DRWContextState *draw_ctx = DRW_context_state_get();
diff --git a/source/blender/draw/intern/draw_cache_impl.h b/source/blender/draw/intern/draw_cache_impl.h
index 4ef8f5a9326..4dc58972ce6 100644
--- a/source/blender/draw/intern/draw_cache_impl.h
+++ b/source/blender/draw/intern/draw_cache_impl.h
@@ -44,15 +44,19 @@ struct bGPdata;
/* Expose via BKE callbacks */
void DRW_mball_batch_cache_dirty_tag(struct MetaBall *mb, int mode);
+void DRW_mball_batch_cache_validate(struct MetaBall *mb);
void DRW_mball_batch_cache_free(struct MetaBall *mb);
void DRW_curve_batch_cache_dirty_tag(struct Curve *cu, int mode);
+void DRW_curve_batch_cache_validate(struct Curve *cu);
void DRW_curve_batch_cache_free(struct Curve *cu);
void DRW_mesh_batch_cache_dirty_tag(struct Mesh *me, int mode);
+void DRW_mesh_batch_cache_validate(struct Mesh *me);
void DRW_mesh_batch_cache_free(struct Mesh *me);
void DRW_lattice_batch_cache_dirty_tag(struct Lattice *lt, int mode);
+void DRW_lattice_batch_cache_validate(struct Lattice *lt);
void DRW_lattice_batch_cache_free(struct Lattice *lt);
void DRW_particle_batch_cache_dirty_tag(struct ParticleSystem *psys, int mode);
@@ -159,8 +163,6 @@ struct GPUBatch *DRW_mesh_batch_cache_get_edituv_facedots(struct Mesh *me);
struct GPUBatch *DRW_mesh_batch_cache_get_uv_edges(struct Mesh *me);
struct GPUBatch *DRW_mesh_batch_cache_get_edit_mesh_analysis(struct Mesh *me);
-void DRW_mesh_cache_sculpt_coords_ensure(struct Mesh *me);
-
/* Edit mesh bitflags (is this the right place?) */
enum {
VFLAG_VERT_ACTIVE = 1 << 0,
@@ -204,30 +206,4 @@ struct GPUBatch *DRW_particles_batch_cache_get_edit_tip_points(struct Object *ob
struct ParticleSystem *psys,
struct PTCacheEdit *edit);
-/* Common */
-// #define DRW_DEBUG_MESH_CACHE_REQUEST
-
-#ifdef DRW_DEBUG_MESH_CACHE_REQUEST
-# define DRW_ADD_FLAG_FROM_VBO_REQUEST(flag, vbo, value) \
- (flag |= DRW_vbo_requested(vbo) ? (printf(" VBO requested " #vbo "\n") ? value : value) : 0)
-# define DRW_ADD_FLAG_FROM_IBO_REQUEST(flag, ibo, value) \
- (flag |= DRW_ibo_requested(ibo) ? (printf(" IBO requested " #ibo "\n") ? value : value) : 0)
-#else
-# define DRW_ADD_FLAG_FROM_VBO_REQUEST(flag, vbo, value) \
- (flag |= DRW_vbo_requested(vbo) ? (value) : 0)
-# define DRW_ADD_FLAG_FROM_IBO_REQUEST(flag, ibo, value) \
- (flag |= DRW_ibo_requested(ibo) ? (value) : 0)
-#endif
-
-/* Test and assign NULL if test fails */
-#define DRW_TEST_ASSIGN_VBO(v) (v = (DRW_vbo_requested(v) ? (v) : NULL))
-#define DRW_TEST_ASSIGN_IBO(v) (v = (DRW_ibo_requested(v) ? (v) : NULL))
-
-struct GPUBatch *DRW_batch_request(struct GPUBatch **batch);
-bool DRW_batch_requested(struct GPUBatch *batch, int prim_type);
-void DRW_ibo_request(struct GPUBatch *batch, struct GPUIndexBuf **ibo);
-bool DRW_ibo_requested(struct GPUIndexBuf *ibo);
-void DRW_vbo_request(struct GPUBatch *batch, struct GPUVertBuf **vbo);
-bool DRW_vbo_requested(struct GPUVertBuf *vbo);
-
#endif /* __DRAW_CACHE_IMPL_H__ */
diff --git a/source/blender/draw/intern/draw_cache_impl_curve.c b/source/blender/draw/intern/draw_cache_impl_curve.c
index 33b872109a5..663fbf647a6 100644
--- a/source/blender/draw/intern/draw_cache_impl_curve.c
+++ b/source/blender/draw/intern/draw_cache_impl_curve.c
@@ -42,6 +42,8 @@
#include "DRW_render.h"
+#include "draw_cache_inline.h"
+
#include "draw_cache_impl.h" /* own include */
#define SELECT 1
@@ -472,12 +474,16 @@ static void curve_batch_cache_init(Curve *cu)
cache->is_dirty = false;
}
-static CurveBatchCache *curve_batch_cache_get(Curve *cu)
+void DRW_curve_batch_cache_validate(Curve *cu)
{
if (!curve_batch_cache_valid(cu)) {
curve_batch_cache_clear(cu);
curve_batch_cache_init(cu);
}
+}
+
+static CurveBatchCache *curve_batch_cache_get(Curve *cu)
+{
return cu->batch_cache;
}
diff --git a/source/blender/draw/intern/draw_cache_impl_displist.c b/source/blender/draw/intern/draw_cache_impl_displist.c
index ea394359b05..d1c214c2aa6 100644
--- a/source/blender/draw/intern/draw_cache_impl_displist.c
+++ b/source/blender/draw/intern/draw_cache_impl_displist.c
@@ -37,6 +37,8 @@
#include "GPU_batch.h"
#include "GPU_extensions.h"
+#include "draw_cache_inline.h"
+
#include "draw_cache_impl.h" /* own include */
static int dl_vert_len(const DispList *dl)
@@ -402,7 +404,6 @@ void DRW_displist_vertbuf_create_loop_pos_and_nor_and_uv(ListBase *lb,
&format_pos_nor, "pos", GPU_COMP_F32, 3, GPU_FETCH_FLOAT);
attr_id.nor = GPU_vertformat_attr_add(
&format_pos_nor, "nor", GPU_COMP_I10, 3, GPU_FETCH_INT_TO_FLOAT_UNIT);
- GPU_vertformat_triple_load(&format_pos_nor);
/* UVs are in [0..1] range. We can compress them. */
attr_id.uv = GPU_vertformat_attr_add(
&format_uv, "u", GPU_COMP_I16, 2, GPU_FETCH_INT_TO_FLOAT_UNIT);
diff --git a/source/blender/draw/intern/draw_cache_impl_lattice.c b/source/blender/draw/intern/draw_cache_impl_lattice.c
index b5223bc047c..8b3864684b5 100644
--- a/source/blender/draw/intern/draw_cache_impl_lattice.c
+++ b/source/blender/draw/intern/draw_cache_impl_lattice.c
@@ -340,12 +340,16 @@ static void lattice_batch_cache_init(Lattice *lt)
cache->is_dirty = false;
}
-static LatticeBatchCache *lattice_batch_cache_get(Lattice *lt)
+void DRW_lattice_batch_cache_validate(Lattice *lt)
{
if (!lattice_batch_cache_valid(lt)) {
lattice_batch_cache_clear(lt);
lattice_batch_cache_init(lt);
}
+}
+
+static LatticeBatchCache *lattice_batch_cache_get(Lattice *lt)
+{
return lt->batch_cache;
}
diff --git a/source/blender/draw/intern/draw_cache_impl_mesh.c b/source/blender/draw/intern/draw_cache_impl_mesh.c
index 1d8c7f0e5a7..9fb9f9713d1 100644
--- a/source/blender/draw/intern/draw_cache_impl_mesh.c
+++ b/source/blender/draw/intern/draw_cache_impl_mesh.c
@@ -61,6 +61,8 @@
#include "ED_mesh.h"
#include "ED_uvedit.h"
+#include "draw_cache_inline.h"
+
#include "draw_cache_impl.h" /* own include */
static void mesh_batch_cache_clear(Mesh *me);
@@ -421,13 +423,13 @@ static DRW_MeshCDMask mesh_cd_calc_used_gpu_layers(const Mesh *me,
const CustomData *cd_ldata = (me->edit_mesh) ? &me->edit_mesh->bm->ldata : &me->ldata;
/* See: DM_vertex_attributes_from_gpu for similar logic */
- GPUVertAttrLayers gpu_attrs = {{{0}}};
DRW_MeshCDMask cd_used;
mesh_cd_layers_type_clear(&cd_used);
for (int i = 0; i < gpumat_array_len; i++) {
GPUMaterial *gpumat = gpumat_array[i];
if (gpumat) {
+ GPUVertAttrLayers gpu_attrs;
GPU_material_vertex_attrs(gpumat, &gpu_attrs);
for (int j = 0; j < gpu_attrs.totlayer; j++) {
const char *name = gpu_attrs.layer[j].name;
@@ -1140,11 +1142,12 @@ static MeshRenderData *mesh_render_data_create_ex(Mesh *me,
rdata->cd.layers.tangent_len);
int i_dst = 0;
+ int act_tan = rdata->cd.layers.tangent_active;
for (int i_src = 0; i_src < cd_layers_src.uv_len; i_src++, i_dst++) {
if ((cd_used->tan & (1 << i_src)) == 0) {
i_dst--;
if (rdata->cd.layers.tangent_active >= i_src) {
- rdata->cd.layers.tangent_active--;
+ act_tan--;
}
}
else {
@@ -1168,6 +1171,11 @@ static MeshRenderData *mesh_render_data_create_ex(Mesh *me,
}
}
}
+ if (rdata->cd.layers.tangent_active != -1) {
+ /* Actual active UV slot inside uv layers used for shading. */
+ rdata->cd.layers.tangent_active = act_tan;
+ }
+
if (cd_used->tan_orco != 0) {
const char *name = CustomData_get_layer_name(&rdata->cd.output.ldata, CD_TANGENT, i_dst);
uint hash = BLI_ghashutil_strhash_p(name);
@@ -1892,6 +1900,39 @@ static void drw_mesh_weight_state_extract(Object *ob,
/** \name Mesh GPUBatch Cache
* \{ */
+typedef enum DRWBatchFlag {
+ MBC_SURFACE = (1 << 0),
+ MBC_SURFACE_WEIGHTS = (1 << 1),
+ MBC_EDIT_TRIANGLES = (1 << 2),
+ MBC_EDIT_VERTICES = (1 << 3),
+ MBC_EDIT_EDGES = (1 << 4),
+ MBC_EDIT_LNOR = (1 << 5),
+ MBC_EDIT_FACEDOTS = (1 << 6),
+ MBC_EDIT_MESH_ANALYSIS = (1 << 7),
+ MBC_EDITUV_FACES_STRECH_AREA = (1 << 8),
+ MBC_EDITUV_FACES_STRECH_ANGLE = (1 << 9),
+ MBC_EDITUV_FACES = (1 << 10),
+ MBC_EDITUV_EDGES = (1 << 11),
+ MBC_EDITUV_VERTS = (1 << 12),
+ MBC_EDITUV_FACEDOTS = (1 << 13),
+ MBC_EDIT_SELECTION_VERTS = (1 << 14),
+ MBC_EDIT_SELECTION_EDGES = (1 << 15),
+ MBC_EDIT_SELECTION_FACES = (1 << 16),
+ MBC_EDIT_SELECTION_FACEDOTS = (1 << 17),
+ MBC_ALL_VERTS = (1 << 18),
+ MBC_ALL_EDGES = (1 << 19),
+ MBC_LOOSE_EDGES = (1 << 20),
+ MBC_EDGE_DETECTION = (1 << 21),
+ MBC_WIRE_EDGES = (1 << 22),
+ MBC_WIRE_LOOPS = (1 << 23),
+ MBC_WIRE_LOOPS_UVS = (1 << 24),
+ MBC_SURF_PER_MAT = (1 << 25),
+} DRWBatchFlag;
+
+#define MBC_EDITUV \
+ (MBC_EDITUV_FACES_STRECH_AREA | MBC_EDITUV_FACES_STRECH_ANGLE | MBC_EDITUV_FACES | \
+ MBC_EDITUV_EDGES | MBC_EDITUV_VERTS | MBC_EDITUV_FACEDOTS)
+
typedef struct MeshBatchCache {
/* In order buffers: All verts only specified once
* or once per loop. To be used with a GPUIndexBuf. */
@@ -1997,14 +2038,16 @@ typedef struct MeshBatchCache {
int *auto_layer_is_srgb;
int auto_layer_len;
+ DRWBatchFlag batch_requested;
+ DRWBatchFlag batch_ready;
+
/* settings to determine if cache is invalid */
- bool is_maybe_dirty;
- bool is_dirty; /* Instantly invalidates cache, skipping mesh check */
int edge_len;
int tri_len;
int poly_len;
int vert_len;
int mat_len;
+ bool is_dirty; /* Instantly invalidates cache, skipping mesh check */
bool is_editmode;
bool is_uvsyncsel;
@@ -2014,13 +2057,15 @@ typedef struct MeshBatchCache {
int lastmatch;
- /* XXX, only keep for as long as sculpt mode uses shaded drawing. */
- bool is_sculpt_points_tag;
-
/* Valid only if edge_detection is up to date. */
bool is_manifold;
} MeshBatchCache;
+BLI_INLINE void mesh_batch_cache_add_request(MeshBatchCache *cache, DRWBatchFlag new_flag)
+{
+ atomic_fetch_and_or_uint32((uint32_t *)(&cache->batch_requested), *(uint32_t *)&new_flag);
+}
+
/* GPUBatch cache management. */
static bool mesh_batch_cache_valid(Mesh *me)
@@ -2031,10 +2076,6 @@ static bool mesh_batch_cache_valid(Mesh *me)
return false;
}
- if (cache->mat_len != mesh_render_mat_len_get(me)) {
- return false;
- }
-
if (cache->is_editmode != (me->edit_mesh != NULL)) {
return false;
}
@@ -2043,20 +2084,8 @@ static bool mesh_batch_cache_valid(Mesh *me)
return false;
}
- if (cache->is_maybe_dirty == false) {
- return true;
- }
- else {
- if (cache->is_editmode) {
- return false;
- }
- else if ((cache->vert_len != mesh_render_verts_len_get(me)) ||
- (cache->edge_len != mesh_render_edges_len_get(me)) ||
- (cache->tri_len != mesh_render_looptri_len_get(me)) ||
- (cache->poly_len != mesh_render_polys_len_get(me)) ||
- (cache->mat_len != mesh_render_mat_len_get(me))) {
- return false;
- }
+ if (cache->mat_len != mesh_render_mat_len_get(me)) {
+ return false;
}
return true;
@@ -2087,18 +2116,23 @@ static void mesh_batch_cache_init(Mesh *me)
__func__);
cache->surf_per_mat = MEM_callocN(sizeof(*cache->surf_per_mat) * cache->mat_len, __func__);
- cache->is_maybe_dirty = false;
cache->is_dirty = false;
+ cache->batch_ready = 0;
+ cache->batch_requested = 0;
drw_mesh_weight_state_clear(&cache->weight_state);
}
-static MeshBatchCache *mesh_batch_cache_get(Mesh *me)
+void DRW_mesh_batch_cache_validate(Mesh *me)
{
if (!mesh_batch_cache_valid(me)) {
mesh_batch_cache_clear(me);
mesh_batch_cache_init(me);
}
+}
+
+static MeshBatchCache *mesh_batch_cache_get(Mesh *me)
+{
return me->runtime.batch_cache;
}
@@ -2109,6 +2143,8 @@ static void mesh_batch_cache_check_vertex_group(MeshBatchCache *cache,
GPU_BATCH_CLEAR_SAFE(cache->batch.surface_weights);
GPU_VERTBUF_DISCARD_SAFE(cache->ordered.weights);
+ cache->batch_ready &= ~MBC_SURFACE_WEIGHTS;
+
drw_mesh_weight_state_clear(&cache->weight_state);
}
}
@@ -2133,6 +2169,8 @@ static void mesh_batch_cache_discard_shaded_tri(MeshBatchCache *cache)
}
MEM_SAFE_FREE(cache->surf_per_mat);
+ cache->batch_ready &= ~MBC_SURF_PER_MAT;
+
MEM_SAFE_FREE(cache->auto_layer_names);
MEM_SAFE_FREE(cache->auto_layer_is_srgb);
@@ -2158,6 +2196,8 @@ static void mesh_batch_cache_discard_uvedit(MeshBatchCache *cache)
GPU_BATCH_DISCARD_SAFE(cache->batch.edituv_edges);
GPU_BATCH_DISCARD_SAFE(cache->batch.edituv_verts);
GPU_BATCH_DISCARD_SAFE(cache->batch.edituv_facedots);
+
+ cache->batch_ready &= ~MBC_EDITUV;
}
void DRW_mesh_batch_cache_dirty_tag(Mesh *me, int mode)
@@ -2167,9 +2207,6 @@ void DRW_mesh_batch_cache_dirty_tag(Mesh *me, int mode)
return;
}
switch (mode) {
- case BKE_MESH_BATCH_DIRTY_MAYBE_ALL:
- cache->is_maybe_dirty = true;
- break;
case BKE_MESH_BATCH_DIRTY_SELECT:
GPU_VERTBUF_DISCARD_SAFE(cache->edit.loop_data);
GPU_VERTBUF_DISCARD_SAFE(cache->edit.facedots_pos_nor_data);
@@ -2177,7 +2214,11 @@ void DRW_mesh_batch_cache_dirty_tag(Mesh *me, int mode)
GPU_BATCH_DISCARD_SAFE(cache->batch.edit_vertices);
GPU_BATCH_DISCARD_SAFE(cache->batch.edit_edges);
GPU_BATCH_DISCARD_SAFE(cache->batch.edit_facedots);
+ GPU_BATCH_DISCARD_SAFE(cache->batch.edit_selection_facedots);
GPU_BATCH_DISCARD_SAFE(cache->batch.edit_mesh_analysis);
+ cache->batch_ready &= ~(MBC_EDIT_TRIANGLES | MBC_EDIT_VERTICES | MBC_EDIT_EDGES |
+ MBC_EDIT_FACEDOTS | MBC_EDIT_SELECTION_FACEDOTS |
+ MBC_EDIT_MESH_ANALYSIS);
/* Because visible UVs depends on edit mode selection, discard everything. */
mesh_batch_cache_discard_uvedit(cache);
break;
@@ -2192,6 +2233,7 @@ void DRW_mesh_batch_cache_dirty_tag(Mesh *me, int mode)
GPU_BATCH_DISCARD_SAFE(cache->surf_per_mat[i]);
}
}
+ cache->batch_ready &= ~(MBC_SURFACE | MBC_WIRE_LOOPS | MBC_SURF_PER_MAT);
break;
case BKE_MESH_BATCH_DIRTY_ALL:
cache->is_dirty = true;
@@ -2200,9 +2242,6 @@ void DRW_mesh_batch_cache_dirty_tag(Mesh *me, int mode)
mesh_batch_cache_discard_shaded_tri(cache);
mesh_batch_cache_discard_uvedit(cache);
break;
- case BKE_MESH_BATCH_DIRTY_SCULPT_COORDS:
- cache->is_sculpt_points_tag = true;
- break;
case BKE_MESH_BATCH_DIRTY_UVEDIT_ALL:
mesh_batch_cache_discard_uvedit(cache);
break;
@@ -2215,6 +2254,7 @@ void DRW_mesh_batch_cache_dirty_tag(Mesh *me, int mode)
GPU_BATCH_DISCARD_SAFE(cache->batch.edituv_edges);
GPU_BATCH_DISCARD_SAFE(cache->batch.edituv_verts);
GPU_BATCH_DISCARD_SAFE(cache->batch.edituv_facedots);
+ cache->batch_ready &= ~MBC_EDITUV;
break;
default:
BLI_assert(0);
@@ -2249,6 +2289,8 @@ static void mesh_batch_cache_clear(Mesh *me)
mesh_batch_cache_discard_uvedit(cache);
+ cache->batch_ready = 0;
+
drw_mesh_weight_state_clear(&cache->weight_state);
}
@@ -4227,36 +4269,42 @@ static void texpaint_request_active_vcol(MeshBatchCache *cache, Mesh *me)
GPUBatch *DRW_mesh_batch_cache_get_all_verts(Mesh *me)
{
MeshBatchCache *cache = mesh_batch_cache_get(me);
+ mesh_batch_cache_add_request(cache, MBC_ALL_VERTS);
return DRW_batch_request(&cache->batch.all_verts);
}
GPUBatch *DRW_mesh_batch_cache_get_all_edges(Mesh *me)
{
MeshBatchCache *cache = mesh_batch_cache_get(me);
+ mesh_batch_cache_add_request(cache, MBC_ALL_EDGES);
return DRW_batch_request(&cache->batch.all_edges);
}
GPUBatch *DRW_mesh_batch_cache_get_surface(Mesh *me)
{
MeshBatchCache *cache = mesh_batch_cache_get(me);
+ mesh_batch_cache_add_request(cache, MBC_SURFACE);
return DRW_batch_request(&cache->batch.surface);
}
GPUBatch *DRW_mesh_batch_cache_get_loose_edges(Mesh *me)
{
MeshBatchCache *cache = mesh_batch_cache_get(me);
+ mesh_batch_cache_add_request(cache, MBC_LOOSE_EDGES);
return DRW_batch_request(&cache->batch.loose_edges);
}
GPUBatch *DRW_mesh_batch_cache_get_surface_weights(Mesh *me)
{
MeshBatchCache *cache = mesh_batch_cache_get(me);
+ mesh_batch_cache_add_request(cache, MBC_SURFACE_WEIGHTS);
return DRW_batch_request(&cache->batch.surface_weights);
}
GPUBatch *DRW_mesh_batch_cache_get_edge_detection(Mesh *me, bool *r_is_manifold)
{
MeshBatchCache *cache = mesh_batch_cache_get(me);
+ mesh_batch_cache_add_request(cache, MBC_EDGE_DETECTION);
/* Even if is_manifold is not correct (not updated),
* the default (not manifold) is just the worst case. */
if (r_is_manifold) {
@@ -4268,12 +4316,14 @@ GPUBatch *DRW_mesh_batch_cache_get_edge_detection(Mesh *me, bool *r_is_manifold)
GPUBatch *DRW_mesh_batch_cache_get_wireframes_face(Mesh *me)
{
MeshBatchCache *cache = mesh_batch_cache_get(me);
+ mesh_batch_cache_add_request(cache, MBC_WIRE_EDGES);
return DRW_batch_request(&cache->batch.wire_edges);
}
GPUBatch *DRW_mesh_batch_cache_get_edit_mesh_analysis(Mesh *me)
{
MeshBatchCache *cache = mesh_batch_cache_get(me);
+ mesh_batch_cache_add_request(cache, MBC_EDIT_MESH_ANALYSIS);
return DRW_batch_request(&cache->batch.edit_mesh_analysis);
}
@@ -4299,6 +4349,8 @@ GPUBatch **DRW_mesh_batch_cache_get_surface_shaded(Mesh *me,
&cache->auto_layer_len);
}
+ mesh_batch_cache_add_request(cache, MBC_SURF_PER_MAT);
+
if (auto_layer_names) {
*auto_layer_names = cache->auto_layer_names;
*auto_layer_is_srgb = cache->auto_layer_is_srgb;
@@ -4313,6 +4365,7 @@ GPUBatch **DRW_mesh_batch_cache_get_surface_shaded(Mesh *me,
GPUBatch **DRW_mesh_batch_cache_get_surface_texpaint(Mesh *me)
{
MeshBatchCache *cache = mesh_batch_cache_get(me);
+ mesh_batch_cache_add_request(cache, MBC_SURF_PER_MAT);
texpaint_request_active_uv(cache, me);
for (int i = 0; i < cache->mat_len; ++i) {
DRW_batch_request(&cache->surf_per_mat[i]);
@@ -4324,6 +4377,7 @@ GPUBatch *DRW_mesh_batch_cache_get_surface_texpaint_single(Mesh *me)
{
MeshBatchCache *cache = mesh_batch_cache_get(me);
texpaint_request_active_uv(cache, me);
+ mesh_batch_cache_add_request(cache, MBC_SURFACE);
return DRW_batch_request(&cache->batch.surface);
}
@@ -4331,6 +4385,7 @@ GPUBatch *DRW_mesh_batch_cache_get_surface_vertpaint(Mesh *me)
{
MeshBatchCache *cache = mesh_batch_cache_get(me);
texpaint_request_active_vcol(cache, me);
+ mesh_batch_cache_add_request(cache, MBC_SURFACE);
return DRW_batch_request(&cache->batch.surface);
}
@@ -4343,30 +4398,35 @@ GPUBatch *DRW_mesh_batch_cache_get_surface_vertpaint(Mesh *me)
GPUBatch *DRW_mesh_batch_cache_get_edit_triangles(Mesh *me)
{
MeshBatchCache *cache = mesh_batch_cache_get(me);
+ mesh_batch_cache_add_request(cache, MBC_EDIT_TRIANGLES);
return DRW_batch_request(&cache->batch.edit_triangles);
}
GPUBatch *DRW_mesh_batch_cache_get_edit_edges(Mesh *me)
{
MeshBatchCache *cache = mesh_batch_cache_get(me);
+ mesh_batch_cache_add_request(cache, MBC_EDIT_EDGES);
return DRW_batch_request(&cache->batch.edit_edges);
}
GPUBatch *DRW_mesh_batch_cache_get_edit_vertices(Mesh *me)
{
MeshBatchCache *cache = mesh_batch_cache_get(me);
+ mesh_batch_cache_add_request(cache, MBC_EDIT_VERTICES);
return DRW_batch_request(&cache->batch.edit_vertices);
}
GPUBatch *DRW_mesh_batch_cache_get_edit_lnors(Mesh *me)
{
MeshBatchCache *cache = mesh_batch_cache_get(me);
+ mesh_batch_cache_add_request(cache, MBC_EDIT_LNOR);
return DRW_batch_request(&cache->batch.edit_lnor);
}
GPUBatch *DRW_mesh_batch_cache_get_edit_facedots(Mesh *me)
{
MeshBatchCache *cache = mesh_batch_cache_get(me);
+ mesh_batch_cache_add_request(cache, MBC_EDIT_FACEDOTS);
return DRW_batch_request(&cache->batch.edit_facedots);
}
@@ -4379,24 +4439,28 @@ GPUBatch *DRW_mesh_batch_cache_get_edit_facedots(Mesh *me)
GPUBatch *DRW_mesh_batch_cache_get_triangles_with_select_id(Mesh *me)
{
MeshBatchCache *cache = mesh_batch_cache_get(me);
+ mesh_batch_cache_add_request(cache, MBC_EDIT_SELECTION_FACES);
return DRW_batch_request(&cache->batch.edit_selection_faces);
}
GPUBatch *DRW_mesh_batch_cache_get_facedots_with_select_id(Mesh *me)
{
MeshBatchCache *cache = mesh_batch_cache_get(me);
+ mesh_batch_cache_add_request(cache, MBC_EDIT_SELECTION_FACEDOTS);
return DRW_batch_request(&cache->batch.edit_selection_facedots);
}
GPUBatch *DRW_mesh_batch_cache_get_edges_with_select_id(Mesh *me)
{
MeshBatchCache *cache = mesh_batch_cache_get(me);
+ mesh_batch_cache_add_request(cache, MBC_EDIT_SELECTION_EDGES);
return DRW_batch_request(&cache->batch.edit_selection_edges);
}
GPUBatch *DRW_mesh_batch_cache_get_verts_with_select_id(Mesh *me)
{
MeshBatchCache *cache = mesh_batch_cache_get(me);
+ mesh_batch_cache_add_request(cache, MBC_EDIT_SELECTION_VERTS);
return DRW_batch_request(&cache->batch.edit_selection_verts);
}
@@ -4409,36 +4473,42 @@ GPUBatch *DRW_mesh_batch_cache_get_verts_with_select_id(Mesh *me)
GPUBatch *DRW_mesh_batch_cache_get_edituv_faces_strech_area(Mesh *me)
{
MeshBatchCache *cache = mesh_batch_cache_get(me);
+ mesh_batch_cache_add_request(cache, MBC_EDITUV_FACES_STRECH_AREA);
return DRW_batch_request(&cache->batch.edituv_faces_strech_area);
}
GPUBatch *DRW_mesh_batch_cache_get_edituv_faces_strech_angle(Mesh *me)
{
MeshBatchCache *cache = mesh_batch_cache_get(me);
+ mesh_batch_cache_add_request(cache, MBC_EDITUV_FACES_STRECH_ANGLE);
return DRW_batch_request(&cache->batch.edituv_faces_strech_angle);
}
GPUBatch *DRW_mesh_batch_cache_get_edituv_faces(Mesh *me)
{
MeshBatchCache *cache = mesh_batch_cache_get(me);
+ mesh_batch_cache_add_request(cache, MBC_EDITUV_FACES);
return DRW_batch_request(&cache->batch.edituv_faces);
}
GPUBatch *DRW_mesh_batch_cache_get_edituv_edges(Mesh *me)
{
MeshBatchCache *cache = mesh_batch_cache_get(me);
+ mesh_batch_cache_add_request(cache, MBC_EDITUV_EDGES);
return DRW_batch_request(&cache->batch.edituv_edges);
}
GPUBatch *DRW_mesh_batch_cache_get_edituv_verts(Mesh *me)
{
MeshBatchCache *cache = mesh_batch_cache_get(me);
+ mesh_batch_cache_add_request(cache, MBC_EDITUV_VERTS);
return DRW_batch_request(&cache->batch.edituv_verts);
}
GPUBatch *DRW_mesh_batch_cache_get_edituv_facedots(Mesh *me)
{
MeshBatchCache *cache = mesh_batch_cache_get(me);
+ mesh_batch_cache_add_request(cache, MBC_EDITUV_FACEDOTS);
return DRW_batch_request(&cache->batch.edituv_facedots);
}
@@ -4446,34 +4516,17 @@ GPUBatch *DRW_mesh_batch_cache_get_uv_edges(Mesh *me)
{
MeshBatchCache *cache = mesh_batch_cache_get(me);
texpaint_request_active_uv(cache, me);
+ mesh_batch_cache_add_request(cache, MBC_WIRE_LOOPS_UVS);
return DRW_batch_request(&cache->batch.wire_loops_uvs);
}
GPUBatch *DRW_mesh_batch_cache_get_surface_edges(Mesh *me)
{
MeshBatchCache *cache = mesh_batch_cache_get(me);
+ mesh_batch_cache_add_request(cache, MBC_WIRE_LOOPS);
return DRW_batch_request(&cache->batch.wire_loops);
}
-/**
- * Needed for when we draw with shaded data.
- */
-void DRW_mesh_cache_sculpt_coords_ensure(Mesh *UNUSED(me))
-{
-#if 0 /* Unused for now */
- if (me->runtime.batch_cache) {
- MeshBatchCache *cache = mesh_batch_cache_get(me);
- if (cache && cache->pos_with_normals && cache->is_sculpt_points_tag) {
- /* XXX Force update of all the batches that contains the pos_with_normals buffer.
- * TODO(fclem): Ideally, Gawain should provide a way to update a buffer without destroying it. */
- mesh_batch_cache_clear_selective(me, cache->pos_with_normals);
- GPU_VERTBUF_DISCARD_SAFE(cache->pos_with_normals);
- }
- cache->is_sculpt_points_tag = false;
- }
-#endif
-}
-
/* Compute 3D & 2D areas and their sum. */
BLI_INLINE void edit_uv_preprocess_stretch_area(BMFace *efa,
const int cd_loop_uv_offset,
@@ -4688,14 +4741,18 @@ static void uvedit_fill_buffer_data(MeshRenderData *rdata,
GPU_indexbuf_add_generic_vert(elb_face, vidx);
GPU_indexbuf_add_primitive_restart(elb_face);
}
- if (elb_edge && e_origindex[l[i].e] != ORIGINDEX_NONE) {
+ if (elb_edge) {
for (i = 0; i < mpoly->totloop; ++i) {
- GPU_indexbuf_add_line_verts(elb_edge, vidx + i, vidx + (i + 1) % mpoly->totloop);
+ if (e_origindex[l[i].e] != ORIGINDEX_NONE) {
+ GPU_indexbuf_add_line_verts(elb_edge, vidx + i, vidx + (i + 1) % mpoly->totloop);
+ }
}
}
- if (elb_vert && v_origindex[l[i].v] != ORIGINDEX_NONE) {
+ if (elb_vert) {
for (i = 0; i < mpoly->totloop; ++i) {
- GPU_indexbuf_add_generic_vert(elb_vert, vidx + i);
+ if (v_origindex[l[i].v] != ORIGINDEX_NONE) {
+ GPU_indexbuf_add_generic_vert(elb_vert, vidx + i);
+ }
}
}
}
@@ -4850,82 +4907,113 @@ void DRW_mesh_batch_cache_create_requested(
{
MeshBatchCache *cache = mesh_batch_cache_get(me);
- /* Check vertex weights. */
- if ((cache->batch.surface_weights != 0) && (ts != NULL)) {
- struct DRW_MeshWeightState wstate;
- BLI_assert(ob->type == OB_MESH);
- drw_mesh_weight_state_extract(ob, me, ts, is_paint_mode, &wstate);
- mesh_batch_cache_check_vertex_group(cache, &wstate);
- drw_mesh_weight_state_copy(&cache->weight_state, &wstate);
- drw_mesh_weight_state_clear(&wstate);
+ /* Early out */
+ if (cache->batch_requested == 0) {
+#ifdef DEBUG
+ goto check;
+#endif
+ return;
}
- /* Optimization : Only create orco layer if mesh is deformed. */
- if (cache->cd_needed.orco != 0) {
- CustomData *cd_vdata = (me->edit_mesh) ? &me->edit_mesh->bm->vdata : &me->vdata;
- if (CustomData_get_layer(cd_vdata, CD_ORCO) != NULL && ob->modifiers.first != NULL) {
- /* Orco layer is needed. */
- }
- else if (cache->cd_needed.tan_orco == 0) {
- /* Skip orco calculation if not needed by tangent generation. */
- cache->cd_needed.orco = 0;
+ DRWBatchFlag batch_requested = cache->batch_requested;
+ cache->batch_requested = 0;
+
+ if (batch_requested & MBC_SURFACE_WEIGHTS) {
+ /* Check vertex weights. */
+ if ((cache->batch.surface_weights != NULL) && (ts != NULL)) {
+ struct DRW_MeshWeightState wstate;
+ BLI_assert(ob->type == OB_MESH);
+ drw_mesh_weight_state_extract(ob, me, ts, is_paint_mode, &wstate);
+ mesh_batch_cache_check_vertex_group(cache, &wstate);
+ drw_mesh_weight_state_copy(&cache->weight_state, &wstate);
+ drw_mesh_weight_state_clear(&wstate);
}
}
- /* Verify that all surface batches have needed attribute layers. */
- /* TODO(fclem): We could be a bit smarter here and only do it per material. */
- bool cd_overlap = mesh_cd_layers_type_overlap(cache->cd_used, cache->cd_needed);
- if (cd_overlap == false) {
- if ((cache->cd_used.uv & cache->cd_needed.uv) != cache->cd_needed.uv ||
- (cache->cd_used.tan & cache->cd_needed.tan) != cache->cd_needed.tan ||
- cache->cd_used.tan_orco != cache->cd_needed.tan_orco) {
- GPU_VERTBUF_DISCARD_SAFE(cache->ordered.loop_uv_tan);
- }
- if (cache->cd_used.orco != cache->cd_needed.orco) {
- GPU_VERTBUF_DISCARD_SAFE(cache->ordered.loop_orco);
+ if (batch_requested & (MBC_SURFACE | MBC_SURF_PER_MAT | MBC_WIRE_LOOPS_UVS)) {
+ /* Optimization : Only create orco layer if mesh is deformed. */
+ if (cache->cd_needed.orco != 0) {
+ CustomData *cd_vdata = (me->edit_mesh) ? &me->edit_mesh->bm->vdata : &me->vdata;
+ if (CustomData_get_layer(cd_vdata, CD_ORCO) != NULL && ob->modifiers.first != NULL) {
+ /* Orco layer is needed. */
+ }
+ else if (cache->cd_needed.tan_orco == 0) {
+ /* Skip orco calculation if not needed by tangent generation.
+ */
+ cache->cd_needed.orco = 0;
+ }
}
- if ((cache->cd_used.vcol & cache->cd_needed.vcol) != cache->cd_needed.vcol) {
- GPU_VERTBUF_DISCARD_SAFE(cache->ordered.loop_vcol);
+
+ /* Verify that all surface batches have needed attribute layers.
+ */
+ /* TODO(fclem): We could be a bit smarter here and only do it per
+ * material. */
+ bool cd_overlap = mesh_cd_layers_type_overlap(cache->cd_used, cache->cd_needed);
+ if (cd_overlap == false) {
+ if ((cache->cd_used.uv & cache->cd_needed.uv) != cache->cd_needed.uv ||
+ (cache->cd_used.tan & cache->cd_needed.tan) != cache->cd_needed.tan ||
+ cache->cd_used.tan_orco != cache->cd_needed.tan_orco) {
+ GPU_VERTBUF_DISCARD_SAFE(cache->ordered.loop_uv_tan);
+ }
+ if (cache->cd_used.orco != cache->cd_needed.orco) {
+ GPU_VERTBUF_DISCARD_SAFE(cache->ordered.loop_orco);
+ }
+ if ((cache->cd_used.vcol & cache->cd_needed.vcol) != cache->cd_needed.vcol) {
+ GPU_VERTBUF_DISCARD_SAFE(cache->ordered.loop_vcol);
+ }
+ /* We can't discard batches at this point as they have been
+ * referenced for drawing. Just clear them in place. */
+ for (int i = 0; i < cache->mat_len; ++i) {
+ GPU_BATCH_CLEAR_SAFE(cache->surf_per_mat[i]);
+ }
+ GPU_BATCH_CLEAR_SAFE(cache->batch.surface);
+ cache->batch_ready &= ~(MBC_SURFACE | MBC_SURF_PER_MAT);
+
+ mesh_cd_layers_type_merge(&cache->cd_used, cache->cd_needed);
}
- /* We can't discard batches at this point as they have been
- * referenced for drawing. Just clear them in place. */
- for (int i = 0; i < cache->mat_len; ++i) {
- GPU_BATCH_CLEAR_SAFE(cache->surf_per_mat[i]);
+ mesh_cd_layers_type_merge(&cache->cd_used_over_time, cache->cd_needed);
+ mesh_cd_layers_type_clear(&cache->cd_needed);
+ }
+
+ if (batch_requested & MBC_EDITUV) {
+ /* Discard UV batches if sync_selection changes */
+ if (ts != NULL) {
+ const bool is_uvsyncsel = (ts->uv_flag & UV_SYNC_SELECTION);
+ if (cache->is_uvsyncsel != is_uvsyncsel) {
+ cache->is_uvsyncsel = is_uvsyncsel;
+ GPU_VERTBUF_DISCARD_SAFE(cache->edit.loop_uv_data);
+ GPU_VERTBUF_DISCARD_SAFE(cache->edit.loop_stretch_angle);
+ GPU_VERTBUF_DISCARD_SAFE(cache->edit.loop_stretch_area);
+ GPU_VERTBUF_DISCARD_SAFE(cache->edit.loop_uv);
+ GPU_VERTBUF_DISCARD_SAFE(cache->edit.facedots_uv);
+ GPU_INDEXBUF_DISCARD_SAFE(cache->ibo.edituv_loops_tri_fans);
+ GPU_INDEXBUF_DISCARD_SAFE(cache->ibo.edituv_loops_line_strips);
+ GPU_INDEXBUF_DISCARD_SAFE(cache->ibo.edituv_loops_points);
+ /* We only clear the batches as they may already have been
+ * referenced. */
+ GPU_BATCH_CLEAR_SAFE(cache->batch.edituv_faces_strech_area);
+ GPU_BATCH_CLEAR_SAFE(cache->batch.edituv_faces_strech_angle);
+ GPU_BATCH_CLEAR_SAFE(cache->batch.edituv_faces);
+ GPU_BATCH_CLEAR_SAFE(cache->batch.edituv_edges);
+ GPU_BATCH_CLEAR_SAFE(cache->batch.edituv_verts);
+ GPU_BATCH_CLEAR_SAFE(cache->batch.edituv_facedots);
+ cache->batch_ready &= ~MBC_EDITUV;
+ }
}
- GPU_BATCH_CLEAR_SAFE(cache->batch.surface);
+ }
- mesh_cd_layers_type_merge(&cache->cd_used, cache->cd_needed);
+ /* Second chance to early out */
+ if ((batch_requested & ~cache->batch_ready) == 0) {
+#ifdef DEBUG
+ goto check;
+#endif
+ return;
}
- mesh_cd_layers_type_merge(&cache->cd_used_over_time, cache->cd_needed);
- mesh_cd_layers_type_clear(&cache->cd_needed);
- /* Discard UV batches if sync_selection changes */
- if (ts != NULL) {
- const bool is_uvsyncsel = (ts->uv_flag & UV_SYNC_SELECTION);
- if (cache->is_uvsyncsel != is_uvsyncsel) {
- cache->is_uvsyncsel = is_uvsyncsel;
- GPU_VERTBUF_DISCARD_SAFE(cache->edit.loop_uv_data);
- GPU_VERTBUF_DISCARD_SAFE(cache->edit.loop_stretch_angle);
- GPU_VERTBUF_DISCARD_SAFE(cache->edit.loop_stretch_area);
- GPU_VERTBUF_DISCARD_SAFE(cache->edit.loop_uv);
- GPU_VERTBUF_DISCARD_SAFE(cache->edit.facedots_uv);
- GPU_INDEXBUF_DISCARD_SAFE(cache->ibo.edituv_loops_tri_fans);
- GPU_INDEXBUF_DISCARD_SAFE(cache->ibo.edituv_loops_line_strips);
- GPU_INDEXBUF_DISCARD_SAFE(cache->ibo.edituv_loops_points);
- /* We only clear the batches as they may already have been referenced. */
- GPU_BATCH_CLEAR_SAFE(cache->batch.edituv_faces_strech_area);
- GPU_BATCH_CLEAR_SAFE(cache->batch.edituv_faces_strech_angle);
- GPU_BATCH_CLEAR_SAFE(cache->batch.edituv_faces);
- GPU_BATCH_CLEAR_SAFE(cache->batch.edituv_edges);
- GPU_BATCH_CLEAR_SAFE(cache->batch.edituv_verts);
- GPU_BATCH_CLEAR_SAFE(cache->batch.edituv_facedots);
- }
- }
-
- bool has_request = false;
+ cache->batch_ready |= batch_requested;
+
/* Init batches and request VBOs & IBOs */
if (DRW_batch_requested(cache->batch.surface, GPU_PRIM_TRIS)) {
- has_request = true;
DRW_ibo_request(cache->batch.surface, &cache->ibo.loops_tris);
DRW_vbo_request(cache->batch.surface, &cache->ordered.loop_pos_nor);
/* For paint overlay. Active layer should have been queried. */
@@ -4937,43 +5025,35 @@ void DRW_mesh_batch_cache_create_requested(
}
}
if (DRW_batch_requested(cache->batch.all_verts, GPU_PRIM_POINTS)) {
- has_request = true;
DRW_vbo_request(cache->batch.all_verts, &cache->ordered.pos_nor);
}
if (DRW_batch_requested(cache->batch.all_edges, GPU_PRIM_LINES)) {
- has_request = true;
DRW_ibo_request(cache->batch.all_edges, &cache->ibo.edges_lines);
DRW_vbo_request(cache->batch.all_edges, &cache->ordered.pos_nor);
}
if (DRW_batch_requested(cache->batch.loose_edges, GPU_PRIM_LINES)) {
- has_request = true;
DRW_ibo_request(cache->batch.loose_edges, &cache->ibo.loose_edges_lines);
DRW_vbo_request(cache->batch.loose_edges, &cache->ordered.pos_nor);
}
if (DRW_batch_requested(cache->batch.edge_detection, GPU_PRIM_LINES_ADJ)) {
- has_request = true;
DRW_ibo_request(cache->batch.edge_detection, &cache->ibo.edges_adj_lines);
DRW_vbo_request(cache->batch.edge_detection, &cache->ordered.pos_nor);
}
if (DRW_batch_requested(cache->batch.surface_weights, GPU_PRIM_TRIS)) {
- has_request = true;
DRW_ibo_request(cache->batch.surface_weights, &cache->ibo.surf_tris);
DRW_vbo_request(cache->batch.surface_weights, &cache->ordered.pos_nor);
DRW_vbo_request(cache->batch.surface_weights, &cache->ordered.weights);
}
if (DRW_batch_requested(cache->batch.wire_loops, GPU_PRIM_LINE_STRIP)) {
- has_request = true;
DRW_ibo_request(cache->batch.wire_loops, &cache->ibo.loops_line_strips);
DRW_vbo_request(cache->batch.wire_loops, &cache->ordered.loop_pos_nor);
}
if (DRW_batch_requested(cache->batch.wire_edges, GPU_PRIM_LINES)) {
- has_request = true;
DRW_ibo_request(cache->batch.wire_edges, &cache->ibo.loops_lines);
DRW_vbo_request(cache->batch.wire_edges, &cache->ordered.loop_pos_nor);
DRW_vbo_request(cache->batch.wire_edges, &cache->ordered.loop_edge_fac);
}
if (DRW_batch_requested(cache->batch.wire_loops_uvs, GPU_PRIM_LINE_STRIP)) {
- has_request = true;
DRW_ibo_request(cache->batch.wire_loops_uvs, &cache->ibo.loops_line_strips);
/* For paint overlay. Active layer should have been queried. */
if (cache->cd_used.uv != 0) {
@@ -4983,37 +5063,31 @@ void DRW_mesh_batch_cache_create_requested(
/* Edit Mesh */
if (DRW_batch_requested(cache->batch.edit_triangles, GPU_PRIM_TRIS)) {
- has_request = true;
DRW_ibo_request(cache->batch.edit_triangles, &cache->ibo.edit_loops_tris);
DRW_vbo_request(cache->batch.edit_triangles, &cache->edit.loop_pos_nor);
DRW_vbo_request(cache->batch.edit_triangles, &cache->edit.loop_data);
}
if (DRW_batch_requested(cache->batch.edit_vertices, GPU_PRIM_POINTS)) {
- has_request = true;
DRW_ibo_request(cache->batch.edit_vertices, &cache->ibo.edit_loops_points);
DRW_vbo_request(cache->batch.edit_vertices, &cache->edit.loop_pos_nor);
DRW_vbo_request(cache->batch.edit_vertices, &cache->edit.loop_data);
}
if (DRW_batch_requested(cache->batch.edit_edges, GPU_PRIM_LINES)) {
- has_request = true;
DRW_ibo_request(cache->batch.edit_edges, &cache->ibo.edit_loops_lines);
DRW_vbo_request(cache->batch.edit_edges, &cache->edit.loop_pos_nor);
DRW_vbo_request(cache->batch.edit_edges, &cache->edit.loop_data);
}
if (DRW_batch_requested(cache->batch.edit_lnor, GPU_PRIM_POINTS)) {
- has_request = true;
DRW_ibo_request(cache->batch.edit_lnor, &cache->ibo.edit_loops_tris);
DRW_vbo_request(cache->batch.edit_lnor, &cache->edit.loop_pos_nor);
DRW_vbo_request(cache->batch.edit_lnor, &cache->edit.loop_lnor);
}
if (DRW_batch_requested(cache->batch.edit_facedots, GPU_PRIM_POINTS)) {
- has_request = true;
DRW_vbo_request(cache->batch.edit_facedots, &cache->edit.facedots_pos_nor_data);
}
/* Mesh Analysis */
if (DRW_batch_requested(cache->batch.edit_mesh_analysis, GPU_PRIM_TRIS)) {
- has_request = true;
DRW_ibo_request(cache->batch.edit_mesh_analysis, &cache->ibo.edit_loops_tris);
DRW_vbo_request(cache->batch.edit_mesh_analysis, &cache->edit.loop_pos_nor);
DRW_vbo_request(cache->batch.edit_mesh_analysis, &cache->edit.loop_mesh_analysis);
@@ -5021,39 +5095,33 @@ void DRW_mesh_batch_cache_create_requested(
/* Edit UV */
if (DRW_batch_requested(cache->batch.edituv_faces, GPU_PRIM_TRI_FAN)) {
- has_request = true;
DRW_ibo_request(cache->batch.edituv_faces, &cache->ibo.edituv_loops_tri_fans);
DRW_vbo_request(cache->batch.edituv_faces, &cache->edit.loop_uv);
DRW_vbo_request(cache->batch.edituv_faces, &cache->edit.loop_uv_data);
}
if (DRW_batch_requested(cache->batch.edituv_faces_strech_area, GPU_PRIM_TRI_FAN)) {
- has_request = true;
DRW_ibo_request(cache->batch.edituv_faces_strech_area, &cache->ibo.edituv_loops_tri_fans);
DRW_vbo_request(cache->batch.edituv_faces_strech_area, &cache->edit.loop_uv);
DRW_vbo_request(cache->batch.edituv_faces_strech_area, &cache->edit.loop_uv_data);
DRW_vbo_request(cache->batch.edituv_faces_strech_area, &cache->edit.loop_stretch_area);
}
if (DRW_batch_requested(cache->batch.edituv_faces_strech_angle, GPU_PRIM_TRI_FAN)) {
- has_request = true;
DRW_ibo_request(cache->batch.edituv_faces_strech_angle, &cache->ibo.edituv_loops_tri_fans);
DRW_vbo_request(cache->batch.edituv_faces_strech_angle, &cache->edit.loop_uv);
DRW_vbo_request(cache->batch.edituv_faces_strech_angle, &cache->edit.loop_uv_data);
DRW_vbo_request(cache->batch.edituv_faces_strech_angle, &cache->edit.loop_stretch_angle);
}
if (DRW_batch_requested(cache->batch.edituv_edges, GPU_PRIM_LINES)) {
- has_request = true;
DRW_ibo_request(cache->batch.edituv_edges, &cache->ibo.edituv_loops_line_strips);
DRW_vbo_request(cache->batch.edituv_edges, &cache->edit.loop_uv);
DRW_vbo_request(cache->batch.edituv_edges, &cache->edit.loop_uv_data);
}
if (DRW_batch_requested(cache->batch.edituv_verts, GPU_PRIM_POINTS)) {
- has_request = true;
DRW_ibo_request(cache->batch.edituv_verts, &cache->ibo.edituv_loops_points);
DRW_vbo_request(cache->batch.edituv_verts, &cache->edit.loop_uv);
DRW_vbo_request(cache->batch.edituv_verts, &cache->edit.loop_uv_data);
}
if (DRW_batch_requested(cache->batch.edituv_facedots, GPU_PRIM_POINTS)) {
- has_request = true;
DRW_vbo_request(cache->batch.edituv_facedots, &cache->edit.facedots_uv);
DRW_vbo_request(cache->batch.edituv_facedots, &cache->edit.facedots_uv_data);
}
@@ -5061,25 +5129,21 @@ void DRW_mesh_batch_cache_create_requested(
/* Selection */
/* TODO reuse ordered.loop_pos_nor if possible. */
if (DRW_batch_requested(cache->batch.edit_selection_verts, GPU_PRIM_POINTS)) {
- has_request = true;
DRW_ibo_request(cache->batch.edit_selection_verts, &cache->ibo.edit_loops_points);
DRW_vbo_request(cache->batch.edit_selection_verts, &cache->edit.loop_pos_nor);
DRW_vbo_request(cache->batch.edit_selection_verts, &cache->edit.loop_vert_idx);
}
if (DRW_batch_requested(cache->batch.edit_selection_edges, GPU_PRIM_LINES)) {
- has_request = true;
DRW_ibo_request(cache->batch.edit_selection_edges, &cache->ibo.edit_loops_lines);
DRW_vbo_request(cache->batch.edit_selection_edges, &cache->edit.loop_pos_nor);
DRW_vbo_request(cache->batch.edit_selection_edges, &cache->edit.loop_edge_idx);
}
if (DRW_batch_requested(cache->batch.edit_selection_faces, GPU_PRIM_TRIS)) {
- has_request = true;
DRW_ibo_request(cache->batch.edit_selection_faces, &cache->ibo.edit_loops_tris);
DRW_vbo_request(cache->batch.edit_selection_faces, &cache->edit.loop_pos_nor);
DRW_vbo_request(cache->batch.edit_selection_faces, &cache->edit.loop_face_idx);
}
if (DRW_batch_requested(cache->batch.edit_selection_facedots, GPU_PRIM_POINTS)) {
- has_request = true;
DRW_vbo_request(cache->batch.edit_selection_facedots, &cache->edit.facedots_pos_nor_data);
DRW_vbo_request(cache->batch.edit_selection_facedots, &cache->edit.facedots_idx);
}
@@ -5087,7 +5151,6 @@ void DRW_mesh_batch_cache_create_requested(
/* Per Material */
for (int i = 0; i < cache->mat_len; ++i) {
if (DRW_batch_requested(cache->surf_per_mat[i], GPU_PRIM_TRIS)) {
- has_request = true;
if (cache->mat_len > 1) {
DRW_ibo_request(cache->surf_per_mat[i], &cache->surf_per_mat_tris[i]);
}
@@ -5108,11 +5171,6 @@ void DRW_mesh_batch_cache_create_requested(
}
}
- /* Early out if no request. */
- if (!has_request) {
- return;
- }
-
#ifdef DRW_DEBUG_MESH_CACHE_REQUEST
printf("-- %s %s --\n", __func__, ob->id.name + 2);
#endif
@@ -5344,6 +5402,7 @@ void DRW_mesh_batch_cache_create_requested(
}
#ifdef DEBUG
+check:
/* Make sure all requested batches have been setup. */
for (int i = 0; i < sizeof(cache->batch) / sizeof(void *); ++i) {
BLI_assert(!DRW_batch_requested(((GPUBatch **)&cache->batch)[i], 0));
diff --git a/source/blender/draw/intern/draw_cache_impl_metaball.c b/source/blender/draw/intern/draw_cache_impl_metaball.c
index 432c5092274..60f15338412 100644
--- a/source/blender/draw/intern/draw_cache_impl_metaball.c
+++ b/source/blender/draw/intern/draw_cache_impl_metaball.c
@@ -98,12 +98,16 @@ static void metaball_batch_cache_init(MetaBall *mb)
cache->is_manifold = false;
}
-static MetaBallBatchCache *metaball_batch_cache_get(MetaBall *mb)
+void DRW_mball_batch_cache_validate(MetaBall *mb)
{
if (!metaball_batch_cache_valid(mb)) {
metaball_batch_cache_clear(mb);
metaball_batch_cache_init(mb);
}
+}
+
+static MetaBallBatchCache *metaball_batch_cache_get(MetaBall *mb)
+{
return mb->batch_cache;
}
diff --git a/source/blender/draw/intern/draw_cache_inline.h b/source/blender/draw/intern/draw_cache_inline.h
new file mode 100644
index 00000000000..d94ef5b90d3
--- /dev/null
+++ b/source/blender/draw/intern/draw_cache_inline.h
@@ -0,0 +1,110 @@
+/*
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * Copyright 2016, Blender Foundation.
+ */
+
+/** \file
+ * \ingroup draw
+ */
+
+#ifndef __DRAW_CACHE_INLINE_H__
+#define __DRAW_CACHE_INLINE_H__
+
+#include "MEM_guardedalloc.h"
+#include "GPU_batch.h"
+
+/* Common */
+// #define DRW_DEBUG_MESH_CACHE_REQUEST
+
+#ifdef DRW_DEBUG_MESH_CACHE_REQUEST
+# define DRW_ADD_FLAG_FROM_VBO_REQUEST(flag, vbo, value) \
+ (flag |= DRW_vbo_requested(vbo) ? (printf(" VBO requested " #vbo "\n") ? value : value) : 0)
+# define DRW_ADD_FLAG_FROM_IBO_REQUEST(flag, ibo, value) \
+ (flag |= DRW_ibo_requested(ibo) ? (printf(" IBO requested " #ibo "\n") ? value : value) : 0)
+#else
+# define DRW_ADD_FLAG_FROM_VBO_REQUEST(flag, vbo, value) \
+ (flag |= DRW_vbo_requested(vbo) ? (value) : 0)
+# define DRW_ADD_FLAG_FROM_IBO_REQUEST(flag, ibo, value) \
+ (flag |= DRW_ibo_requested(ibo) ? (value) : 0)
+#endif
+
+/* Test and assign NULL if test fails */
+#define DRW_TEST_ASSIGN_VBO(v) (v = (DRW_vbo_requested(v) ? (v) : NULL))
+#define DRW_TEST_ASSIGN_IBO(v) (v = (DRW_ibo_requested(v) ? (v) : NULL))
+
+BLI_INLINE GPUBatch *DRW_batch_request(GPUBatch **batch)
+{
+ /* XXX TODO(fclem): We are writting to batch cache here. Need to make this thread safe. */
+ if (*batch == NULL) {
+ *batch = MEM_callocN(sizeof(GPUBatch), "GPUBatch");
+ }
+ return *batch;
+}
+
+BLI_INLINE bool DRW_batch_requested(GPUBatch *batch, int prim_type)
+{
+ /* Batch has been requested if it has been created but not initialized. */
+ if (batch != NULL && batch->verts[0] == NULL) {
+ /* HACK. We init without a valid VBO and let the first vbo binding
+ * fill verts[0]. */
+ GPU_batch_init_ex(batch, prim_type, (GPUVertBuf *)1, NULL, 0);
+ batch->verts[0] = NULL;
+ return true;
+ }
+ return false;
+}
+
+BLI_INLINE void DRW_ibo_request(GPUBatch *batch, GPUIndexBuf **ibo)
+{
+ if (*ibo == NULL) {
+ *ibo = MEM_callocN(sizeof(GPUIndexBuf), "GPUIndexBuf");
+ }
+ GPU_batch_vao_cache_clear(batch);
+ batch->elem = *ibo;
+}
+
+BLI_INLINE bool DRW_ibo_requested(GPUIndexBuf *ibo)
+{
+ /* TODO do not rely on data uploaded. This prevents multithreading.
+ * (need access to a gl context) */
+ return (ibo != NULL && ibo->ibo_id == 0 && ibo->data == NULL);
+}
+
+BLI_INLINE void DRW_vbo_request(GPUBatch *batch, GPUVertBuf **vbo)
+{
+ if (*vbo == NULL) {
+ *vbo = MEM_callocN(sizeof(GPUVertBuf), "GPUVertBuf");
+ }
+ /* HACK set first vbo if not init. */
+ if (batch->verts[0] == NULL) {
+ GPU_batch_vao_cache_clear(batch);
+ batch->verts[0] = *vbo;
+ }
+ else {
+ /* HACK: bypass assert */
+ int vbo_vert_len = (*vbo)->vertex_len;
+ (*vbo)->vertex_len = batch->verts[0]->vertex_len;
+ GPU_batch_vertbuf_add(batch, *vbo);
+ (*vbo)->vertex_len = vbo_vert_len;
+ }
+}
+
+BLI_INLINE bool DRW_vbo_requested(GPUVertBuf *vbo)
+{
+ return (vbo != NULL && vbo->format.attr_len == 0);
+}
+
+#endif /* __DRAW_CACHE_INLINE_H__ */
diff --git a/source/blender/draw/intern/draw_common.c b/source/blender/draw/intern/draw_common.c
index b4eb354ec59..378324b4871 100644
--- a/source/blender/draw/intern/draw_common.c
+++ b/source/blender/draw/intern/draw_common.c
@@ -233,6 +233,7 @@ extern char datatoc_armature_stick_frag_glsl[];
extern char datatoc_armature_dof_vert_glsl[];
extern char datatoc_common_globals_lib_glsl[];
+extern char datatoc_common_view_lib_glsl[];
extern char datatoc_gpu_shader_flat_color_frag_glsl[];
extern char datatoc_gpu_shader_3D_smooth_color_frag_glsl[];
@@ -284,7 +285,8 @@ static struct {
struct GPUVertFormat *instance_bone_envelope_distance;
struct GPUVertFormat *instance_bone_envelope_outline;
struct GPUVertFormat *instance_mball_handles;
- struct GPUVertFormat *dynlines_color;
+ struct GPUVertFormat *pos_color;
+ struct GPUVertFormat *pos;
} g_formats = {NULL};
void DRW_globals_free(void)
@@ -309,34 +311,36 @@ void DRW_shgroup_world_clip_planes_from_rv3d(DRWShadingGroup *shgrp, const Regio
DRW_shgroup_state_enable(shgrp, DRW_STATE_CLIP_PLANES);
}
-DRWShadingGroup *shgroup_dynlines_flat_color(DRWPass *pass, eGPUShaderConfig sh_cfg)
+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);
- DRW_shgroup_instance_format(g_formats.dynlines_color,
+ DRW_shgroup_instance_format(g_formats.pos_color,
{
{"pos", DRW_ATTR_FLOAT, 3},
{"color", DRW_ATTR_FLOAT, 4},
});
- DRWShadingGroup *grp = DRW_shgroup_line_batch_create_with_format(
- sh, pass, g_formats.dynlines_color);
+ 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);
}
- return grp;
+ return DRW_shgroup_call_buffer(grp, g_formats.pos_color, GPU_PRIM_LINES);
}
-DRWShadingGroup *shgroup_dynlines_dashed_uniform_color(DRWPass *pass,
- const float color[4],
- eGPUShaderConfig sh_cfg)
+struct DRWCallBuffer *buffer_dynlines_dashed_uniform_color(DRWPass *pass,
+ const float color[4],
+ eGPUShaderConfig sh_cfg)
{
GPUShader *sh = GPU_shader_get_builtin_shader_with_config(
GPU_SHADER_3D_LINE_DASHED_UNIFORM_COLOR, sh_cfg);
static float dash_width = 6.0f;
static float dash_factor = 0.5f;
- DRWShadingGroup *grp = DRW_shgroup_line_batch_create(sh, pass);
+
+ DRW_shgroup_instance_format(g_formats.pos, {{"pos", DRW_ATTR_FLOAT, 3}});
+
+ DRWShadingGroup *grp = DRW_shgroup_create(sh, pass);
DRW_shgroup_uniform_vec4(grp, "color", color, 1);
DRW_shgroup_uniform_vec2(grp, "viewport_size", DRW_viewport_size_get(), 1);
DRW_shgroup_uniform_float(grp, "dash_width", &dash_width, 1);
@@ -345,60 +349,52 @@ DRWShadingGroup *shgroup_dynlines_dashed_uniform_color(DRWPass *pass,
if (sh_cfg == GPU_SHADER_CFG_CLIPPED) {
DRW_shgroup_world_clip_planes_from_rv3d(grp, DRW_context_state_get()->rv3d);
}
- return grp;
+ return DRW_shgroup_call_buffer(grp, g_formats.pos, GPU_PRIM_LINES);
}
-DRWShadingGroup *shgroup_dynpoints_uniform_color(DRWPass *pass,
- const float color[4],
- const float *size,
- eGPUShaderConfig sh_cfg)
+struct DRWCallBuffer *buffer_dynpoints_uniform_color(DRWShadingGroup *grp)
{
- GPUShader *sh = GPU_shader_get_builtin_shader_with_config(
- GPU_SHADER_3D_POINT_UNIFORM_SIZE_UNIFORM_COLOR_AA, sh_cfg);
+ DRW_shgroup_instance_format(g_formats.pos, {{"pos", DRW_ATTR_FLOAT, 3}});
- DRWShadingGroup *grp = DRW_shgroup_point_batch_create(sh, pass);
- DRW_shgroup_uniform_vec4(grp, "color", color, 1);
- DRW_shgroup_uniform_float(grp, "size", size, 1);
- DRW_shgroup_state_enable(grp, DRW_STATE_POINT);
- if (sh_cfg == GPU_SHADER_CFG_CLIPPED) {
- DRW_shgroup_world_clip_planes_from_rv3d(grp, DRW_context_state_get()->rv3d);
- }
- return grp;
+ return DRW_shgroup_call_buffer(grp, g_formats.pos, GPU_PRIM_POINTS);
}
-DRWShadingGroup *shgroup_groundlines_uniform_color(DRWPass *pass,
- const float color[4],
- eGPUShaderConfig sh_cfg)
+struct DRWCallBuffer *buffer_groundlines_uniform_color(DRWPass *pass,
+ const float color[4],
+ eGPUShaderConfig sh_cfg)
{
GPUShader *sh = GPU_shader_get_builtin_shader_with_config(GPU_SHADER_3D_GROUNDLINE, sh_cfg);
- DRWShadingGroup *grp = DRW_shgroup_point_batch_create(sh, pass);
+ DRW_shgroup_instance_format(g_formats.pos, {{"pos", DRW_ATTR_FLOAT, 3}});
+
+ 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);
}
- return grp;
+ return DRW_shgroup_call_buffer(grp, g_formats.pos, GPU_PRIM_POINTS);
}
-DRWShadingGroup *shgroup_groundpoints_uniform_color(DRWPass *pass,
- const float color[4],
- eGPUShaderConfig sh_cfg)
+struct DRWCallBuffer *buffer_groundpoints_uniform_color(DRWPass *pass,
+ const float color[4],
+ eGPUShaderConfig sh_cfg)
{
GPUShader *sh = GPU_shader_get_builtin_shader_with_config(GPU_SHADER_3D_GROUNDPOINT, sh_cfg);
- DRWShadingGroup *grp = DRW_shgroup_point_batch_create(sh, pass);
+ DRW_shgroup_instance_format(g_formats.pos, {{"pos", DRW_ATTR_FLOAT, 3}});
+
+ DRWShadingGroup *grp = DRW_shgroup_create(sh, pass);
DRW_shgroup_uniform_vec4(grp, "color", color, 1);
- DRW_shgroup_state_enable(grp, DRW_STATE_POINT);
if (sh_cfg == GPU_SHADER_CFG_CLIPPED) {
DRW_shgroup_world_clip_planes_from_rv3d(grp, DRW_context_state_get()->rv3d);
}
- return grp;
+ return DRW_shgroup_call_buffer(grp, g_formats.pos, GPU_PRIM_POINTS);
}
-DRWShadingGroup *shgroup_instance_screenspace(DRWPass *pass,
- struct GPUBatch *geom,
- const float *size,
- eGPUShaderConfig sh_cfg)
+struct DRWCallBuffer *buffer_instance_screenspace(DRWPass *pass,
+ struct GPUBatch *geom,
+ const float *size,
+ eGPUShaderConfig sh_cfg)
{
GPUShader *sh = GPU_shader_get_builtin_shader_with_config(
GPU_SHADER_3D_SCREENSPACE_VARIYING_COLOR, sh_cfg);
@@ -409,18 +405,17 @@ DRWShadingGroup *shgroup_instance_screenspace(DRWPass *pass,
{"color", DRW_ATTR_FLOAT, 3},
});
- DRWShadingGroup *grp = DRW_shgroup_instance_create(
- sh, pass, geom, g_formats.instance_screenspace);
+ DRWShadingGroup *grp = DRW_shgroup_create(sh, pass);
DRW_shgroup_uniform_float(grp, "size", size, 1);
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);
}
- return grp;
+ return DRW_shgroup_call_buffer_instance(grp, g_formats.instance_screenspace, geom);
}
-DRWShadingGroup *shgroup_instance_solid(DRWPass *pass, struct GPUBatch *geom)
+struct DRWCallBuffer *buffer_instance_solid(DRWPass *pass, struct GPUBatch *geom)
{
static float light[3] = {0.0f, 0.0f, 1.0f};
GPUShader *sh = GPU_shader_get_builtin_shader(
@@ -432,13 +427,13 @@ DRWShadingGroup *shgroup_instance_solid(DRWPass *pass, struct GPUBatch *geom)
{"color", DRW_ATTR_FLOAT, 4},
});
- DRWShadingGroup *grp = DRW_shgroup_instance_create(sh, pass, geom, g_formats.instance_color);
+ DRWShadingGroup *grp = DRW_shgroup_create(sh, pass);
DRW_shgroup_uniform_vec3(grp, "light", light, 1);
- return grp;
+ return DRW_shgroup_call_buffer_instance(grp, g_formats.instance_color, geom);
}
-DRWShadingGroup *shgroup_instance_wire(DRWPass *pass, struct GPUBatch *geom)
+struct DRWCallBuffer *buffer_instance_wire(DRWPass *pass, struct GPUBatch *geom)
{
GPUShader *sh = GPU_shader_get_builtin_shader(GPU_SHADER_3D_OBJECTSPACE_VARIYING_COLOR);
@@ -448,14 +443,14 @@ DRWShadingGroup *shgroup_instance_wire(DRWPass *pass, struct GPUBatch *geom)
{"color", DRW_ATTR_FLOAT, 4},
});
- DRWShadingGroup *grp = DRW_shgroup_instance_create(sh, pass, geom, g_formats.instance_color);
+ DRWShadingGroup *grp = DRW_shgroup_create(sh, pass);
- return grp;
+ return DRW_shgroup_call_buffer_instance(grp, g_formats.instance_color, geom);
}
-DRWShadingGroup *shgroup_instance_screen_aligned(DRWPass *pass,
- struct GPUBatch *geom,
- eGPUShaderConfig sh_cfg)
+struct DRWCallBuffer *buffer_instance_screen_aligned(DRWPass *pass,
+ struct GPUBatch *geom,
+ eGPUShaderConfig sh_cfg)
{
GPUShader *sh = GPU_shader_get_builtin_shader_with_config(GPU_SHADER_3D_INSTANCE_SCREEN_ALIGNED,
sh_cfg);
@@ -467,18 +462,17 @@ DRWShadingGroup *shgroup_instance_screen_aligned(DRWPass *pass,
{"InstanceModelMatrix", DRW_ATTR_FLOAT, 16},
});
- DRWShadingGroup *grp = DRW_shgroup_instance_create(
- sh, pass, geom, g_formats.instance_screen_aligned);
+ 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);
}
- return grp;
+ return DRW_shgroup_call_buffer_instance(grp, g_formats.instance_screen_aligned, geom);
}
-DRWShadingGroup *shgroup_instance_scaled(DRWPass *pass,
- struct GPUBatch *geom,
- eGPUShaderConfig sh_cfg)
+struct DRWCallBuffer *buffer_instance_scaled(DRWPass *pass,
+ struct GPUBatch *geom,
+ eGPUShaderConfig sh_cfg)
{
GPUShader *sh_inst = GPU_shader_get_builtin_shader_with_config(
GPU_SHADER_INSTANCE_VARIYING_COLOR_VARIYING_SCALE, sh_cfg);
@@ -490,15 +484,16 @@ DRWShadingGroup *shgroup_instance_scaled(DRWPass *pass,
{"InstanceModelMatrix", DRW_ATTR_FLOAT, 16},
});
- DRWShadingGroup *grp = DRW_shgroup_instance_create(
- sh_inst, pass, geom, g_formats.instance_scaled);
+ 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);
}
- return grp;
+ return DRW_shgroup_call_buffer_instance(grp, g_formats.instance_scaled, geom);
}
-DRWShadingGroup *shgroup_instance(DRWPass *pass, struct GPUBatch *geom, eGPUShaderConfig sh_cfg)
+struct DRWCallBuffer *buffer_instance(DRWPass *pass,
+ struct GPUBatch *geom,
+ eGPUShaderConfig sh_cfg)
{
GPUShader *sh_inst = GPU_shader_get_builtin_shader_with_config(
GPU_SHADER_INSTANCE_VARIYING_COLOR_VARIYING_SIZE, sh_cfg);
@@ -510,22 +505,16 @@ DRWShadingGroup *shgroup_instance(DRWPass *pass, struct GPUBatch *geom, eGPUShad
{"InstanceModelMatrix", DRW_ATTR_FLOAT, 16},
});
- DRWShadingGroup *grp = DRW_shgroup_instance_create(
- sh_inst, pass, geom, g_formats.instance_sized);
+ 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);
}
- return grp;
+ return DRW_shgroup_call_buffer_instance(grp, g_formats.instance_sized, geom);
}
-DRWShadingGroup *shgroup_instance_alpha(DRWPass *pass,
- struct GPUBatch *geom,
- eGPUShaderConfig sh_cfg)
+struct DRWCallBuffer *buffer_instance_alpha(DRWShadingGroup *grp, struct GPUBatch *geom)
{
- GPUShader *sh_inst = GPU_shader_get_builtin_shader_with_config(
- GPU_SHADER_INSTANCE_VARIYING_COLOR_VARIYING_SIZE, sh_cfg);
-
DRW_shgroup_instance_format(g_formats.instance_sized,
{
{"color", DRW_ATTR_FLOAT, 4},
@@ -533,17 +522,12 @@ DRWShadingGroup *shgroup_instance_alpha(DRWPass *pass,
{"InstanceModelMatrix", DRW_ATTR_FLOAT, 16},
});
- DRWShadingGroup *grp = DRW_shgroup_instance_create(
- sh_inst, pass, geom, g_formats.instance_sized);
- if (sh_cfg == GPU_SHADER_CFG_CLIPPED) {
- DRW_shgroup_world_clip_planes_from_rv3d(grp, DRW_context_state_get()->rv3d);
- }
- return grp;
+ return DRW_shgroup_call_buffer_instance(grp, g_formats.instance_sized, geom);
}
-DRWShadingGroup *shgroup_instance_empty_axes(DRWPass *pass,
- struct GPUBatch *geom,
- eGPUShaderConfig sh_cfg)
+struct DRWCallBuffer *buffer_instance_empty_axes(DRWPass *pass,
+ struct GPUBatch *geom,
+ eGPUShaderConfig sh_cfg)
{
COMMON_Shaders *sh_data = &g_shaders[sh_cfg];
if (sh_data->empty_axes_sh == NULL) {
@@ -562,16 +546,15 @@ DRWShadingGroup *shgroup_instance_empty_axes(DRWPass *pass,
{"InstanceModelMatrix", DRW_ATTR_FLOAT, 16},
});
- DRWShadingGroup *grp = DRW_shgroup_instance_create(
- sh_data->empty_axes_sh, pass, geom, g_formats.instance_sized);
+ 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);
}
- return grp;
+ return DRW_shgroup_call_buffer_instance(grp, g_formats.instance_sized, geom);
}
-DRWShadingGroup *shgroup_instance_outline(DRWPass *pass, struct GPUBatch *geom, int *baseid)
+struct DRWCallBuffer *buffer_instance_outline(DRWPass *pass, struct GPUBatch *geom, int *baseid)
{
GPUShader *sh_inst = GPU_shader_get_builtin_shader(
GPU_SHADER_INSTANCE_VARIYING_ID_VARIYING_SIZE);
@@ -583,16 +566,15 @@ DRWShadingGroup *shgroup_instance_outline(DRWPass *pass, struct GPUBatch *geom,
{"InstanceModelMatrix", DRW_ATTR_FLOAT, 16},
});
- DRWShadingGroup *grp = DRW_shgroup_instance_create(
- sh_inst, pass, geom, g_formats.instance_outline);
+ DRWShadingGroup *grp = DRW_shgroup_create(sh_inst, pass);
DRW_shgroup_uniform_int(grp, "baseId", baseid, 1);
- return grp;
+ return DRW_shgroup_call_buffer_instance(grp, g_formats.instance_outline, geom);
}
-DRWShadingGroup *shgroup_camera_instance(DRWPass *pass,
- struct GPUBatch *geom,
- eGPUShaderConfig sh_cfg)
+struct DRWCallBuffer *buffer_camera_instance(DRWPass *pass,
+ struct GPUBatch *geom,
+ eGPUShaderConfig sh_cfg)
{
GPUShader *sh_inst = GPU_shader_get_builtin_shader_with_config(GPU_SHADER_CAMERA, sh_cfg);
@@ -605,17 +587,16 @@ DRWShadingGroup *shgroup_camera_instance(DRWPass *pass,
{"InstanceModelMatrix", DRW_ATTR_FLOAT, 16},
});
- DRWShadingGroup *grp = DRW_shgroup_instance_create(
- sh_inst, pass, geom, g_formats.instance_camera);
+ 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);
}
- return grp;
+ return DRW_shgroup_call_buffer_instance(grp, g_formats.instance_camera, geom);
}
-DRWShadingGroup *shgroup_distance_lines_instance(DRWPass *pass,
- struct GPUBatch *geom,
- eGPUShaderConfig sh_cfg)
+struct DRWCallBuffer *buffer_distance_lines_instance(DRWPass *pass,
+ struct GPUBatch *geom,
+ eGPUShaderConfig sh_cfg)
{
GPUShader *sh_inst = GPU_shader_get_builtin_shader_with_config(GPU_SHADER_DISTANCE_LINES,
sh_cfg);
@@ -629,18 +610,17 @@ DRWShadingGroup *shgroup_distance_lines_instance(DRWPass *pass,
{"InstanceModelMatrix", DRW_ATTR_FLOAT, 16},
});
- DRWShadingGroup *grp = DRW_shgroup_instance_create(
- sh_inst, pass, geom, g_formats.instance_distance_lines);
+ 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);
}
- return grp;
+ return DRW_shgroup_call_buffer_instance(grp, g_formats.instance_distance_lines, geom);
}
-DRWShadingGroup *shgroup_spot_instance(DRWPass *pass,
- struct GPUBatch *geom,
- eGPUShaderConfig sh_cfg)
+struct DRWCallBuffer *buffer_spot_instance(DRWPass *pass,
+ struct GPUBatch *geom,
+ eGPUShaderConfig sh_cfg)
{
GPUShader *sh_inst = GPU_shader_get_builtin_shader_with_config(
GPU_SHADER_INSTANCE_EDGES_VARIYING_COLOR, sh_cfg);
@@ -653,17 +633,17 @@ DRWShadingGroup *shgroup_spot_instance(DRWPass *pass,
{"InstanceModelMatrix", DRW_ATTR_FLOAT, 16},
});
- DRWShadingGroup *grp = DRW_shgroup_instance_create(sh_inst, pass, geom, g_formats.instance_spot);
+ DRWShadingGroup *grp = DRW_shgroup_create(sh_inst, pass);
DRW_shgroup_uniform_bool(grp, "drawFront", &False, 1);
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);
}
- return grp;
+ return DRW_shgroup_call_buffer_instance(grp, g_formats.instance_spot, geom);
}
-DRWShadingGroup *shgroup_instance_bone_axes(DRWPass *pass, eGPUShaderConfig sh_cfg)
+struct DRWCallBuffer *buffer_instance_bone_axes(DRWPass *pass, eGPUShaderConfig sh_cfg)
{
COMMON_Shaders *sh_data = &g_shaders[sh_cfg];
if (sh_data->bone_axes == NULL) {
@@ -681,16 +661,16 @@ DRWShadingGroup *shgroup_instance_bone_axes(DRWPass *pass, eGPUShaderConfig sh_c
{"color", DRW_ATTR_FLOAT, 4},
});
- DRWShadingGroup *grp = DRW_shgroup_instance_create(
- sh_data->bone_axes, pass, DRW_cache_bone_arrows_get(), g_formats.instance_color);
+ 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);
}
- return grp;
+ return DRW_shgroup_call_buffer_instance(
+ grp, g_formats.instance_color, DRW_cache_bone_arrows_get());
}
-DRWShadingGroup *shgroup_instance_bone_envelope_outline(DRWPass *pass, eGPUShaderConfig sh_cfg)
+struct DRWCallBuffer *buffer_instance_bone_envelope_outline(DRWPass *pass, eGPUShaderConfig sh_cfg)
{
COMMON_Shaders *sh_data = &g_shaders[sh_cfg];
if (sh_data->bone_envelope_outline == NULL) {
@@ -711,18 +691,17 @@ DRWShadingGroup *shgroup_instance_bone_envelope_outline(DRWPass *pass, eGPUShade
{"xAxis", DRW_ATTR_FLOAT, 3},
});
- DRWShadingGroup *grp = DRW_shgroup_instance_create(sh_data->bone_envelope_outline,
- pass,
- DRW_cache_bone_envelope_outline_get(),
- g_formats.instance_bone_envelope_outline);
+ 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);
}
- return grp;
+ return DRW_shgroup_call_buffer_instance(
+ grp, g_formats.instance_bone_envelope_outline, DRW_cache_bone_envelope_outline_get());
}
-DRWShadingGroup *shgroup_instance_bone_envelope_distance(DRWPass *pass, eGPUShaderConfig sh_cfg)
+struct DRWCallBuffer *buffer_instance_bone_envelope_distance(DRWPass *pass,
+ eGPUShaderConfig sh_cfg)
{
COMMON_Shaders *sh_data = &g_shaders[sh_cfg];
if (sh_data->bone_envelope_distance == NULL) {
@@ -742,19 +721,17 @@ DRWShadingGroup *shgroup_instance_bone_envelope_distance(DRWPass *pass, eGPUShad
{"xAxis", DRW_ATTR_FLOAT, 3},
});
- DRWShadingGroup *grp = DRW_shgroup_instance_create(sh_data->bone_envelope_distance,
- pass,
- DRW_cache_bone_envelope_solid_get(),
- g_formats.instance_bone_envelope_distance);
+ 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);
}
- return grp;
+ return DRW_shgroup_call_buffer_instance(
+ grp, g_formats.instance_bone_envelope_distance, DRW_cache_bone_envelope_solid_get());
}
-DRWShadingGroup *shgroup_instance_bone_envelope_solid(DRWPass *pass,
- bool transp,
- eGPUShaderConfig sh_cfg)
+struct DRWCallBuffer *buffer_instance_bone_envelope_solid(DRWPass *pass,
+ bool transp,
+ eGPUShaderConfig sh_cfg)
{
COMMON_Shaders *sh_data = &g_shaders[sh_cfg];
if (sh_data->bone_envelope == NULL) {
@@ -776,18 +753,19 @@ DRWShadingGroup *shgroup_instance_bone_envelope_solid(DRWPass *pass,
{"xAxis", DRW_ATTR_FLOAT, 3},
});
- DRWShadingGroup *grp = DRW_shgroup_instance_create(sh_data->bone_envelope,
- pass,
- DRW_cache_bone_envelope_solid_get(),
- g_formats.instance_bone_envelope);
+ DRWShadingGroup *grp = DRW_shgroup_create(sh_data->bone_envelope, pass);
+ /* We can have a lot of overdraw if we don't do this. Also envelope are not subject to
+ * inverted matrix. */
+ 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);
}
- return grp;
+ return DRW_shgroup_call_buffer_instance(
+ grp, g_formats.instance_bone_envelope, DRW_cache_bone_envelope_solid_get());
}
-DRWShadingGroup *shgroup_instance_mball_handles(DRWPass *pass, eGPUShaderConfig sh_cfg)
+struct DRWCallBuffer *buffer_instance_mball_handles(DRWPass *pass, eGPUShaderConfig sh_cfg)
{
COMMON_Shaders *sh_data = &g_shaders[sh_cfg];
if (sh_data->mball_handles == NULL) {
@@ -806,28 +784,32 @@ DRWShadingGroup *shgroup_instance_mball_handles(DRWPass *pass, eGPUShaderConfig
{"color", DRW_ATTR_FLOAT, 3},
});
- DRWShadingGroup *grp = DRW_shgroup_instance_create(sh_data->mball_handles,
- pass,
- DRW_cache_screenspace_circle_get(),
- g_formats.instance_mball_handles);
+ 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);
}
- return grp;
+ return DRW_shgroup_call_buffer_instance(
+ grp, g_formats.instance_mball_handles, DRW_cache_screenspace_circle_get());
}
/* Only works with batches with adjacency infos. */
-DRWShadingGroup *shgroup_instance_bone_shape_outline(DRWPass *pass,
- struct GPUBatch *geom,
- eGPUShaderConfig sh_cfg)
+struct DRWCallBuffer *buffer_instance_bone_shape_outline(DRWPass *pass,
+ struct GPUBatch *geom,
+ eGPUShaderConfig sh_cfg)
{
COMMON_Shaders *sh_data = &g_shaders[sh_cfg];
if (sh_data->shape_outline == NULL) {
const GPUShaderConfigData *sh_cfg_data = &GPU_shader_cfg_data[sh_cfg];
sh_data->shape_outline = GPU_shader_create_from_arrays({
- .vert = (const char *[]){sh_cfg_data->lib, datatoc_armature_shape_outline_vert_glsl, NULL},
- .geom = (const char *[]){sh_cfg_data->lib, datatoc_armature_shape_outline_geom_glsl, NULL},
+ .vert = (const char *[]){sh_cfg_data->lib,
+ datatoc_common_view_lib_glsl,
+ datatoc_armature_shape_outline_vert_glsl,
+ NULL},
+ .geom = (const char *[]){sh_cfg_data->lib,
+ datatoc_common_view_lib_glsl,
+ datatoc_armature_shape_outline_geom_glsl,
+ NULL},
.frag = (const char *[]){datatoc_gpu_shader_flat_color_frag_glsl, NULL},
.defs = (const char *[]){sh_cfg_data->def, NULL},
});
@@ -839,25 +821,27 @@ DRWShadingGroup *shgroup_instance_bone_shape_outline(DRWPass *pass,
{"outlineColorSize", DRW_ATTR_FLOAT, 4},
});
- DRWShadingGroup *grp = DRW_shgroup_instance_create(
- sh_data->shape_outline, pass, geom, g_formats.instance_bone_outline);
+ 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);
}
- return grp;
+ return DRW_shgroup_call_buffer_instance(grp, g_formats.instance_bone_outline, geom);
}
-DRWShadingGroup *shgroup_instance_bone_shape_solid(DRWPass *pass,
- struct GPUBatch *geom,
- bool transp,
- eGPUShaderConfig sh_cfg)
+struct DRWCallBuffer *buffer_instance_bone_shape_solid(DRWPass *pass,
+ struct GPUBatch *geom,
+ bool transp,
+ eGPUShaderConfig sh_cfg)
{
COMMON_Shaders *sh_data = &g_shaders[sh_cfg];
if (sh_data->shape_solid == NULL) {
const GPUShaderConfigData *sh_cfg_data = &GPU_shader_cfg_data[sh_cfg];
sh_data->shape_solid = GPU_shader_create_from_arrays({
- .vert = (const char *[]){sh_cfg_data->lib, datatoc_armature_shape_solid_vert_glsl, NULL},
+ .vert = (const char *[]){sh_cfg_data->lib,
+ datatoc_common_view_lib_glsl,
+ datatoc_armature_shape_solid_vert_glsl,
+ NULL},
.frag = (const char *[]){datatoc_armature_shape_solid_frag_glsl, NULL},
.defs = (const char *[]){sh_cfg_data->def, NULL},
});
@@ -870,18 +854,17 @@ DRWShadingGroup *shgroup_instance_bone_shape_solid(DRWPass *pass,
{"stateColor", DRW_ATTR_FLOAT, 3},
});
- DRWShadingGroup *grp = DRW_shgroup_instance_create(
- sh_data->shape_solid, pass, geom, g_formats.instance_bone);
+ 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);
}
- return grp;
+ return DRW_shgroup_call_buffer_instance(grp, g_formats.instance_bone, geom);
}
-DRWShadingGroup *shgroup_instance_bone_sphere_solid(DRWPass *pass,
- bool transp,
- eGPUShaderConfig sh_cfg)
+struct DRWCallBuffer *buffer_instance_bone_sphere_solid(DRWPass *pass,
+ bool transp,
+ eGPUShaderConfig sh_cfg)
{
COMMON_Shaders *sh_data = &g_shaders[sh_cfg];
if (sh_data->bone_sphere == NULL) {
@@ -900,17 +883,17 @@ DRWShadingGroup *shgroup_instance_bone_sphere_solid(DRWPass *pass,
{"stateColor", DRW_ATTR_FLOAT, 3},
});
- DRWShadingGroup *grp = DRW_shgroup_instance_create(
- sh_data->bone_sphere, pass, DRW_cache_bone_point_get(), g_formats.instance_bone);
+ DRWShadingGroup *grp = DRW_shgroup_create(sh_data->bone_sphere, 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);
}
- return grp;
+ return DRW_shgroup_call_buffer_instance(
+ grp, g_formats.instance_bone, DRW_cache_bone_point_get());
}
-DRWShadingGroup *shgroup_instance_bone_sphere_outline(DRWPass *pass, eGPUShaderConfig sh_cfg)
+struct DRWCallBuffer *buffer_instance_bone_sphere_outline(DRWPass *pass, eGPUShaderConfig sh_cfg)
{
COMMON_Shaders *sh_data = &g_shaders[sh_cfg];
if (sh_data->bone_sphere_outline == NULL) {
@@ -929,18 +912,16 @@ DRWShadingGroup *shgroup_instance_bone_sphere_outline(DRWPass *pass, eGPUShaderC
{"outlineColorSize", DRW_ATTR_FLOAT, 4},
});
- DRWShadingGroup *grp = DRW_shgroup_instance_create(sh_data->bone_sphere_outline,
- pass,
- DRW_cache_bone_point_wire_outline_get(),
- g_formats.instance_bone_outline);
+ 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);
}
- return grp;
+ return DRW_shgroup_call_buffer_instance(
+ grp, g_formats.instance_bone_outline, DRW_cache_bone_point_wire_outline_get());
}
-DRWShadingGroup *shgroup_instance_bone_stick(DRWPass *pass, eGPUShaderConfig sh_cfg)
+struct DRWCallBuffer *buffer_instance_bone_stick(DRWPass *pass, eGPUShaderConfig sh_cfg)
{
COMMON_Shaders *sh_data = &g_shaders[sh_cfg];
if (sh_data->bone_stick == NULL) {
@@ -963,17 +944,19 @@ DRWShadingGroup *shgroup_instance_bone_stick(DRWPass *pass, eGPUShaderConfig sh_
{"tailColor", DRW_ATTR_FLOAT, 4},
});
- DRWShadingGroup *grp = DRW_shgroup_instance_create(
- sh_data->bone_stick, pass, DRW_cache_bone_stick_get(), g_formats.instance_bone_stick);
+ DRWShadingGroup *grp = DRW_shgroup_create(sh_data->bone_stick, pass);
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);
}
- return grp;
+ return DRW_shgroup_call_buffer_instance(
+ grp, g_formats.instance_bone_stick, DRW_cache_bone_stick_get());
}
-struct DRWShadingGroup *shgroup_instance_bone_dof(struct DRWPass *pass, struct GPUBatch *geom)
+struct DRWCallBuffer *buffer_instance_bone_dof(struct DRWPass *pass,
+ struct GPUBatch *geom,
+ bool blend)
{
COMMON_Shaders *sh_data = &g_shaders[GPU_SHADER_CFG_DEFAULT];
if (sh_data->bone_dofs == NULL) {
@@ -989,10 +972,12 @@ struct DRWShadingGroup *shgroup_instance_bone_dof(struct DRWPass *pass, struct G
{"amax", DRW_ATTR_FLOAT, 2},
});
- DRWShadingGroup *grp = DRW_shgroup_instance_create(
- sh_data->bone_dofs, pass, geom, g_formats.instance_bone_dof);
-
- return grp;
+ DRWShadingGroup *grp = DRW_shgroup_create(sh_data->bone_dofs, pass);
+ if (blend) {
+ DRW_shgroup_state_enable(grp, DRW_STATE_BLEND);
+ DRW_shgroup_state_disable(grp, DRW_STATE_CULL_FRONT);
+ }
+ return DRW_shgroup_call_buffer_instance(grp, g_formats.instance_bone_dof, geom);
}
struct GPUShader *mpath_line_shader_get(void)
@@ -1028,18 +1013,23 @@ struct GPUShader *volume_velocity_shader_get(bool use_needle)
COMMON_Shaders *sh_data = &g_shaders[GPU_SHADER_CFG_DEFAULT];
if (use_needle) {
if (sh_data->volume_velocity_needle_sh == NULL) {
- sh_data->volume_velocity_needle_sh = DRW_shader_create(
+ sh_data->volume_velocity_needle_sh = DRW_shader_create_with_lib(
datatoc_volume_velocity_vert_glsl,
NULL,
datatoc_gpu_shader_flat_color_frag_glsl,
+ datatoc_common_view_lib_glsl,
"#define USE_NEEDLE");
}
return sh_data->volume_velocity_needle_sh;
}
else {
if (sh_data->volume_velocity_sh == NULL) {
- sh_data->volume_velocity_sh = DRW_shader_create(
- datatoc_volume_velocity_vert_glsl, NULL, datatoc_gpu_shader_flat_color_frag_glsl, NULL);
+ sh_data->volume_velocity_sh = DRW_shader_create_with_lib(
+ datatoc_volume_velocity_vert_glsl,
+ NULL,
+ datatoc_gpu_shader_flat_color_frag_glsl,
+ datatoc_common_view_lib_glsl,
+ NULL);
}
return sh_data->volume_velocity_sh;
}
@@ -1075,22 +1065,27 @@ int DRW_object_wire_theme_get(Object *ob, ViewLayer *view_layer, float **r_color
theme_id = (active) ? TH_ACTIVE : TH_SELECT;
}
else {
- if (ob->type == OB_LAMP) {
- theme_id = TH_LIGHT;
- }
- else if (ob->type == OB_SPEAKER) {
- theme_id = TH_SPEAKER;
- }
- else if (ob->type == OB_CAMERA) {
- theme_id = TH_CAMERA;
- }
- else if (ob->type == OB_EMPTY) {
- theme_id = TH_EMPTY;
+ switch (ob->type) {
+ case OB_LAMP:
+ theme_id = TH_LIGHT;
+ break;
+ case OB_SPEAKER:
+ theme_id = TH_SPEAKER;
+ break;
+ case OB_CAMERA:
+ theme_id = TH_CAMERA;
+ break;
+ case OB_EMPTY:
+ theme_id = TH_EMPTY;
+ break;
+ case OB_LIGHTPROBE:
+ /* TODO add lightprobe color */
+ theme_id = TH_EMPTY;
+ break;
+ default:
+ /* fallback to TH_WIRE */
+ break;
}
- else if (ob->type == OB_LIGHTPROBE) {
- theme_id = TH_EMPTY;
- } /* TODO add lightprobe color */
- /* fallback to TH_WIRE */
}
}
@@ -1217,7 +1212,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 489bc7459df..df7220c0d2a 100644
--- a/source/blender/draw/intern/draw_common.h
+++ b/source/blender/draw/intern/draw_common.h
@@ -23,6 +23,7 @@
#ifndef __DRAW_COMMON_H__
#define __DRAW_COMMON_H__
+struct DRWCallBuffer;
struct DRWPass;
struct DRWShadingGroup;
struct GPUBatch;
@@ -125,77 +126,74 @@ void DRW_globals_free(void);
void DRW_shgroup_world_clip_planes_from_rv3d(struct DRWShadingGroup *shgrp,
const RegionView3D *rv3d);
-struct DRWShadingGroup *shgroup_dynlines_flat_color(struct DRWPass *pass, eGPUShaderConfig sh_cfg);
-struct DRWShadingGroup *shgroup_dynlines_dashed_uniform_color(struct DRWPass *pass,
- const float color[4],
- eGPUShaderConfig sh_cfg);
-struct DRWShadingGroup *shgroup_dynpoints_uniform_color(struct DRWPass *pass,
- const float color[4],
- const float *size,
- eGPUShaderConfig sh_cfg);
-struct DRWShadingGroup *shgroup_groundlines_uniform_color(struct DRWPass *pass,
- const float color[4],
- eGPUShaderConfig sh_cfg);
-struct DRWShadingGroup *shgroup_groundpoints_uniform_color(struct DRWPass *pass,
+/* 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,
const float color[4],
eGPUShaderConfig sh_cfg);
-struct DRWShadingGroup *shgroup_instance_screenspace(struct DRWPass *pass,
+struct DRWCallBuffer *buffer_dynpoints_uniform_color(struct DRWShadingGroup *grp);
+struct DRWCallBuffer *buffer_groundlines_uniform_color(struct DRWPass *pass,
+ const float color[4],
+ eGPUShaderConfig sh_cfg);
+struct DRWCallBuffer *buffer_groundpoints_uniform_color(struct DRWPass *pass,
+ const float color[4],
+ eGPUShaderConfig sh_cfg);
+struct DRWCallBuffer *buffer_instance_screenspace(struct DRWPass *pass,
+ struct GPUBatch *geom,
+ const float *size,
+ eGPUShaderConfig sh_cfg);
+struct DRWCallBuffer *buffer_instance_solid(struct DRWPass *pass, struct GPUBatch *geom);
+struct DRWCallBuffer *buffer_instance_wire(struct DRWPass *pass, struct GPUBatch *geom);
+struct DRWCallBuffer *buffer_instance_screen_aligned(struct DRWPass *pass,
struct GPUBatch *geom,
- const float *size,
eGPUShaderConfig sh_cfg);
-struct DRWShadingGroup *shgroup_instance_solid(struct DRWPass *pass, struct GPUBatch *geom);
-struct DRWShadingGroup *shgroup_instance_wire(struct DRWPass *pass, struct GPUBatch *geom);
-struct DRWShadingGroup *shgroup_instance_screen_aligned(struct DRWPass *pass,
- struct GPUBatch *geom,
- eGPUShaderConfig sh_cfg);
-struct DRWShadingGroup *shgroup_instance_empty_axes(struct DRWPass *pass,
- struct GPUBatch *geom,
- eGPUShaderConfig sh_cfg);
-struct DRWShadingGroup *shgroup_instance_scaled(struct DRWPass *pass,
- struct GPUBatch *geom,
- eGPUShaderConfig sh_cfg);
-struct DRWShadingGroup *shgroup_instance(struct DRWPass *pass,
- struct GPUBatch *geom,
- eGPUShaderConfig sh_cfg);
-struct DRWShadingGroup *shgroup_instance_alpha(struct DRWPass *pass,
- struct GPUBatch *geom,
- eGPUShaderConfig sh_cfg);
-struct DRWShadingGroup *shgroup_instance_outline(struct DRWPass *pass,
+struct DRWCallBuffer *buffer_instance_empty_axes(struct DRWPass *pass,
struct GPUBatch *geom,
- int *baseid);
-struct DRWShadingGroup *shgroup_camera_instance(struct DRWPass *pass,
- struct GPUBatch *geom,
- eGPUShaderConfig sh_cfg);
-struct DRWShadingGroup *shgroup_distance_lines_instance(struct DRWPass *pass,
- struct GPUBatch *geom,
- eGPUShaderConfig sh_cfg);
-struct DRWShadingGroup *shgroup_spot_instance(struct DRWPass *pass,
+ eGPUShaderConfig sh_cfg);
+struct DRWCallBuffer *buffer_instance_scaled(struct DRWPass *pass,
+ struct GPUBatch *geom,
+ eGPUShaderConfig sh_cfg);
+struct DRWCallBuffer *buffer_instance(struct DRWPass *pass,
+ struct GPUBatch *geom,
+ eGPUShaderConfig sh_cfg);
+struct DRWCallBuffer *buffer_instance_alpha(struct DRWShadingGroup *grp, struct GPUBatch *geom);
+struct DRWCallBuffer *buffer_instance_outline(struct DRWPass *pass,
struct GPUBatch *geom,
- eGPUShaderConfig sh_cfg);
-struct DRWShadingGroup *shgroup_instance_mball_handles(struct DRWPass *pass,
- eGPUShaderConfig sh_cfg);
-struct DRWShadingGroup *shgroup_instance_bone_axes(struct DRWPass *pass, eGPUShaderConfig sh_cfg);
-struct DRWShadingGroup *shgroup_instance_bone_envelope_distance(struct DRWPass *pass,
- eGPUShaderConfig sh_cfg);
-struct DRWShadingGroup *shgroup_instance_bone_envelope_outline(struct DRWPass *pass,
- eGPUShaderConfig sh_cfg);
-struct DRWShadingGroup *shgroup_instance_bone_envelope_solid(struct DRWPass *pass,
- bool transp,
+ int *baseid);
+struct DRWCallBuffer *buffer_camera_instance(struct DRWPass *pass,
+ struct GPUBatch *geom,
+ eGPUShaderConfig sh_cfg);
+struct DRWCallBuffer *buffer_distance_lines_instance(struct DRWPass *pass,
+ struct GPUBatch *geom,
+ eGPUShaderConfig sh_cfg);
+struct DRWCallBuffer *buffer_spot_instance(struct DRWPass *pass,
+ struct GPUBatch *geom,
+ eGPUShaderConfig sh_cfg);
+struct DRWCallBuffer *buffer_instance_mball_handles(struct DRWPass *pass, eGPUShaderConfig sh_cfg);
+struct DRWCallBuffer *buffer_instance_bone_axes(struct DRWPass *pass, eGPUShaderConfig sh_cfg);
+struct DRWCallBuffer *buffer_instance_bone_envelope_distance(struct DRWPass *pass,
eGPUShaderConfig sh_cfg);
-struct DRWShadingGroup *shgroup_instance_bone_shape_outline(struct DRWPass *pass,
- struct GPUBatch *geom,
+struct DRWCallBuffer *buffer_instance_bone_envelope_outline(struct DRWPass *pass,
eGPUShaderConfig sh_cfg);
-struct DRWShadingGroup *shgroup_instance_bone_shape_solid(struct DRWPass *pass,
- struct GPUBatch *geom,
+struct DRWCallBuffer *buffer_instance_bone_envelope_solid(struct DRWPass *pass,
bool transp,
eGPUShaderConfig sh_cfg);
-struct DRWShadingGroup *shgroup_instance_bone_sphere_outline(struct DRWPass *pass,
- eGPUShaderConfig sh_cfg);
-struct DRWShadingGroup *shgroup_instance_bone_sphere_solid(struct DRWPass *pass,
- bool transp,
- eGPUShaderConfig sh_cfg);
-struct DRWShadingGroup *shgroup_instance_bone_stick(struct DRWPass *pass, eGPUShaderConfig sh_cfg);
-struct DRWShadingGroup *shgroup_instance_bone_dof(struct DRWPass *pass, struct GPUBatch *geom);
+struct DRWCallBuffer *buffer_instance_bone_shape_outline(struct DRWPass *pass,
+ struct GPUBatch *geom,
+ eGPUShaderConfig sh_cfg);
+struct DRWCallBuffer *buffer_instance_bone_shape_solid(struct DRWPass *pass,
+ struct GPUBatch *geom,
+ bool transp,
+ eGPUShaderConfig sh_cfg);
+struct DRWCallBuffer *buffer_instance_bone_sphere_outline(struct DRWPass *pass,
+ eGPUShaderConfig sh_cfg);
+struct DRWCallBuffer *buffer_instance_bone_sphere_solid(struct DRWPass *pass,
+ bool transp,
+ eGPUShaderConfig sh_cfg);
+struct DRWCallBuffer *buffer_instance_bone_stick(struct DRWPass *pass, eGPUShaderConfig sh_cfg);
+struct DRWCallBuffer *buffer_instance_bone_dof(struct DRWPass *pass,
+ struct GPUBatch *geom,
+ bool blend);
struct GPUShader *mpath_line_shader_get(void);
struct GPUShader *mpath_points_shader_get(void);
diff --git a/source/blender/draw/intern/draw_hair.c b/source/blender/draw/intern/draw_hair.c
index cb83265195a..50819f6a522 100644
--- a/source/blender/draw/intern/draw_hair.c
+++ b/source/blender/draw/intern/draw_hair.c
@@ -98,9 +98,9 @@ static GPUShader *hair_refine_shader_get(ParticleRefineShader sh)
void DRW_hair_init(void)
{
#ifdef USE_TRANSFORM_FEEDBACK
- g_tf_pass = DRW_pass_create("Update Hair Pass", DRW_STATE_TRANS_FEEDBACK);
+ g_tf_pass = DRW_pass_create("Update Hair Pass", 0);
#else
- g_tf_pass = DRW_pass_create("Update Hair Pass", DRW_STATE_WRITE_COLOR | DRW_STATE_POINT);
+ g_tf_pass = DRW_pass_create("Update Hair Pass", DRW_STATE_WRITE_COLOR);
#endif
}
@@ -195,7 +195,7 @@ static DRWShadingGroup *drw_shgroup_create_hair_procedural_ex(Object *object,
shgrp, "hairCloseTip", (part->shape_flag & PART_SHAPE_CLOSE_TIP) != 0);
/* TODO(fclem): Until we have a better way to cull the hair and render with orco, bypass culling
* test. */
- DRW_shgroup_call_object_add_no_cull(
+ DRW_shgroup_call_object_no_cull(
shgrp, hair_cache->final[subdiv].proc_hairs[thickness_res - 1], object);
/* Transform Feedback subdiv. */
@@ -224,7 +224,7 @@ static DRWShadingGroup *drw_shgroup_create_hair_procedural_ex(Object *object,
DRW_shgroup_uniform_texture(tf_shgrp, "hairStrandBuffer", hair_cache->strand_tex);
DRW_shgroup_uniform_texture(tf_shgrp, "hairStrandSegBuffer", hair_cache->strand_seg_tex);
DRW_shgroup_uniform_int(tf_shgrp, "hairStrandsRes", &hair_cache->final[subdiv].strands_res, 1);
- DRW_shgroup_call_procedural_points_add(tf_shgrp, final_points_len, NULL);
+ DRW_shgroup_call_procedural_points(tf_shgrp, final_points_len, NULL);
}
return shgrp;
diff --git a/source/blender/draw/intern/draw_instance_data.c b/source/blender/draw/intern/draw_instance_data.c
index e8d91309e06..e7a41ee3e43 100644
--- a/source/blender/draw/intern/draw_instance_data.c
+++ b/source/blender/draw/intern/draw_instance_data.c
@@ -36,33 +36,9 @@
#include "MEM_guardedalloc.h"
#include "BLI_utildefines.h"
#include "BLI_mempool.h"
+#include "BLI_memblock.h"
-#define BUFFER_CHUNK_SIZE 32
-#define BUFFER_VERTS_CHUNK 32
-
-typedef struct DRWBatchingBuffer {
- struct DRWShadingGroup *shgroup; /* Link back to the owning shGroup. Also tells if it's used */
- GPUVertFormat *format; /* Identifier. */
- GPUVertBuf *vert; /* GPUVertBuf contained in the GPUBatch. */
- GPUBatch *batch; /* GPUBatch containing the GPUVertBuf. */
-} DRWBatchingBuffer;
-
-typedef struct DRWInstancingBuffer {
- struct DRWShadingGroup *shgroup; /* Link back to the owning shGroup. Also tells if it's used */
- GPUVertFormat *format; /* Identifier. */
- GPUBatch *instance; /* Identifier. */
- GPUVertBuf *vert; /* GPUVertBuf contained in the GPUBatch. */
- GPUBatch *batch; /* GPUBatch containing the GPUVertBuf. */
-} DRWInstancingBuffer;
-
-typedef struct DRWInstanceChunk {
- size_t cursor; /* Offset to the next instance data. */
- size_t alloc_size; /* Number of DRWBatchingBuffer/Batches alloc'd in ibufs/btchs. */
- union {
- DRWBatchingBuffer *bbufs;
- DRWInstancingBuffer *ibufs;
- };
-} DRWInstanceChunk;
+#include "intern/gpu_primitive_private.h"
struct DRWInstanceData {
struct DRWInstanceData *next;
@@ -77,212 +53,167 @@ struct DRWInstanceDataList {
DRWInstanceData *idata_head[MAX_INSTANCE_DATA_SIZE];
DRWInstanceData *idata_tail[MAX_INSTANCE_DATA_SIZE];
- DRWInstanceChunk instancing;
- DRWInstanceChunk batching;
+ BLI_memblock *pool_instancing;
+ BLI_memblock *pool_batching;
+ BLI_memblock *pool_buffers;
};
+typedef struct DRWTempBufferHandle {
+ /** Must be first for casting. */
+ GPUVertBuf buf;
+ /** Format pointer for reuse. */
+ GPUVertFormat *format;
+ /** Touched vertex length for resize. */
+ uint *vert_len;
+} DRWTempBufferHandle;
+
static ListBase g_idatalists = {NULL, NULL};
/* -------------------------------------------------------------------- */
/** \name Instance Buffer Management
* \{ */
-/**
- * This manager allows to distribute existing batches for instancing
- * attributes. This reduce the number of batches creation.
- * Querying a batch is done with a vertex format. This format should
- * be static so that it's pointer never changes (because we are using
- * this pointer as identifier [we don't want to check the full format
- * that would be too slow]).
- */
-static void instance_batch_free(GPUBatch *batch, void *UNUSED(user_data))
+static void instance_batch_free(GPUBatch *geom, void *UNUSED(user_data))
{
- if (batch->verts[0] == NULL) {
+ if (geom->verts[0] == NULL) {
/** XXX This is a false positive case.
* The batch has been requested but not init yet
* and there is a chance that it might become init.
*/
return;
}
- /* Free all batches that have the same key before they are reused. */
+
+ /* Free all batches that use the same vbos before they are reused. */
/* TODO: Make it thread safe! Batch freeing can happen from another thread. */
- /* XXX we need to iterate over all idatalists unless we make some smart
- * data structure to store the locations to update. */
- for (DRWInstanceDataList *idatalist = g_idatalists.first; idatalist;
- idatalist = idatalist->next) {
- DRWInstancingBuffer *ibuf = idatalist->instancing.ibufs;
- for (int i = 0; i < idatalist->instancing.alloc_size; i++, ibuf++) {
- if (ibuf->instance == batch) {
- BLI_assert(ibuf->shgroup == NULL); /* Make sure it has no other users. */
- GPU_VERTBUF_DISCARD_SAFE(ibuf->vert);
- GPU_BATCH_DISCARD_SAFE(ibuf->batch);
- /* Tag as non alloced. */
- ibuf->format = NULL;
+ /* FIXME: This is not really correct. The correct way would be to check based on
+ * the vertex buffers. We assume the batch containing the VBO is being when it should. */
+ /* PERF: This is doing a linear search. This can be very costly. */
+ LISTBASE_FOREACH (DRWInstanceDataList *, data_list, &g_idatalists) {
+ BLI_memblock *memblock = data_list->pool_instancing;
+ BLI_memblock_iter iter;
+ BLI_memblock_iternew(memblock, &iter);
+ GPUBatch *batch;
+ while ((batch = (GPUBatch *)BLI_memblock_iterstep(&iter))) {
+ /* Only check verts[0] that's enough. */
+ if (batch->verts[0] == geom->verts[0]) {
+ GPU_batch_clear(batch);
}
}
}
}
-void DRW_batching_buffer_request(DRWInstanceDataList *idatalist,
- GPUVertFormat *format,
- GPUPrimType type,
- struct DRWShadingGroup *shgroup,
- GPUBatch **r_batch,
- GPUVertBuf **r_vert)
+/**
+ * This manager allows to distribute existing batches for instancing
+ * attributes. This reduce the number of batches creation.
+ * Querying a batch is done with a vertex format. This format should
+ * be static so that it's pointer never changes (because we are using
+ * this pointer as identifier [we don't want to check the full format
+ * that would be too slow]).
+ */
+GPUVertBuf *DRW_temp_buffer_request(DRWInstanceDataList *idatalist,
+ GPUVertFormat *format,
+ uint *vert_len)
{
- DRWInstanceChunk *chunk = &idatalist->batching;
- DRWBatchingBuffer *bbuf = idatalist->batching.bbufs;
- BLI_assert(format);
- /* Search for an unused batch. */
- for (int i = 0; i < idatalist->batching.alloc_size; i++, bbuf++) {
- if (bbuf->shgroup == NULL) {
- if (bbuf->format == format) {
- bbuf->shgroup = shgroup;
- *r_batch = bbuf->batch;
- *r_vert = bbuf->vert;
- return;
- }
- }
- }
- int new_id = 0; /* Find insertion point. */
- for (; new_id < chunk->alloc_size; ++new_id) {
- if (chunk->bbufs[new_id].format == NULL) {
- break;
- }
+ BLI_assert(format != NULL);
+ BLI_assert(vert_len != NULL);
+
+ DRWTempBufferHandle *handle = BLI_memblock_alloc(idatalist->pool_buffers);
+ GPUVertBuf *vert = &handle->buf;
+ handle->vert_len = vert_len;
+
+ if (handle->format != format) {
+ handle->format = format;
+ /* TODO/PERF: Save the allocated data from freeing to avoid reallocation. */
+ GPU_vertbuf_clear(vert);
+ GPU_vertbuf_init_with_format_ex(vert, format, GPU_USAGE_DYNAMIC);
+ GPU_vertbuf_data_alloc(vert, DRW_BUFFER_VERTS_CHUNK);
}
- /* If there is no batch left. Allocate more. */
- if (new_id == chunk->alloc_size) {
- new_id = chunk->alloc_size;
- chunk->alloc_size += BUFFER_CHUNK_SIZE;
- chunk->bbufs = MEM_reallocN(chunk->bbufs, chunk->alloc_size * sizeof(DRWBatchingBuffer));
- memset(chunk->bbufs + new_id, 0, sizeof(DRWBatchingBuffer) * BUFFER_CHUNK_SIZE);
- }
- /* Create the batch. */
- bbuf = chunk->bbufs + new_id;
- bbuf->vert = *r_vert = GPU_vertbuf_create_with_format_ex(format, GPU_USAGE_DYNAMIC);
- bbuf->batch = *r_batch = GPU_batch_create_ex(type, bbuf->vert, NULL, 0);
- bbuf->format = format;
- bbuf->shgroup = shgroup;
- GPU_vertbuf_data_alloc(*r_vert, BUFFER_VERTS_CHUNK);
+ return vert;
}
-void DRW_instancing_buffer_request(DRWInstanceDataList *idatalist,
- GPUVertFormat *format,
- GPUBatch *instance,
- struct DRWShadingGroup *shgroup,
- GPUBatch **r_batch,
- GPUVertBuf **r_vert)
+/* NOTE: Does not return a valid drawable batch until DRW_instance_buffer_finish has run. */
+GPUBatch *DRW_temp_batch_instance_request(DRWInstanceDataList *idatalist,
+ GPUVertBuf *buf,
+ GPUBatch *geom)
{
- DRWInstanceChunk *chunk = &idatalist->instancing;
- DRWInstancingBuffer *ibuf = idatalist->instancing.ibufs;
- BLI_assert(format);
- /* Search for an unused batch. */
- for (int i = 0; i < idatalist->instancing.alloc_size; i++, ibuf++) {
- if (ibuf->shgroup == NULL) {
- if (ibuf->format == format) {
- if (ibuf->instance == instance) {
- ibuf->shgroup = shgroup;
- *r_batch = ibuf->batch;
- *r_vert = ibuf->vert;
- return;
- }
- }
+ /* Do not call this with a batch that is already an instancing batch. */
+ BLI_assert(geom->inst == NULL);
+
+ GPUBatch *batch = BLI_memblock_alloc(idatalist->pool_instancing);
+ bool is_compatible = (batch->gl_prim_type == geom->gl_prim_type) && (batch->inst == buf) &&
+ (batch->phase == GPU_BATCH_READY_TO_DRAW);
+ for (int i = 0; i < GPU_BATCH_VBO_MAX_LEN && is_compatible; i++) {
+ if (batch->verts[i] != geom->verts[i]) {
+ is_compatible = false;
}
}
- int new_id = 0; /* Find insertion point. */
- for (; new_id < chunk->alloc_size; ++new_id) {
- if (chunk->ibufs[new_id].format == NULL) {
- break;
- }
+
+ if (!is_compatible) {
+ GPU_batch_clear(batch);
+ /* Save args and init later */
+ batch->inst = buf;
+ batch->phase = GPU_BATCH_READY_TO_BUILD;
+ batch->verts[0] = (void *)geom; /* HACK to save the pointer without other alloc. */
+
+ /* Make sure to free this batch if the instance geom gets free. */
+ GPU_batch_callback_free_set(geom, &instance_batch_free, NULL);
}
- /* If there is no batch left. Allocate more. */
- if (new_id == chunk->alloc_size) {
- new_id = chunk->alloc_size;
- chunk->alloc_size += BUFFER_CHUNK_SIZE;
- chunk->ibufs = MEM_reallocN(chunk->ibufs, chunk->alloc_size * sizeof(DRWInstancingBuffer));
- memset(chunk->ibufs + new_id, 0, sizeof(DRWInstancingBuffer) * BUFFER_CHUNK_SIZE);
+ return batch;
+}
+
+/* NOTE: Use only with buf allocated via DRW_temp_buffer_request. */
+GPUBatch *DRW_temp_batch_request(DRWInstanceDataList *idatalist,
+ GPUVertBuf *buf,
+ GPUPrimType prim_type)
+{
+ GPUBatch *batch = BLI_memblock_alloc(idatalist->pool_batching);
+ bool is_compatible = (batch->verts[0] == buf) &&
+ (batch->gl_prim_type == convert_prim_type_to_gl(prim_type));
+ if (!is_compatible) {
+ GPU_batch_clear(batch);
+ GPU_batch_init(batch, prim_type, buf, NULL);
}
- /* Create the batch. */
- ibuf = chunk->ibufs + new_id;
- ibuf->vert = *r_vert = GPU_vertbuf_create_with_format_ex(format, GPU_USAGE_DYNAMIC);
- ibuf->batch = *r_batch = MEM_callocN(sizeof(GPUBatch), "GPUBatch");
- ibuf->format = format;
- ibuf->shgroup = shgroup;
- ibuf->instance = instance;
- GPU_vertbuf_data_alloc(*r_vert, BUFFER_VERTS_CHUNK);
- /* Make sure to free this ibuf if the instance batch gets free. */
- GPU_batch_callback_free_set(instance, &instance_batch_free, NULL);
+ return batch;
+}
+
+static void temp_buffer_handle_free(DRWTempBufferHandle *handle)
+{
+ handle->format = NULL;
+ GPU_vertbuf_clear(&handle->buf);
}
void DRW_instance_buffer_finish(DRWInstanceDataList *idatalist)
{
- size_t realloc_size = 1; /* Avoid 0 size realloc. */
- /* Resize down buffers in use and send data to GPU & free unused buffers. */
- DRWInstanceChunk *batching = &idatalist->batching;
- DRWBatchingBuffer *bbuf = batching->bbufs;
- for (int i = 0; i < batching->alloc_size; i++, bbuf++) {
- if (bbuf->shgroup != NULL) {
- realloc_size = i + 1;
- uint vert_len = DRW_shgroup_get_instance_count(bbuf->shgroup);
- vert_len += (vert_len == 0) ? 1 : 0; /* Do not realloc to 0 size buffer */
- if (vert_len + BUFFER_VERTS_CHUNK <= bbuf->vert->vertex_len) {
- uint size = vert_len + BUFFER_VERTS_CHUNK - 1;
- size = size - size % BUFFER_VERTS_CHUNK;
- GPU_vertbuf_data_resize(bbuf->vert, size);
+ /* Resize down buffers in use and send data to GPU. */
+ BLI_memblock_iter iter;
+ DRWTempBufferHandle *handle;
+ BLI_memblock_iternew(idatalist->pool_buffers, &iter);
+ while ((handle = BLI_memblock_iterstep(&iter))) {
+ if (handle->vert_len != NULL) {
+ uint vert_len = *(handle->vert_len);
+ uint target_buf_size = ((vert_len / DRW_BUFFER_VERTS_CHUNK) + 1) * DRW_BUFFER_VERTS_CHUNK;
+ if (target_buf_size < handle->buf.vertex_alloc) {
+ GPU_vertbuf_data_resize(&handle->buf, target_buf_size);
}
- GPU_vertbuf_use(bbuf->vert); /* Send data. */
- bbuf->shgroup = NULL; /* Set as non used for the next round. */
- }
- else {
- GPU_VERTBUF_DISCARD_SAFE(bbuf->vert);
- GPU_BATCH_DISCARD_SAFE(bbuf->batch);
- bbuf->format = NULL; /* Tag as non alloced. */
+ GPU_vertbuf_data_len_set(&handle->buf, vert_len);
+ GPU_vertbuf_use(&handle->buf); /* Send data. */
}
}
- /* Rounding up to nearest chunk size. */
- realloc_size += BUFFER_CHUNK_SIZE - 1;
- realloc_size -= realloc_size % BUFFER_CHUNK_SIZE;
- /* Resize down if necessary. */
- if (realloc_size < batching->alloc_size) {
- batching->alloc_size = realloc_size;
- batching->ibufs = MEM_reallocN(batching->ibufs, realloc_size * sizeof(DRWBatchingBuffer));
- }
-
- realloc_size = 1;
- /* Resize down buffers in use and send data to GPU & free unused buffers. */
- DRWInstanceChunk *instancing = &idatalist->instancing;
- DRWInstancingBuffer *ibuf = instancing->ibufs;
- for (int i = 0; i < instancing->alloc_size; i++, ibuf++) {
- if (ibuf->shgroup != NULL) {
- realloc_size = i + 1;
- uint vert_len = DRW_shgroup_get_instance_count(ibuf->shgroup);
- vert_len += (vert_len == 0) ? 1 : 0; /* Do not realloc to 0 size buffer */
- if (vert_len + BUFFER_VERTS_CHUNK <= ibuf->vert->vertex_len) {
- uint size = vert_len + BUFFER_VERTS_CHUNK - 1;
- size = size - size % BUFFER_VERTS_CHUNK;
- GPU_vertbuf_data_resize(ibuf->vert, size);
- }
- GPU_vertbuf_use(ibuf->vert); /* Send data. */
- /* Setup batch now that we are sure ibuf->instance is setup. */
- GPU_batch_copy(ibuf->batch, ibuf->instance);
- GPU_batch_instbuf_set(ibuf->batch, ibuf->vert, false);
- ibuf->shgroup = NULL; /* Set as non used for the next round. */
- }
- else {
- GPU_VERTBUF_DISCARD_SAFE(ibuf->vert);
- GPU_BATCH_DISCARD_SAFE(ibuf->batch);
- ibuf->format = NULL; /* Tag as non alloced. */
+ /* Finish pending instancing batches. */
+ GPUBatch *batch;
+ BLI_memblock_iternew(idatalist->pool_instancing, &iter);
+ while ((batch = BLI_memblock_iterstep(&iter))) {
+ if (batch->phase == GPU_BATCH_READY_TO_BUILD) {
+ GPUVertBuf *inst = batch->inst;
+ GPUBatch *geom = (void *)batch->verts[0]; /* HACK see DRW_temp_batch_instance_request. */
+ GPU_batch_copy(batch, geom);
+ GPU_batch_instbuf_set(batch, inst, false);
}
}
- /* Rounding up to nearest chunk size. */
- realloc_size += BUFFER_CHUNK_SIZE - 1;
- realloc_size -= realloc_size % BUFFER_CHUNK_SIZE;
- /* Resize down if necessary. */
- if (realloc_size < instancing->alloc_size) {
- instancing->alloc_size = realloc_size;
- instancing->ibufs = MEM_reallocN(instancing->ibufs,
- realloc_size * sizeof(DRWInstancingBuffer));
- }
+ /* Resize pools and free unused. */
+ BLI_memblock_clear(idatalist->pool_buffers, (MemblockValFreeFP)temp_buffer_handle_free);
+ BLI_memblock_clear(idatalist->pool_instancing, (MemblockValFreeFP)GPU_batch_clear);
+ BLI_memblock_clear(idatalist->pool_batching, (MemblockValFreeFP)GPU_batch_clear);
}
/** \} */
@@ -352,12 +283,10 @@ DRWInstanceData *DRW_instance_data_request(DRWInstanceDataList *idatalist, uint
DRWInstanceDataList *DRW_instance_data_list_create(void)
{
DRWInstanceDataList *idatalist = MEM_callocN(sizeof(DRWInstanceDataList), "DRWInstanceDataList");
- idatalist->batching.bbufs = MEM_callocN(sizeof(DRWBatchingBuffer) * BUFFER_CHUNK_SIZE,
- "DRWBatchingBuffers");
- idatalist->batching.alloc_size = BUFFER_CHUNK_SIZE;
- idatalist->instancing.ibufs = MEM_callocN(sizeof(DRWInstancingBuffer) * BUFFER_CHUNK_SIZE,
- "DRWInstancingBuffers");
- idatalist->instancing.alloc_size = BUFFER_CHUNK_SIZE;
+
+ 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);
@@ -378,19 +307,9 @@ void DRW_instance_data_list_free(DRWInstanceDataList *idatalist)
idatalist->idata_tail[i] = NULL;
}
- DRWBatchingBuffer *bbuf = idatalist->batching.bbufs;
- for (int i = 0; i < idatalist->batching.alloc_size; i++, bbuf++) {
- GPU_VERTBUF_DISCARD_SAFE(bbuf->vert);
- GPU_BATCH_DISCARD_SAFE(bbuf->batch);
- }
- MEM_freeN(idatalist->batching.bbufs);
-
- DRWInstancingBuffer *ibuf = idatalist->instancing.ibufs;
- for (int i = 0; i < idatalist->instancing.alloc_size; i++, ibuf++) {
- GPU_VERTBUF_DISCARD_SAFE(ibuf->vert);
- GPU_BATCH_DISCARD_SAFE(ibuf->batch);
- }
- MEM_freeN(idatalist->instancing.ibufs);
+ BLI_memblock_destroy(idatalist->pool_buffers, (MemblockValFreeFP)temp_buffer_handle_free);
+ BLI_memblock_destroy(idatalist->pool_instancing, (MemblockValFreeFP)GPU_batch_clear);
+ BLI_memblock_destroy(idatalist->pool_batching, (MemblockValFreeFP)GPU_batch_clear);
BLI_remlink(&g_idatalists, idatalist);
}
diff --git a/source/blender/draw/intern/draw_instance_data.h b/source/blender/draw/intern/draw_instance_data.h
index ea5c6ac7bb2..d88de1a58e2 100644
--- a/source/blender/draw/intern/draw_instance_data.h
+++ b/source/blender/draw/intern/draw_instance_data.h
@@ -30,6 +30,8 @@
#define MAX_INSTANCE_DATA_SIZE 64 /* Can be adjusted for more */
+#define DRW_BUFFER_VERTS_CHUNK 128
+
typedef struct DRWInstanceData DRWInstanceData;
typedef struct DRWInstanceDataList DRWInstanceDataList;
@@ -38,18 +40,15 @@ struct DRWShadingGroup;
void *DRW_instance_data_next(DRWInstanceData *idata);
DRWInstanceData *DRW_instance_data_request(DRWInstanceDataList *idatalist, uint attr_size);
-void DRW_batching_buffer_request(DRWInstanceDataList *idatalist,
- GPUVertFormat *format,
- GPUPrimType type,
- struct DRWShadingGroup *shgroup,
- GPUBatch **r_batch,
- GPUVertBuf **r_vert);
-void DRW_instancing_buffer_request(DRWInstanceDataList *idatalist,
- GPUVertFormat *format,
- GPUBatch *instance,
- struct DRWShadingGroup *shgroup,
- GPUBatch **r_batch,
- GPUVertBuf **r_vert);
+GPUVertBuf *DRW_temp_buffer_request(DRWInstanceDataList *idatalist,
+ GPUVertFormat *format,
+ uint *vert_len);
+GPUBatch *DRW_temp_batch_instance_request(DRWInstanceDataList *idatalist,
+ GPUVertBuf *buf,
+ GPUBatch *geom);
+GPUBatch *DRW_temp_batch_request(DRWInstanceDataList *idatalist,
+ GPUVertBuf *buf,
+ GPUPrimType type);
/* Upload all instance data to the GPU as soon as possible. */
void DRW_instance_buffer_finish(DRWInstanceDataList *idatalist);
diff --git a/source/blender/draw/intern/draw_manager.c b/source/blender/draw/intern/draw_manager.c
index 5c88c1f93db..be046abfc8c 100644
--- a/source/blender/draw/intern/draw_manager.c
+++ b/source/blender/draw/intern/draw_manager.c
@@ -22,16 +22,19 @@
#include <stdio.h>
+#include "BLI_alloca.h"
#include "BLI_listbase.h"
-#include "BLI_mempool.h"
+#include "BLI_memblock.h"
#include "BLI_rect.h"
#include "BLI_string.h"
#include "BLI_threads.h"
#include "BLF_api.h"
+#include "BKE_anim.h"
#include "BKE_colortools.h"
#include "BKE_curve.h"
+#include "BKE_editmesh.h"
#include "BKE_global.h"
#include "BKE_gpencil.h"
#include "BKE_lattice.h"
@@ -40,6 +43,7 @@
#include "BKE_mesh.h"
#include "BKE_object.h"
#include "BKE_particle.h"
+#include "BKE_paint.h"
#include "BKE_pointcache.h"
#include "draw_manager.h"
@@ -212,6 +216,11 @@ bool DRW_object_use_hide_faces(const struct Object *ob)
return false;
}
+bool DRW_object_use_pbvh_drawing(const struct Object *ob)
+{
+ return ob->sculpt && (ob->sculpt->mode_type == OB_MODE_SCULPT);
+}
+
bool DRW_object_is_visible_psys_in_active_context(const Object *object, const ParticleSystem *psys)
{
const bool for_render = DRW_state_is_image_render();
@@ -356,7 +365,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);
@@ -447,7 +457,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);
}
@@ -520,19 +531,21 @@ static void drw_viewport_cache_resize(void)
if (DST.vmempool != NULL) {
/* Release Image textures. */
- BLI_mempool_iter iter;
+ BLI_memblock_iter iter;
GPUTexture **tex;
- BLI_mempool_iternew(DST.vmempool->images, &iter);
- while ((tex = BLI_mempool_iterstep(&iter))) {
+ BLI_memblock_iternew(DST.vmempool->images, &iter);
+ while ((tex = BLI_memblock_iterstep(&iter))) {
GPU_texture_free(*tex);
}
- BLI_mempool_clear_ex(DST.vmempool->calls, BLI_mempool_len(DST.vmempool->calls));
- BLI_mempool_clear_ex(DST.vmempool->states, BLI_mempool_len(DST.vmempool->states));
- BLI_mempool_clear_ex(DST.vmempool->shgroups, BLI_mempool_len(DST.vmempool->shgroups));
- BLI_mempool_clear_ex(DST.vmempool->uniforms, BLI_mempool_len(DST.vmempool->uniforms));
- BLI_mempool_clear_ex(DST.vmempool->passes, BLI_mempool_len(DST.vmempool->passes));
- BLI_mempool_clear_ex(DST.vmempool->images, BLI_mempool_len(DST.vmempool->images));
+ 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);
}
DRW_instance_data_list_free_unused(DST.idatalist);
@@ -597,24 +610,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_mempool_create(sizeof(DRWCall), 0, 512, 0);
+ DST.vmempool->calls = BLI_memblock_create(sizeof(DRWCall));
}
if (DST.vmempool->states == NULL) {
- DST.vmempool->states = BLI_mempool_create(
- sizeof(DRWCallState), 0, 512, BLI_MEMPOOL_ALLOW_ITER);
+ 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_mempool_create(sizeof(DRWShadingGroup), 0, 256, 0);
+ DST.vmempool->shgroups = BLI_memblock_create(sizeof(DRWShadingGroup));
}
if (DST.vmempool->uniforms == NULL) {
- DST.vmempool->uniforms = BLI_mempool_create(sizeof(DRWUniform), 0, 512, 0);
+ 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_mempool_create(sizeof(DRWPass), 0, 64, 0);
+ DST.vmempool->passes = BLI_memblock_create(sizeof(DRWPass));
}
if (DST.vmempool->images == NULL) {
- DST.vmempool->images = BLI_mempool_create(
- sizeof(GPUTexture *), 0, 512, BLI_MEMPOOL_ALLOW_ITER);
+ DST.vmempool->images = BLI_memblock_create(sizeof(GPUTexture *));
}
DST.idatalist = GPU_viewport_instance_data_list_get(DST.viewport);
@@ -631,36 +648,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);
}
@@ -669,116 +685,94 @@ 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)
+DefaultFramebufferList *DRW_viewport_framebuffer_list_get(void)
{
- 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]);
+ return GPU_viewport_framebuffer_list_get(DST.viewport);
}
-void DRW_viewport_matrix_get_all(DRWMatrixState *state)
+DefaultTextureList *DRW_viewport_texture_list_get(void)
{
- memcpy(state, DST.view_data.matstate.mat, sizeof(DRWMatrixState));
+ return GPU_viewport_texture_list_get(DST.viewport);
}
-void DRW_viewport_matrix_override_set(const float mat[4][4], DRWViewportMatrixType type)
+void DRW_viewport_request_redraw(void)
{
- 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;
+ GPU_viewport_tag_update(DST.viewport);
}
-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;
-}
+/* -------------------------------------------------------------------- */
+/** \name Duplis
+ * \{ */
-void DRW_viewport_matrix_override_unset_all(void)
+static void drw_duplidata_load(DupliObject *dupli)
{
- memcpy(DST.view_data.matstate.mat, DST.original_mat.mat, sizeof(DRWMatrixState));
- DST.override_mat = 0;
- DST.dirty_mat = true;
- DST.clipping.updated = false;
-}
+ if (dupli == NULL) {
+ return;
+ }
-bool DRW_viewport_is_persp_get(void)
-{
- RegionView3D *rv3d = DST.draw_ctx.rv3d;
- if (rv3d) {
- return rv3d->is_persp;
+ if (DST.dupli_origin != dupli->ob) {
+ DST.dupli_origin = dupli->ob;
}
else {
- return DST.view_data.matstate.mat[DRW_MAT_WIN][3][3] == 0.0f;
+ /* Same data as previous iter. No need to poll ghash for this. */
+ return;
}
-}
-
-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];
+ if (DST.dupli_ghash == NULL) {
+ DST.dupli_ghash = BLI_ghash_ptr_new(__func__);
}
-}
-float DRW_viewport_far_distance_get(void)
-{
- float projmat[4][4];
- DRW_viewport_matrix_get(projmat, DRW_MAT_WIN);
+ void **value;
+ if (!BLI_ghash_ensure_p(DST.dupli_ghash, DST.dupli_origin, &value)) {
+ *value = MEM_callocN(sizeof(void *) * DST.enabled_engine_count, __func__);
- 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];
+ /* TODO: Meh a bit out of place but this is nice as it is
+ * only done once per "original" object. */
+ drw_batch_cache_validate(DST.dupli_origin);
}
+ DST.dupli_datas = *(void ***)value;
}
-DefaultFramebufferList *DRW_viewport_framebuffer_list_get(void)
+static void duplidata_value_free(void *val)
{
- return GPU_viewport_framebuffer_list_get(DST.viewport);
+ void **dupli_datas = val;
+ for (int i = 0; i < DST.enabled_engine_count; i++) {
+ MEM_SAFE_FREE(dupli_datas[i]);
+ }
+ MEM_freeN(val);
}
-DefaultTextureList *DRW_viewport_texture_list_get(void)
+static void drw_duplidata_free(void)
{
- return GPU_viewport_texture_list_get(DST.viewport);
+ if (DST.dupli_ghash != NULL) {
+ BLI_ghash_free(DST.dupli_ghash,
+ (void (*)(void *key))drw_batch_cache_generate_requested,
+ duplidata_value_free);
+ DST.dupli_ghash = NULL;
+ }
}
-void DRW_viewport_request_redraw(void)
+/* Return NULL if not a dupli or a pointer of pointer to the engine data */
+void **DRW_duplidata_get(void *vedata)
{
- GPU_viewport_tag_update(DST.viewport);
+ if (DST.dupli_source == NULL) {
+ return NULL;
+ }
+ /* XXX Search engine index by using vedata array */
+ for (int i = 0; i < DST.enabled_engine_count; i++) {
+ if (DST.vedata_array[i] == vedata) {
+ return &DST.dupli_datas[i];
+ }
+ }
+ return NULL;
}
/** \} */
@@ -1039,9 +1033,14 @@ static void drw_engines_init(void)
static void drw_engines_cache_init(void)
{
- for (LinkData *link = DST.enabled_engines.first; link; link = link->next) {
+ DST.enabled_engine_count = BLI_listbase_count(&DST.enabled_engines);
+ DST.vedata_array = MEM_mallocN(sizeof(void *) * DST.enabled_engine_count, __func__);
+
+ int i = 0;
+ for (LinkData *link = DST.enabled_engines.first; link; link = link->next, i++) {
DrawEngineType *engine = link->data;
ViewportEngineData *data = drw_viewport_engine_data_ensure(engine);
+ DST.vedata_array[i] = data;
if (data->text_draw_cache) {
DRW_text_cache_destroy(data->text_draw_cache);
@@ -1083,9 +1082,15 @@ static void drw_engines_cache_populate(Object *ob)
* ourselves here. */
drw_drawdata_unlink_dupli((ID *)ob);
- for (LinkData *link = DST.enabled_engines.first; link; link = link->next) {
+ /* Validation for dupli objects happen elsewhere. */
+ if (!DST.dupli_source) {
+ drw_batch_cache_validate(ob);
+ }
+
+ int i = 0;
+ for (LinkData *link = DST.enabled_engines.first; link; link = link->next, i++) {
DrawEngineType *engine = link->data;
- ViewportEngineData *data = drw_viewport_engine_data_ensure(engine);
+ ViewportEngineData *data = DST.vedata_array[i];
if (engine->id_update) {
engine->id_update(data, &ob->id);
@@ -1098,7 +1103,9 @@ static void drw_engines_cache_populate(Object *ob)
/* TODO: in the future it would be nice to generate once for all viewports.
* But we need threaded DRW manager first. */
- drw_batch_cache_generate_requested(ob);
+ if (!DST.dupli_source) {
+ drw_batch_cache_generate_requested(ob);
+ }
/* ... and clearing it here too because theses draw data are
* from a mempool and must not be free individually by depsgraph. */
@@ -1107,14 +1114,16 @@ static void drw_engines_cache_populate(Object *ob)
static void drw_engines_cache_finish(void)
{
- for (LinkData *link = DST.enabled_engines.first; link; link = link->next) {
+ int i = 0;
+ for (LinkData *link = DST.enabled_engines.first; link; link = link->next, i++) {
DrawEngineType *engine = link->data;
- ViewportEngineData *data = drw_viewport_engine_data_ensure(engine);
+ ViewportEngineData *data = DST.vedata_array[i];
if (engine->cache_finish) {
engine->cache_finish(data);
}
}
+ MEM_freeN(DST.vedata_array);
}
static void drw_engines_draw_background(void)
@@ -1390,17 +1399,19 @@ static void drw_engines_disable(void)
BLI_freelistN(&DST.enabled_engines);
}
-static uint DRW_engines_get_hash(void)
+static void drw_engines_data_validate(void)
{
- uint hash = 0;
- /* The cache depends on enabled engines */
- /* FIXME : if collision occurs ... segfault */
+ int enabled_engines = BLI_listbase_count(&DST.enabled_engines);
+ void **engine_handle_array = BLI_array_alloca(engine_handle_array, enabled_engines + 1);
+ int i = 0;
+
for (LinkData *link = DST.enabled_engines.first; link; link = link->next) {
DrawEngineType *engine = link->data;
- hash += BLI_ghashutil_strhash_p(engine->idname);
+ engine_handle_array[i++] = engine;
}
+ engine_handle_array[i] = NULL;
- return hash;
+ GPU_viewport_engines_data_validate(DST.viewport, engine_handle_array);
}
/* -------------------------------------------------------------------- */
@@ -1513,8 +1524,6 @@ void DRW_draw_render_loop_ex(struct Depsgraph *depsgraph,
DST.viewport = viewport;
/* Setup viewport */
- GPU_viewport_engines_data_validate(DST.viewport, DRW_engines_get_hash());
-
DST.draw_ctx = (DRWContextState){
.ar = ar,
.rv3d = rv3d,
@@ -1534,6 +1543,8 @@ void DRW_draw_render_loop_ex(struct Depsgraph *depsgraph,
/* Get list of enabled engines */
drw_engines_enable(view_layer, engine_type);
+ drw_engines_data_validate();
+
/* Update ubos */
DRW_globals_update();
@@ -1552,23 +1563,31 @@ void DRW_draw_render_loop_ex(struct Depsgraph *depsgraph,
drw_engines_cache_init();
drw_engines_world_update(scene);
- const int object_type_exclude_viewport = v3d->object_type_exclude_viewport;
- const int iter_flag = DEG_ITER_OBJECT_FLAG_LINKED_DIRECTLY |
- DEG_ITER_OBJECT_FLAG_LINKED_VIA_SET | DEG_ITER_OBJECT_FLAG_VISIBLE |
- DEG_ITER_OBJECT_FLAG_DUPLI;
- DEG_OBJECT_ITER_BEGIN (depsgraph, ob, iter_flag) {
- if ((object_type_exclude_viewport & (1 << ob->type)) != 0) {
- continue;
- }
- if (v3d->localvd && ((v3d->local_view_uuid & ob->base_local_view_bits) == 0)) {
- continue;
+ /* Only iterate over objects for internal engines or when overlays are enabled */
+ const bool internal_engine = (engine_type->flag & RE_INTERNAL) != 0;
+ const bool draw_type_render = v3d->shading.type == OB_RENDER;
+ const bool overlays_on = (v3d->flag2 & V3D_HIDE_OVERLAYS) == 0;
+ if (internal_engine || overlays_on || !draw_type_render) {
+ const int object_type_exclude_viewport = v3d->object_type_exclude_viewport;
+ const int iter_flag = DEG_ITER_OBJECT_FLAG_LINKED_DIRECTLY |
+ DEG_ITER_OBJECT_FLAG_LINKED_VIA_SET | DEG_ITER_OBJECT_FLAG_VISIBLE |
+ DEG_ITER_OBJECT_FLAG_DUPLI;
+ DEG_OBJECT_ITER_BEGIN (depsgraph, ob, iter_flag) {
+ if ((object_type_exclude_viewport & (1 << ob->type)) != 0) {
+ continue;
+ }
+ if (v3d->localvd && ((v3d->local_view_uuid & ob->base_local_view_bits) == 0)) {
+ continue;
+ }
+ DST.dupli_parent = data_.dupli_parent;
+ DST.dupli_source = data_.dupli_object_current;
+ drw_duplidata_load(DST.dupli_source);
+ drw_engines_cache_populate(ob);
}
- DST.dupli_parent = data_.dupli_parent;
- DST.dupli_source = data_.dupli_object_current;
- drw_engines_cache_populate(ob);
+ DEG_OBJECT_ITER_END;
}
- DEG_OBJECT_ITER_END;
+ drw_duplidata_free();
drw_engines_cache_finish();
DRW_render_instance_buffer_finish();
@@ -1615,10 +1634,8 @@ void DRW_draw_render_loop_ex(struct Depsgraph *depsgraph,
drw_engines_draw_scene();
-#ifdef __APPLE__
- /* Fix 3D view being "laggy" on macos. (See T56996) */
+ /* Fix 3D view being "laggy" on macos and win+nvidia. (See T56996, T61474) */
GPU_flush();
-#endif
/* annotations - temporary drawing buffer (3d space) */
/* XXX: Or should we use a proper draw/overlay engine for this case? */
@@ -1630,16 +1647,15 @@ void DRW_draw_render_loop_ex(struct Depsgraph *depsgraph,
}
DRW_draw_callbacks_post_scene();
+ DRW_state_reset();
+
if (DST.draw_ctx.evil_C) {
- DRW_state_reset();
ED_region_draw_cb_draw(DST.draw_ctx.evil_C, DST.draw_ctx.ar, REGION_DRAW_POST_VIEW);
/* Callback can be nasty and do whatever they want with the state.
* Don't trust them! */
DRW_state_reset();
}
- DRW_state_reset();
-
drw_debug_draw();
GPU_depth_test(false);
@@ -1785,9 +1801,9 @@ static void DRW_render_gpencil_to_image(RenderEngine *engine,
void DRW_render_gpencil(struct RenderEngine *engine, struct Depsgraph *depsgraph)
{
- /* This function is only valid for Cycles
- * Eevee done all work in the Eevee render directly.
- * Maybe it can be done equal for both engines?
+ /* This function is only valid for Cycles & Workbench
+ * Eevee does all work in the Eevee render directly.
+ * Maybe it can be done equal for all engines?
*/
if (STREQ(engine->type->name, "Eevee")) {
return;
@@ -1854,7 +1870,7 @@ void DRW_render_gpencil(struct RenderEngine *engine, struct Depsgraph *depsgraph
}
RenderResult *render_result = RE_engine_get_result(engine);
- RenderLayer *render_layer = render_result->layers.first;
+ RenderLayer *render_layer = RE_GetRenderLayer(render_result, view_layer->name);
DRW_render_gpencil_to_image(engine, render_layer, &render_rect);
@@ -2011,12 +2027,20 @@ void DRW_render_object_iter(
DST.dupli_parent = data_.dupli_parent;
DST.dupli_source = data_.dupli_object_current;
DST.ob_state = NULL;
- callback(vedata, ob, engine, depsgraph);
+ drw_duplidata_load(DST.dupli_source);
- drw_batch_cache_generate_requested(ob);
+ if (!DST.dupli_source) {
+ drw_batch_cache_validate(ob);
+ }
+ callback(vedata, ob, engine, depsgraph);
+ if (!DST.dupli_source) {
+ drw_batch_cache_generate_requested(ob);
+ }
}
}
DEG_OBJECT_ITER_END;
+
+ drw_duplidata_free();
}
/* Assume a valid gl context is bound (and that the gl_context_mutex has been acquired).
@@ -2246,14 +2270,10 @@ void DRW_draw_select_loop(struct Depsgraph *depsgraph,
drw_engines_world_update(scene);
if (use_obedit) {
-# if 0
- drw_engines_cache_populate(obact);
-# else
FOREACH_OBJECT_IN_MODE_BEGIN (view_layer, v3d, obact->type, obact->mode, ob_iter) {
drw_engines_cache_populate(ob_iter);
}
FOREACH_OBJECT_IN_MODE_END;
-# endif
}
else {
const int iter_flag = DEG_ITER_OBJECT_FLAG_LINKED_DIRECTLY |
@@ -2284,16 +2304,18 @@ void DRW_draw_select_loop(struct Depsgraph *depsgraph,
/* This relies on dupli instances being after their instancing object. */
if ((ob->base_flag & BASE_FROM_DUPLI) == 0) {
Object *ob_orig = DEG_get_original_object(ob);
- DRW_select_load_id(ob_orig->select_id);
+ DRW_select_load_id(ob_orig->runtime.select_id);
}
DST.dupli_parent = data_.dupli_parent;
DST.dupli_source = data_.dupli_object_current;
+ drw_duplidata_load(DST.dupli_source);
drw_engines_cache_populate(ob);
}
}
DEG_OBJECT_ITER_END;
}
+ drw_duplidata_free();
drw_engines_cache_finish();
DRW_render_instance_buffer_finish();
@@ -2349,8 +2371,6 @@ void DRW_draw_select_loop(struct Depsgraph *depsgraph,
*/
static void drw_draw_depth_loop_imp(void)
{
- DRW_opengl_context_enable();
-
/* Setup framebuffer */
DefaultFramebufferList *fbl = (DefaultFramebufferList *)GPU_viewport_framebuffer_list_get(
DST.viewport);
@@ -2388,10 +2408,12 @@ static void drw_draw_depth_loop_imp(void)
DST.dupli_parent = data_.dupli_parent;
DST.dupli_source = data_.dupli_object_current;
+ drw_duplidata_load(DST.dupli_source);
drw_engines_cache_populate(ob);
}
DEG_OBJECT_ITER_END;
+ drw_duplidata_free();
drw_engines_cache_finish();
DRW_render_instance_buffer_finish();
@@ -2411,9 +2433,6 @@ static void drw_draw_depth_loop_imp(void)
/* TODO: Reading depth for operators should be done here. */
GPU_framebuffer_restore();
-
- /* Changin context */
- DRW_opengl_context_disable();
}
/**
@@ -2429,6 +2448,8 @@ void DRW_draw_depth_loop(struct Depsgraph *depsgraph,
ViewLayer *view_layer = DEG_get_evaluated_view_layer(depsgraph);
RegionView3D *rv3d = ar->regiondata;
+ DRW_opengl_context_enable();
+
/* Reset before using it. */
drw_state_prepare_clean_for_draw(&DST);
@@ -2463,6 +2484,9 @@ void DRW_draw_depth_loop(struct Depsgraph *depsgraph,
/* Avoid accidental reuse. */
drw_state_ensure_not_reused(&DST);
#endif
+
+ /* Changin context */
+ DRW_opengl_context_disable();
}
/**
@@ -2477,6 +2501,8 @@ void DRW_draw_depth_loop_gpencil(struct Depsgraph *depsgraph,
ViewLayer *view_layer = DEG_get_evaluated_view_layer(depsgraph);
RegionView3D *rv3d = ar->regiondata;
+ DRW_opengl_context_enable();
+
/* Reset before using it. */
drw_state_prepare_clean_for_draw(&DST);
@@ -2502,6 +2528,15 @@ void DRW_draw_depth_loop_gpencil(struct Depsgraph *depsgraph,
/* Avoid accidental reuse. */
drw_state_ensure_not_reused(&DST);
#endif
+
+ /* Changin context */
+ DRW_opengl_context_disable();
+}
+
+/** 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]);
}
/**
@@ -2547,7 +2582,7 @@ void DRW_draw_depth_object(ARegion *ar, GPUViewport *viewport, Object *object)
GPU_SHADER_CFG_DEFAULT;
GPU_batch_program_set_builtin_with_config(batch, GPU_SHADER_3D_DEPTH_ONLY, sh_cfg);
if (world_clip_planes != NULL) {
- GPU_batch_uniform_4fv_array(batch, "WorldClipPlanes", 6, world_clip_planes[0]);
+ draw_world_clip_planes_from_rv3d(batch, world_clip_planes);
}
GPU_batch_draw(batch);
@@ -2567,6 +2602,204 @@ void DRW_draw_depth_object(ARegion *ar, GPUViewport *viewport, Object *object)
DRW_opengl_context_disable();
}
+static void draw_mesh_verts(GPUBatch *batch, uint offset, const float world_clip_planes[6][4])
+{
+ GPU_point_size(UI_GetThemeValuef(TH_VERTEX_SIZE));
+
+ const eGPUShaderConfig sh_cfg = world_clip_planes ? GPU_SHADER_CFG_CLIPPED :
+ GPU_SHADER_CFG_DEFAULT;
+ GPU_batch_program_set_builtin_with_config(batch, GPU_SHADER_3D_FLAT_SELECT_ID, sh_cfg);
+ GPU_batch_uniform_1ui(batch, "offset", offset);
+ if (world_clip_planes != NULL) {
+ draw_world_clip_planes_from_rv3d(batch, world_clip_planes);
+ }
+ GPU_batch_draw(batch);
+}
+
+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);
+
+ const eGPUShaderConfig sh_cfg = world_clip_planes ? GPU_SHADER_CFG_CLIPPED :
+ GPU_SHADER_CFG_DEFAULT;
+ GPU_batch_program_set_builtin_with_config(batch, GPU_SHADER_3D_FLAT_SELECT_ID, sh_cfg);
+ GPU_batch_uniform_1ui(batch, "offset", offset);
+ if (world_clip_planes != NULL) {
+ draw_world_clip_planes_from_rv3d(batch, world_clip_planes);
+ }
+ GPU_batch_draw(batch);
+
+ glProvokingVertex(GL_LAST_VERTEX_CONVENTION);
+}
+
+/* two options, facecolors or black */
+static void draw_mesh_face(GPUBatch *batch,
+ uint offset,
+ const bool use_select,
+ const float world_clip_planes[6][4])
+{
+ if (use_select) {
+ const eGPUShaderConfig sh_cfg = world_clip_planes ? GPU_SHADER_CFG_CLIPPED :
+ GPU_SHADER_CFG_DEFAULT;
+ GPU_batch_program_set_builtin_with_config(batch, GPU_SHADER_3D_FLAT_SELECT_ID, sh_cfg);
+ GPU_batch_uniform_1ui(batch, "offset", offset);
+ if (world_clip_planes != NULL) {
+ draw_world_clip_planes_from_rv3d(batch, world_clip_planes);
+ }
+ GPU_batch_draw(batch);
+ }
+ else {
+ const eGPUShaderConfig sh_cfg = world_clip_planes ? GPU_SHADER_CFG_CLIPPED :
+ GPU_SHADER_CFG_DEFAULT;
+ GPU_batch_program_set_builtin_with_config(batch, GPU_SHADER_3D_UNIFORM_SELECT_ID, sh_cfg);
+ GPU_batch_uniform_1ui(batch, "id", 0);
+ if (world_clip_planes != NULL) {
+ draw_world_clip_planes_from_rv3d(batch, world_clip_planes);
+ }
+ GPU_batch_draw(batch);
+ }
+}
+
+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;
+ GPU_batch_program_set_builtin_with_config(batch, GPU_SHADER_3D_FLAT_SELECT_ID, sh_cfg);
+ GPU_batch_uniform_1ui(batch, "offset", offset);
+ if (world_clip_planes != NULL) {
+ draw_world_clip_planes_from_rv3d(batch, world_clip_planes);
+ }
+ GPU_batch_draw(batch);
+}
+
+void DRW_draw_select_id_object(Scene *scene,
+ RegionView3D *rv3d,
+ Object *ob,
+ short select_mode,
+ bool draw_facedot,
+ uint initial_offset,
+ uint *r_vert_offset,
+ uint *r_edge_offset,
+ uint *r_face_offset)
+{
+ ToolSettings *ts = scene->toolsettings;
+ if (select_mode == -1) {
+ select_mode = ts->selectmode;
+ }
+
+ GPU_matrix_mul(ob->obmat);
+
+ const float(*world_clip_planes)[4] = NULL;
+ if (rv3d->rflag & RV3D_CLIPPING) {
+ ED_view3d_clipping_local(rv3d, ob->obmat);
+ world_clip_planes = rv3d->clip_local;
+ }
+
+ BLI_assert(initial_offset > 0);
+
+ switch (ob->type) {
+ case OB_MESH:
+ if (ob->mode & OB_MODE_EDIT) {
+ Mesh *me = ob->data;
+ BMEditMesh *em = me->edit_mesh;
+ const bool use_faceselect = (select_mode & SCE_SELECT_FACE) != 0;
+
+ DRW_mesh_batch_cache_validate(me);
+
+ BM_mesh_elem_table_ensure(em->bm, BM_VERT | BM_EDGE | BM_FACE);
+
+ GPUBatch *geom_faces, *geom_edges, *geom_verts, *geom_facedots;
+ geom_faces = DRW_mesh_batch_cache_get_triangles_with_select_id(me);
+ if (select_mode & SCE_SELECT_EDGE) {
+ geom_edges = DRW_mesh_batch_cache_get_edges_with_select_id(me);
+ }
+ if (select_mode & SCE_SELECT_VERTEX) {
+ geom_verts = DRW_mesh_batch_cache_get_verts_with_select_id(me);
+ }
+ if (use_faceselect && draw_facedot) {
+ geom_facedots = DRW_mesh_batch_cache_get_facedots_with_select_id(me);
+ }
+ DRW_mesh_batch_cache_create_requested(ob, me, NULL, false, true);
+
+ draw_mesh_face(geom_faces, initial_offset, use_faceselect, world_clip_planes);
+
+ if (use_faceselect && draw_facedot) {
+ draw_mesh_face_dot(geom_facedots, initial_offset, world_clip_planes);
+ }
+
+ if (select_mode & SCE_SELECT_FACE) {
+ *r_face_offset = initial_offset + em->bm->totface;
+ }
+ else {
+ *r_face_offset = initial_offset;
+ }
+
+ ED_view3d_polygon_offset(rv3d, 1.0);
+
+ /* Unlike faces, only draw edges if edge select mode. */
+ if (select_mode & SCE_SELECT_EDGE) {
+ draw_mesh_edges(geom_edges, *r_face_offset, world_clip_planes);
+ *r_edge_offset = *r_face_offset + em->bm->totedge;
+ }
+ else {
+ /* Note that `r_vert_offset` is calculated from `r_edge_offset`.
+ * Otherwise the first vertex is never selected, see: T53512. */
+ *r_edge_offset = *r_face_offset;
+ }
+
+ ED_view3d_polygon_offset(rv3d, 1.1);
+
+ /* Unlike faces, only verts if vert select mode. */
+ if (select_mode & SCE_SELECT_VERTEX) {
+ draw_mesh_verts(geom_verts, *r_edge_offset, world_clip_planes);
+ *r_vert_offset = *r_edge_offset + em->bm->totvert;
+ }
+ else {
+ *r_vert_offset = *r_edge_offset;
+ }
+
+ ED_view3d_polygon_offset(rv3d, 0.0);
+ }
+ else {
+ Mesh *me_orig = DEG_get_original_object(ob)->data;
+ Mesh *me_eval = ob->data;
+
+ DRW_mesh_batch_cache_validate(me_eval);
+ GPUBatch *geom_faces = DRW_mesh_batch_cache_get_triangles_with_select_id(me_eval);
+ if ((me_orig->editflag & ME_EDIT_PAINT_VERT_SEL) &&
+ /* Currently vertex select supports weight paint and vertex paint. */
+ ((ob->mode & OB_MODE_WEIGHT_PAINT) || (ob->mode & OB_MODE_VERTEX_PAINT))) {
+
+ GPUBatch *geom_verts = DRW_mesh_batch_cache_get_verts_with_select_id(me_eval);
+ DRW_mesh_batch_cache_create_requested(ob, me_eval, NULL, false, true);
+
+ /* Only draw faces to mask out verts, we don't want their selection ID's. */
+ 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 {
+ const bool use_hide = (me_orig->editflag & ME_EDIT_PAINT_FACE_SEL);
+ DRW_mesh_batch_cache_create_requested(ob, me_eval, NULL, false, use_hide);
+
+ draw_mesh_face(geom_faces, initial_offset, true, world_clip_planes);
+
+ *r_face_offset = initial_offset + me_eval->totpoly;
+ *r_edge_offset = *r_vert_offset = *r_face_offset;
+ }
+ }
+ break;
+ case OB_CURVE:
+ case OB_SURF:
+ break;
+ }
+
+ GPU_matrix_set(rv3d->viewmat);
+}
+
/* Set an opengl context to be used with shaders that draw on U32 colors. */
void DRW_framebuffer_select_id_setup(ARegion *ar, const bool clear)
{
@@ -2583,7 +2816,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(
@@ -2654,7 +2887,8 @@ void DRW_state_dfdy_factors_get(float dfdyfac[2])
*/
bool DRW_state_is_fbo(void)
{
- return ((DST.default_framebuffer != NULL) || DST.options.is_image_render);
+ return ((DST.default_framebuffer != NULL) || DST.options.is_image_render) &&
+ !DRW_state_is_depth() && !DRW_state_is_select();
}
/**
@@ -2841,7 +3075,6 @@ void DRW_engines_free(void)
DRW_UBO_FREE_SAFE(G_draw.view_ubo);
DRW_TEXTURE_FREE_SAFE(G_draw.ramp);
DRW_TEXTURE_FREE_SAFE(G_draw.weight_ramp);
- MEM_SAFE_FREE(g_pos_format);
MEM_SAFE_FREE(DST.uniform_names.buffer);
diff --git a/source/blender/draw/intern/draw_manager.h b/source/blender/draw/intern/draw_manager.h
index a70438a2d37..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,102 +92,56 @@
/* 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 */
enum {
DRW_CALL_MODELINVERSE = (1 << 0),
- DRW_CALL_MODELVIEW = (1 << 1),
- DRW_CALL_MODELVIEWINVERSE = (1 << 2),
- DRW_CALL_MODELVIEWPROJECTION = (1 << 3),
- DRW_CALL_NORMALVIEW = (1 << 4),
- DRW_CALL_NORMALVIEWINVERSE = (1 << 5),
- DRW_CALL_NORMALWORLD = (1 << 6),
- DRW_CALL_ORCOTEXFAC = (1 << 7),
- DRW_CALL_EYEVEC = (1 << 8),
- DRW_CALL_OBJECTINFO = (1 << 9),
+ DRW_CALL_MODELVIEWPROJECTION = (1 << 1),
+ DRW_CALL_ORCOTEXFAC = (1 << 2),
+ 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. */
- uint16_t matflag; /* Which matrices to compute. */
- /* Culling: Using Bounding Sphere for now for faster culling.
- * Not ideal for planes. */
- BoundSphere bsphere;
+ uchar matflag; /* Which matrices to compute. */
+ short ob_index;
/* Matrices */
float model[4][4];
float modelinverse[4][4];
- float modelview[4][4];
- float modelviewinverse[4][4];
- float modelviewprojection[4][4];
- float normalview[3][3];
- float normalviewinverse[3][3];
- float normalworld[3][3]; /* Not view dependent */
- float orcotexfac[2][3]; /* Not view dependent */
- float objectinfo[2];
- float eyevec[3];
+ float orcotexfac[2][3];
+ float ob_random;
} DRWCallState;
-typedef enum {
- /** A single batch. */
- DRW_CALL_SINGLE,
- /** Like single but only draw a range of vertices/indices. */
- DRW_CALL_RANGE,
- /** Draw instances without any instancing attributes. */
- DRW_CALL_INSTANCES,
- /** Uses a callback to draw with any number of batches. */
- DRW_CALL_GENERATE,
- /** Generate a drawcall without any #GPUBatch. */
- DRW_CALL_PROCEDURAL,
-} DRWCallType;
-
typedef struct DRWCall {
struct DRWCall *next;
DRWCallState *state;
- union {
- struct { /* type == DRW_CALL_SINGLE */
- GPUBatch *geometry;
- short ma_index;
- } single;
- struct { /* type == DRW_CALL_RANGE */
- GPUBatch *geometry;
- uint start, count;
- } range;
- struct { /* type == DRW_CALL_INSTANCES */
- GPUBatch *geometry;
- /* Count can be adjusted between redraw. If needed, we can add fixed count. */
- uint *count;
- } instances;
- struct { /* type == DRW_CALL_GENERATE */
- DRWCallGenerateFn *geometry_fn;
- void *user_data;
- } generate;
- struct { /* type == DRW_CALL_PROCEDURAL */
- uint vert_count;
- GPUPrimType prim_type;
- } procedural;
- };
+ GPUBatch *batch;
+ uint vert_first;
+ uint vert_count;
+ uint inst_count;
- DRWCallType type;
#ifdef USE_GPU_SELECT
+ /* TODO(fclem) remove once we have a dedicated selection engine. */
int select_id;
+ GPUVertBuf *inst_selectid;
#endif
} DRWCall;
/* Used by DRWUniform.type */
typedef enum {
- DRW_UNIFORM_BOOL,
- DRW_UNIFORM_BOOL_COPY,
- DRW_UNIFORM_SHORT_TO_INT,
- DRW_UNIFORM_SHORT_TO_FLOAT,
DRW_UNIFORM_INT,
DRW_UNIFORM_INT_COPY,
DRW_UNIFORM_FLOAT,
@@ -205,8 +159,8 @@ struct DRWUniform {
/* For reference or array/vector types. */
const void *pvalue;
/* Single values. */
- float fvalue;
- int ivalue;
+ float fvalue[2];
+ int ivalue[2];
};
int name_ofs; /* name offset in name buffer. */
int location;
@@ -215,43 +169,18 @@ struct DRWUniform {
char arraysize; /* cannot be more than 16 too */
};
-typedef enum {
- DRW_SHG_NORMAL,
- DRW_SHG_POINT_BATCH,
- DRW_SHG_LINE_BATCH,
- DRW_SHG_TRIANGLE_BATCH,
- DRW_SHG_INSTANCE,
- DRW_SHG_INSTANCE_EXTERNAL,
- DRW_SHG_FEEDBACK_TRANSFORM,
-} DRWShadingGroupType;
-
struct DRWShadingGroup {
DRWShadingGroup *next;
GPUShader *shader; /* Shader to bind */
DRWUniform *uniforms; /* Uniforms pointers */
- /* Watch this! Can be nasty for debugging. */
- union {
- struct { /* DRW_SHG_NORMAL */
- DRWCall *first, *last; /* Linked list of DRWCall or DRWCallDynamic depending of type */
- } calls;
- struct { /* DRW_SHG_FEEDBACK_TRANSFORM */
- DRWCall *first, *last; /* Linked list of DRWCall or DRWCallDynamic depending of type */
- struct GPUVertBuf *tfeedback_target; /* Transform Feedback target. */
- };
- struct { /* DRW_SHG_***_BATCH */
- struct GPUBatch *batch_geom; /* Result of call batching */
- struct GPUVertBuf *batch_vbo;
- uint primitive_count;
- };
- struct { /* DRW_SHG_INSTANCE[_EXTERNAL] */
- struct GPUBatch *instance_geom;
- struct GPUVertBuf *instance_vbo;
- uint instance_count;
- float instance_orcofac[2][3]; /* TODO find a better place. */
- };
- };
+ struct {
+ DRWCall *first, *last; /* Linked list of DRWCall */
+ } calls;
+
+ /** TODO Maybe remove from here */
+ struct GPUVertBuf *tfeedback_target;
/** State changes for this batch only (or'd with the pass's state) */
DRWState state_extra;
@@ -259,31 +188,17 @@ struct DRWShadingGroup {
DRWState state_extra_disable;
/** Stencil mask to use for stencil test / write operations */
uint stencil_mask;
- DRWShadingGroupType type;
/* Builtin matrices locations */
int model;
int modelinverse;
- int modelview;
- int modelviewinverse;
int modelviewprojection;
- int normalview;
- int normalviewinverse;
- int normalworld;
int orcotexfac;
- int eye;
int callid;
int objectinfo;
- uint16_t matflag; /* Matrices needed, same as DRWCall.flag */
+ uchar matflag; /* Matrices needed, same as DRWCall.flag */
DRWPass *pass_parent; /* backlink to pass we're in */
-#ifndef NDEBUG
- char attrs_count;
-#endif
-#ifdef USE_GPU_SELECT
- GPUVertBuf *inst_selectid;
- int override_selectid; /* Override for single object instances. */
-#endif
};
#define MAX_PASS_NAME 32
@@ -299,11 +214,49 @@ struct DRWPass {
char name[MAX_PASS_NAME];
};
-typedef struct ViewUboStorage {
- DRWMatrixState matstate;
+/* 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];
- float clipplanes[2][4];
-} ViewUboStorage;
+} 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 ModelUboStorage {
+ float model[4][4];
+ float modelinverse[4][4];
+} ModelUboStorage;
+#endif
/* ------------- DRAW DEBUG ------------ */
@@ -332,12 +285,15 @@ 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;
+ struct GHash *dupli_ghash;
+ void **dupli_datas; /* Array of dupli_data (one for each enabled engine) to handle duplis. */
/* Rendering state */
GPUShader *shader;
+ GPUBatch *batch;
/* Managed by `DRW_state_set`, `DRW_state_reset` */
DRWState state;
@@ -352,8 +308,6 @@ typedef struct DRWManager {
float screenvecs[2][3];
float pixsize;
- GLenum backface, frontface;
-
struct {
uint is_select : 1;
uint is_depth : 1;
@@ -370,24 +324,18 @@ typedef struct DRWManager {
struct DRWTextStore **text_store_p;
ListBase enabled_engines; /* RenderEngineType */
+ void **vedata_array; /* ViewportEngineData */
+ int enabled_engine_count; /* Length of enabled_engines list. */
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;
@@ -443,8 +391,12 @@ void drw_state_set(DRWState state);
void drw_debug_draw(void);
void drw_debug_init(void);
+void drw_batch_cache_validate(Object *ob);
void drw_batch_cache_generate_requested(struct Object *ob);
-extern struct GPUVertFormat *g_pos_format;
+/* Procedural Drawing */
+GPUBatch *drw_cache_procedural_points_get(void);
+GPUBatch *drw_cache_procedural_lines_get(void);
+GPUBatch *drw_cache_procedural_triangles_get(void);
#endif /* __DRAW_MANAGER_H__ */
diff --git a/source/blender/draw/intern/draw_manager_data.c b/source/blender/draw/intern/draw_manager_data.c
index 65ef2fa66fa..70f7d28d551 100644
--- a/source/blender/draw/intern/draw_manager_data.c
+++ b/source/blender/draw/intern/draw_manager_data.c
@@ -37,10 +37,15 @@
#include "BLI_hash.h"
#include "BLI_link_utils.h"
#include "BLI_mempool.h"
+#include "BLI_memblock.h"
-#include "intern/gpu_codegen.h"
+#ifdef DRW_DEBUG_CULLING
+# include "BLI_math_bits.h"
+#endif
-struct GPUVertFormat *g_pos_format = NULL;
+#include "GPU_buffers.h"
+
+#include "intern/gpu_codegen.h"
/* -------------------------------------------------------------------- */
/** \name Uniform Buffer Object (DRW_uniformbuffer)
@@ -74,7 +79,7 @@ static void drw_shgroup_uniform_create_ex(DRWShadingGroup *shgroup,
int length,
int arraysize)
{
- DRWUniform *uni = BLI_mempool_alloc(DST.vmempool->uniforms);
+ DRWUniform *uni = BLI_memblock_alloc(DST.vmempool->uniforms);
uni->location = loc;
uni->type = type;
uni->length = length;
@@ -82,16 +87,15 @@ static void drw_shgroup_uniform_create_ex(DRWShadingGroup *shgroup,
switch (type) {
case DRW_UNIFORM_INT_COPY:
- uni->ivalue = *((int *)value);
- break;
- case DRW_UNIFORM_BOOL_COPY:
- uni->ivalue = (int)*((bool *)value);
+ BLI_assert(length <= 2);
+ memcpy(uni->ivalue, value, sizeof(int) * length);
break;
case DRW_UNIFORM_FLOAT_COPY:
- uni->fvalue = *((float *)value);
+ BLI_assert(length <= 2);
+ memcpy(uni->fvalue, value, sizeof(float) * length);
break;
default:
- uni->pvalue = value;
+ uni->pvalue = (const float *)value;
break;
}
@@ -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);
}
@@ -199,7 +203,7 @@ void DRW_shgroup_uniform_bool(DRWShadingGroup *shgroup,
const int *value,
int arraysize)
{
- drw_shgroup_uniform(shgroup, name, DRW_UNIFORM_BOOL, value, 1, arraysize);
+ drw_shgroup_uniform(shgroup, name, DRW_UNIFORM_INT, value, 1, arraysize);
}
void DRW_shgroup_uniform_float(DRWShadingGroup *shgroup,
@@ -234,22 +238,6 @@ void DRW_shgroup_uniform_vec4(DRWShadingGroup *shgroup,
drw_shgroup_uniform(shgroup, name, DRW_UNIFORM_FLOAT, value, 4, arraysize);
}
-void DRW_shgroup_uniform_short_to_int(DRWShadingGroup *shgroup,
- const char *name,
- const short *value,
- int arraysize)
-{
- drw_shgroup_uniform(shgroup, name, DRW_UNIFORM_SHORT_TO_INT, value, 1, arraysize);
-}
-
-void DRW_shgroup_uniform_short_to_float(DRWShadingGroup *shgroup,
- const char *name,
- const short *value,
- int arraysize)
-{
- drw_shgroup_uniform(shgroup, name, DRW_UNIFORM_SHORT_TO_FLOAT, value, 1, arraysize);
-}
-
void DRW_shgroup_uniform_int(DRWShadingGroup *shgroup,
const char *name,
const int *value,
@@ -300,7 +288,8 @@ void DRW_shgroup_uniform_int_copy(DRWShadingGroup *shgroup, const char *name, co
void DRW_shgroup_uniform_bool_copy(DRWShadingGroup *shgroup, const char *name, const bool value)
{
- drw_shgroup_uniform(shgroup, name, DRW_UNIFORM_BOOL_COPY, &value, 1, 1);
+ int ival = value;
+ drw_shgroup_uniform(shgroup, name, DRW_UNIFORM_INT_COPY, &ival, 1, 1);
}
void DRW_shgroup_uniform_float_copy(DRWShadingGroup *shgroup, const char *name, const float value)
@@ -308,6 +297,11 @@ void DRW_shgroup_uniform_float_copy(DRWShadingGroup *shgroup, const char *name,
drw_shgroup_uniform(shgroup, name, DRW_UNIFORM_FLOAT_COPY, &value, 1, 1);
}
+void DRW_shgroup_uniform_vec2_copy(DRWShadingGroup *shgroup, const char *name, const float *value)
+{
+ drw_shgroup_uniform(shgroup, name, DRW_UNIFORM_FLOAT_COPY, value, 2, 1);
+}
+
/** \} */
/* -------------------------------------------------------------------- */
@@ -361,20 +355,29 @@ static void drw_call_state_update_matflag(DRWCallState *state,
DRWShadingGroup *shgroup,
Object *ob)
{
- uint16_t new_flags = ((state->matflag ^ shgroup->matflag) & shgroup->matflag);
+ uchar new_flags = ((state->matflag ^ shgroup->matflag) & shgroup->matflag);
/* HACK: Here we set the matflags bit to 1 when computing the value
* so that it's not recomputed for other drawcalls.
* This is the opposite of what draw_matrices_model_prepare() does. */
state->matflag |= shgroup->matflag;
+ if (new_flags & DRW_CALL_MODELINVERSE) {
+ if (ob) {
+ copy_m4_m4(state->modelinverse, ob->imat);
+ }
+ else {
+ invert_m4_m4(state->modelinverse, state->model);
+ }
+ }
+
/* Orco factors: We compute this at creation to not have to save the *ob_data */
- if ((new_flags & DRW_CALL_ORCOTEXFAC) != 0) {
+ if (new_flags & DRW_CALL_ORCOTEXFAC) {
drw_call_calc_orco(ob, state->orcotexfac);
}
- if ((new_flags & DRW_CALL_OBJECTINFO) != 0) {
- state->objectinfo[0] = ob ? ob->index : 0;
+ if (new_flags & DRW_CALL_OBJECTINFO) {
+ state->ob_index = ob ? ob->index : 0;
uint random;
if (DST.dupli_source) {
random = DST.dupli_source->random_id;
@@ -382,23 +385,21 @@ static void drw_call_state_update_matflag(DRWCallState *state,
else {
random = BLI_hash_int_2d(BLI_hash_string(ob->id.name + 2), 0);
}
- state->objectinfo[1] = random * (1.0f / (float)0xFFFFFFFF);
+ state->ob_random = random * (1.0f / (float)0xFFFFFFFF);
}
}
static DRWCallState *drw_call_state_create(DRWShadingGroup *shgroup, float (*obmat)[4], Object *ob)
{
- DRWCallState *state = BLI_mempool_alloc(DST.vmempool->states);
+ DRWCallState *state = BLI_memblock_alloc(DST.vmempool->states);
state->flag = 0;
- state->cache_id = 0;
- state->visibility_cb = NULL;
state->matflag = 0;
/* Matrices */
if (obmat != NULL) {
copy_m4_m4(state->model, obmat);
- if (is_negative_m4(state->model)) {
+ if (ob && (ob->transflag & OB_NEG_SCALE)) {
state->flag |= DRW_CALL_NEGSCALE;
}
}
@@ -406,22 +407,27 @@ static DRWCallState *drw_call_state_create(DRWShadingGroup *shgroup, float (*obm
unit_m4(state->model);
}
+ 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;
}
- drw_call_state_update_matflag(state, shgroup, ob);
-
return state;
}
@@ -438,314 +444,408 @@ static DRWCallState *drw_call_state_object(DRWShadingGroup *shgroup, float (*obm
return DST.ob_state;
}
-void DRW_shgroup_call_add(DRWShadingGroup *shgroup, GPUBatch *geom, float (*obmat)[4])
+void DRW_shgroup_call(DRWShadingGroup *shgroup, GPUBatch *geom, float (*obmat)[4])
{
BLI_assert(geom != NULL);
- BLI_assert(ELEM(shgroup->type, DRW_SHG_NORMAL, DRW_SHG_FEEDBACK_TRANSFORM));
- DRWCall *call = BLI_mempool_alloc(DST.vmempool->calls);
+ DRWCall *call = BLI_memblock_alloc(DST.vmempool->calls);
+ BLI_LINKS_APPEND(&shgroup->calls, call);
+
call->state = drw_call_state_create(shgroup, obmat, NULL);
- call->type = DRW_CALL_SINGLE;
- call->single.geometry = geom;
+ call->batch = geom;
+ call->vert_first = 0;
+ call->vert_count = 0; /* Auto from batch. */
+ call->inst_count = 0;
#ifdef USE_GPU_SELECT
call->select_id = DST.select_id;
+ call->inst_selectid = NULL;
#endif
-
- BLI_LINKS_APPEND(&shgroup->calls, call);
}
-void DRW_shgroup_call_range_add(
+void DRW_shgroup_call_range(
DRWShadingGroup *shgroup, GPUBatch *geom, float (*obmat)[4], uint v_sta, uint v_count)
{
BLI_assert(geom != NULL);
- BLI_assert(ELEM(shgroup->type, DRW_SHG_NORMAL, DRW_SHG_FEEDBACK_TRANSFORM));
BLI_assert(v_count);
- DRWCall *call = BLI_mempool_alloc(DST.vmempool->calls);
+ DRWCall *call = BLI_memblock_alloc(DST.vmempool->calls);
+ BLI_LINKS_APPEND(&shgroup->calls, call);
+
call->state = drw_call_state_create(shgroup, obmat, NULL);
- call->type = DRW_CALL_RANGE;
- call->range.geometry = geom;
- call->range.start = v_sta;
- call->range.count = v_count;
+ call->batch = geom;
+ call->vert_first = v_sta;
+ call->vert_count = v_count;
+ call->inst_count = 0;
#ifdef USE_GPU_SELECT
call->select_id = DST.select_id;
+ call->inst_selectid = NULL;
#endif
-
- BLI_LINKS_APPEND(&shgroup->calls, call);
}
static void drw_shgroup_call_procedural_add_ex(DRWShadingGroup *shgroup,
- GPUPrimType prim_type,
+ GPUBatch *geom,
uint vert_count,
- float (*obmat)[4],
- Object *ob)
+ float (*obmat)[4])
{
- BLI_assert(ELEM(shgroup->type, DRW_SHG_NORMAL, DRW_SHG_FEEDBACK_TRANSFORM));
- DRWCall *call = BLI_mempool_alloc(DST.vmempool->calls);
- if (ob) {
- call->state = drw_call_state_object(shgroup, ob->obmat, ob);
- }
- else {
- call->state = drw_call_state_create(shgroup, obmat, NULL);
- }
- call->type = DRW_CALL_PROCEDURAL;
- call->procedural.prim_type = prim_type;
- call->procedural.vert_count = vert_count;
+ DRWCall *call = BLI_memblock_alloc(DST.vmempool->calls);
+ BLI_LINKS_APPEND(&shgroup->calls, call);
+
+ call->state = drw_call_state_object(shgroup, obmat, NULL);
+ call->batch = geom;
+ call->vert_first = 0;
+ call->vert_count = vert_count;
+ call->inst_count = 0;
#ifdef USE_GPU_SELECT
call->select_id = DST.select_id;
+ call->inst_selectid = NULL;
#endif
-
- BLI_LINKS_APPEND(&shgroup->calls, call);
-}
-
-void DRW_shgroup_call_procedural_points_add(DRWShadingGroup *shgroup,
- uint point_len,
- float (*obmat)[4])
-{
- drw_shgroup_call_procedural_add_ex(shgroup, GPU_PRIM_POINTS, point_len, obmat, NULL);
}
-void DRW_shgroup_call_procedural_lines_add(DRWShadingGroup *shgroup,
- uint line_count,
- float (*obmat)[4])
+void DRW_shgroup_call_procedural_points(DRWShadingGroup *shgroup,
+ uint point_len,
+ float (*obmat)[4])
{
- drw_shgroup_call_procedural_add_ex(shgroup, GPU_PRIM_LINES, line_count * 2, obmat, NULL);
+ struct GPUBatch *geom = drw_cache_procedural_points_get();
+ drw_shgroup_call_procedural_add_ex(shgroup, geom, point_len, obmat);
}
-void DRW_shgroup_call_procedural_triangles_add(DRWShadingGroup *shgroup,
- uint tria_count,
- float (*obmat)[4])
+void DRW_shgroup_call_procedural_lines(DRWShadingGroup *shgroup,
+ uint line_count,
+ float (*obmat)[4])
{
- drw_shgroup_call_procedural_add_ex(shgroup, GPU_PRIM_TRIS, tria_count * 3, obmat, NULL);
+ struct GPUBatch *geom = drw_cache_procedural_lines_get();
+ drw_shgroup_call_procedural_add_ex(shgroup, geom, line_count * 2, obmat);
}
-/* TODO (fclem): this is a sign that the api is starting to be limiting.
- * Maybe add special function that general purpose for special cases. */
-void DRW_shgroup_call_object_procedural_triangles_culled_add(DRWShadingGroup *shgroup,
- uint tria_count,
- Object *ob)
+void DRW_shgroup_call_procedural_triangles(DRWShadingGroup *shgroup,
+ uint tria_count,
+ float (*obmat)[4])
{
- drw_shgroup_call_procedural_add_ex(shgroup, GPU_PRIM_TRIS, tria_count * 3, NULL, ob);
+ struct GPUBatch *geom = drw_cache_procedural_triangles_get();
+ drw_shgroup_call_procedural_add_ex(shgroup, geom, tria_count * 3, obmat);
}
/* These calls can be culled and are optimized for redraw */
-void DRW_shgroup_call_object_add_ex(
- DRWShadingGroup *shgroup, GPUBatch *geom, Object *ob, Material *ma, bool bypass_culling)
+void DRW_shgroup_call_object_ex(DRWShadingGroup *shgroup,
+ GPUBatch *geom,
+ Object *ob,
+ bool bypass_culling)
{
BLI_assert(geom != NULL);
- BLI_assert(ELEM(shgroup->type, DRW_SHG_NORMAL, DRW_SHG_FEEDBACK_TRANSFORM));
- DRWCall *call = BLI_mempool_alloc(DST.vmempool->calls);
+ DRWCall *call = BLI_memblock_alloc(DST.vmempool->calls);
+ BLI_LINKS_APPEND(&shgroup->calls, call);
+
call->state = drw_call_state_object(shgroup, ob->obmat, ob);
- call->type = DRW_CALL_SINGLE;
- call->single.geometry = geom;
- call->single.ma_index = ma ? ma->index : 0;
+ call->batch = geom;
+ call->vert_first = 0;
+ call->vert_count = 0; /* Auto from batch. */
+ call->inst_count = 0;
#ifdef USE_GPU_SELECT
call->select_id = DST.select_id;
+ call->inst_selectid = NULL;
#endif
-
- /* NOTE this will disable culling for the whole object. */
- call->state->flag |= (bypass_culling) ? DRW_CALL_BYPASS_CULLING : 0;
-
- BLI_LINKS_APPEND(&shgroup->calls, call);
+ if (bypass_culling) {
+ /* NOTE this will disable culling for the whole object. */
+ call->state->culling->bsphere.radius = -1.0f;
+ }
}
-void DRW_shgroup_call_object_add_with_callback(DRWShadingGroup *shgroup,
- GPUBatch *geom,
- Object *ob,
- Material *ma,
- DRWCallVisibilityFn *callback,
- void *user_data)
+void DRW_shgroup_call_object_with_callback(DRWShadingGroup *shgroup,
+ GPUBatch *geom,
+ Object *ob,
+ void *user_data)
{
BLI_assert(geom != NULL);
- BLI_assert(ELEM(shgroup->type, DRW_SHG_NORMAL, DRW_SHG_FEEDBACK_TRANSFORM));
- DRWCall *call = BLI_mempool_alloc(DST.vmempool->calls);
+ DRWCall *call = BLI_memblock_alloc(DST.vmempool->calls);
+ 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->type = DRW_CALL_SINGLE;
- call->single.geometry = geom;
- call->single.ma_index = ma ? ma->index : 0;
+ call->state->culling->user_data = user_data;
+ call->batch = geom;
+ call->vert_first = 0;
+ call->vert_count = 0; /* Auto from batch. */
+ call->inst_count = 0;
#ifdef USE_GPU_SELECT
call->select_id = DST.select_id;
+ call->inst_selectid = NULL;
#endif
-
- BLI_LINKS_APPEND(&shgroup->calls, call);
}
-void DRW_shgroup_call_instances_add(DRWShadingGroup *shgroup,
- GPUBatch *geom,
- float (*obmat)[4],
- uint *count)
+void DRW_shgroup_call_instances(DRWShadingGroup *shgroup,
+ GPUBatch *geom,
+ float (*obmat)[4],
+ uint count)
{
BLI_assert(geom != NULL);
- BLI_assert(ELEM(shgroup->type, DRW_SHG_NORMAL, DRW_SHG_FEEDBACK_TRANSFORM));
- DRWCall *call = BLI_mempool_alloc(DST.vmempool->calls);
+ DRWCall *call = BLI_memblock_alloc(DST.vmempool->calls);
+ BLI_LINKS_APPEND(&shgroup->calls, call);
+
call->state = drw_call_state_create(shgroup, obmat, NULL);
- call->type = DRW_CALL_INSTANCES;
- call->instances.geometry = geom;
- call->instances.count = count;
+ call->batch = geom;
+ call->vert_first = 0;
+ call->vert_count = 0; /* Auto from batch. */
+ call->inst_count = count;
#ifdef USE_GPU_SELECT
call->select_id = DST.select_id;
+ call->inst_selectid = NULL;
#endif
-
- BLI_LINKS_APPEND(&shgroup->calls, call);
}
-/* These calls can be culled and are optimized for redraw */
-void DRW_shgroup_call_object_instances_add(DRWShadingGroup *shgroup,
- GPUBatch *geom,
- Object *ob,
- uint *count)
+void DRW_shgroup_call_instances_with_attribs(DRWShadingGroup *shgroup,
+ struct GPUBatch *geom,
+ float (*obmat)[4],
+ struct GPUBatch *inst_attributes)
{
BLI_assert(geom != NULL);
- BLI_assert(ELEM(shgroup->type, DRW_SHG_NORMAL, DRW_SHG_FEEDBACK_TRANSFORM));
+ BLI_assert(inst_attributes->verts[0] != NULL);
- DRWCall *call = BLI_mempool_alloc(DST.vmempool->calls);
- call->state = drw_call_state_object(shgroup, ob->obmat, ob);
- call->type = DRW_CALL_INSTANCES;
- call->instances.geometry = geom;
- call->instances.count = count;
-#ifdef USE_GPU_SELECT
- call->select_id = DST.select_id;
-#endif
+ GPUVertBuf *buf_inst = inst_attributes->verts[0];
+ DRWCall *call = BLI_memblock_alloc(DST.vmempool->calls);
BLI_LINKS_APPEND(&shgroup->calls, call);
-}
-
-void DRW_shgroup_call_generate_add(DRWShadingGroup *shgroup,
- DRWCallGenerateFn *geometry_fn,
- void *user_data,
- float (*obmat)[4])
-{
- BLI_assert(geometry_fn != NULL);
- BLI_assert(ELEM(shgroup->type, DRW_SHG_NORMAL, DRW_SHG_FEEDBACK_TRANSFORM));
- DRWCall *call = BLI_mempool_alloc(DST.vmempool->calls);
call->state = drw_call_state_create(shgroup, obmat, NULL);
- call->type = DRW_CALL_GENERATE;
- call->generate.geometry_fn = geometry_fn;
- call->generate.user_data = user_data;
+ call->batch = DRW_temp_batch_instance_request(DST.idatalist, buf_inst, geom);
+ call->vert_first = 0;
+ call->vert_count = 0; /* Auto from batch. */
+ call->inst_count = buf_inst->vertex_len;
#ifdef USE_GPU_SELECT
call->select_id = DST.select_id;
+ call->inst_selectid = NULL;
#endif
-
- BLI_LINKS_APPEND(&shgroup->calls, call);
}
-/* This function tests if the current draw engine draws the vertex colors
- * It is used when drawing sculpts
- *
- * XXX: should we use a callback to a the draw engine to retrieve this
- * setting, this makes the draw manager more clean? */
-static bool DRW_draw_vertex_color_active(const DRWContextState *draw_ctx)
-{
- View3D *v3d = draw_ctx->v3d;
- return v3d->shading.type == OB_SOLID && v3d->shading.color_type == V3D_SHADING_VERTEX_COLOR;
-}
+// #define SCULPT_DEBUG_BUFFERS
-static void sculpt_draw_cb(DRWShadingGroup *shgroup,
- void (*draw_fn)(DRWShadingGroup *shgroup, GPUBatch *geom),
- void *user_data)
-{
- Object *ob = user_data;
+typedef struct DRWSculptCallbackData {
+ Object *ob;
+ DRWShadingGroup **shading_groups;
+ bool use_wire;
+ bool use_mats;
+ bool use_mask;
+ bool fast_mode; /* Set by draw manager. Do not init. */
+#ifdef SCULPT_DEBUG_BUFFERS
+ int node_nr;
+#endif
+} DRWSculptCallbackData;
+
+#ifdef SCULPT_DEBUG_BUFFERS
+# define SCULPT_DEBUG_COLOR(id) (sculpt_debug_colors[id % 9])
+static float sculpt_debug_colors[9][4] = {
+ {1.0f, 0.2f, 0.2f, 1.0f},
+ {0.2f, 1.0f, 0.2f, 1.0f},
+ {0.2f, 0.2f, 1.0f, 1.0f},
+ {1.0f, 1.0f, 0.2f, 1.0f},
+ {0.2f, 1.0f, 1.0f, 1.0f},
+ {1.0f, 0.2f, 1.0f, 1.0f},
+ {1.0f, 0.7f, 0.2f, 1.0f},
+ {0.2f, 1.0f, 0.7f, 1.0f},
+ {0.7f, 0.2f, 1.0f, 1.0f},
+};
+#endif
- /* XXX should be ensured before but sometime it's not... go figure (see T57040). */
- PBVH *pbvh = BKE_sculpt_object_pbvh_ensure(DST.draw_ctx.depsgraph, ob);
+static void sculpt_draw_cb(DRWSculptCallbackData *scd, GPU_PBVH_Buffers *buffers)
+{
+ GPUBatch *geom = GPU_pbvh_buffers_batch_get(buffers, scd->fast_mode, scd->use_wire);
+ short index = 0;
- const DRWContextState *drwctx = DRW_context_state_get();
- int fast_mode = 0;
+ /* Meh... use_mask is a bit misleading here. */
+ if (scd->use_mask && !GPU_pbvh_buffers_has_mask(buffers)) {
+ return;
+ }
- if (drwctx->evil_C != NULL) {
- Paint *p = BKE_paint_get_active_from_context(drwctx->evil_C);
- if (p && (p->flags & PAINT_FAST_NAVIGATE)) {
- fast_mode = drwctx->rv3d->rflag & RV3D_NAVIGATING;
- }
+ if (scd->use_mats) {
+ index = GPU_pbvh_buffers_material_index_get(buffers);
}
- if (pbvh) {
- const bool show_vcol = DRW_draw_vertex_color_active(drwctx);
- BKE_pbvh_draw_cb(pbvh,
- NULL,
- NULL,
- fast_mode,
- false,
- false,
- show_vcol,
- (void (*)(void *, GPUBatch *))draw_fn,
- shgroup);
+ DRWShadingGroup *shgrp = scd->shading_groups[index];
+ if (geom != NULL && shgrp != NULL) {
+#ifdef SCULPT_DEBUG_BUFFERS
+ /* Color each buffers in different colors. Only work in solid/Xray mode. */
+ shgrp = DRW_shgroup_create_sub(shgrp);
+ DRW_shgroup_uniform_vec3(shgrp, "materialDiffuseColor", SCULPT_DEBUG_COLOR(scd->node_nr++), 1);
+#endif
+ /* DRW_shgroup_call_object_ex reuses matrices calculations for all the drawcalls of this
+ * object. */
+ DRW_shgroup_call_object_ex(shgrp, geom, scd->ob, true);
}
}
-static void sculpt_draw_wires_cb(DRWShadingGroup *shgroup,
- void (*draw_fn)(DRWShadingGroup *shgroup, GPUBatch *geom),
- void *user_data)
+#ifdef SCULPT_DEBUG_BUFFERS
+static void sculpt_debug_cb(void *user_data,
+ const float bmin[3],
+ const float bmax[3],
+ PBVHNodeFlags flag)
{
- Object *ob = user_data;
+ int *node_nr = (int *)user_data;
+ BoundBox bb;
+ BKE_boundbox_init_from_minmax(&bb, bmin, bmax);
+# if 0 /* Nodes hierarchy. */
+ if (flag & PBVH_Leaf) {
+ DRW_debug_bbox(&bb, (float[4]){0.0f, 1.0f, 0.0f, 1.0f});
+ }
+ else {
+ DRW_debug_bbox(&bb, (float[4]){0.5f, 0.5f, 0.5f, 0.6f});
+ }
+# else /* Color coded leaf bounds. */
+ if (flag & PBVH_Leaf) {
+ DRW_debug_bbox(&bb, SCULPT_DEBUG_COLOR((*node_nr)++));
+ }
+# endif
+}
+#endif
+
+static void drw_sculpt_generate_calls(DRWSculptCallbackData *scd, bool use_vcol)
+{
/* XXX should be ensured before but sometime it's not... go figure (see T57040). */
- PBVH *pbvh = BKE_sculpt_object_pbvh_ensure(DST.draw_ctx.depsgraph, ob);
+ PBVH *pbvh = BKE_sculpt_object_pbvh_ensure(DST.draw_ctx.depsgraph, scd->ob);
+ if (!pbvh) {
+ return;
+ }
- const DRWContextState *drwctx = DRW_context_state_get();
- int fast_mode = 0;
+ float(*planes)[4] = NULL; /* TODO proper culling. */
+ scd->fast_mode = false;
+ const DRWContextState *drwctx = DRW_context_state_get();
if (drwctx->evil_C != NULL) {
Paint *p = BKE_paint_get_active_from_context(drwctx->evil_C);
if (p && (p->flags & PAINT_FAST_NAVIGATE)) {
- fast_mode = drwctx->rv3d->rflag & RV3D_NAVIGATING;
+ scd->fast_mode = (drwctx->rv3d->rflag & RV3D_NAVIGATING) != 0;
}
}
- if (pbvh) {
- BKE_pbvh_draw_cb(pbvh,
- NULL,
- NULL,
- fast_mode,
- true,
- false,
- false,
- (void (*)(void *, GPUBatch *))draw_fn,
- shgroup);
- }
+ BKE_pbvh_draw_cb(
+ pbvh, planes, NULL, use_vcol, (void (*)(void *, GPU_PBVH_Buffers *))sculpt_draw_cb, scd);
+
+#ifdef SCULPT_DEBUG_BUFFERS
+ int node_nr = 0;
+ DRW_debug_modelmat(scd->ob->obmat);
+ BKE_pbvh_draw_debug_cb(
+ pbvh,
+ (void (*)(void *d, const float min[3], const float max[3], PBVHNodeFlags f))sculpt_debug_cb,
+ &node_nr);
+#endif
}
-void DRW_shgroup_call_sculpt_add(DRWShadingGroup *shgroup, Object *ob, float (*obmat)[4])
+void DRW_shgroup_call_sculpt(
+ DRWShadingGroup *shgroup, Object *ob, bool use_wire, bool use_mask, bool use_vcol)
{
- DRW_shgroup_call_generate_add(shgroup, sculpt_draw_cb, ob, obmat);
+ DRWSculptCallbackData scd = {
+ .ob = ob,
+ .shading_groups = &shgroup,
+ .use_wire = use_wire,
+ .use_mats = false,
+ .use_mask = use_mask,
+ };
+ drw_sculpt_generate_calls(&scd, use_vcol);
}
-void DRW_shgroup_call_sculpt_wires_add(DRWShadingGroup *shgroup, Object *ob, float (*obmat)[4])
+void DRW_shgroup_call_sculpt_with_materials(DRWShadingGroup **shgroups, Object *ob, bool use_vcol)
{
- DRW_shgroup_call_generate_add(shgroup, sculpt_draw_wires_cb, ob, obmat);
+ DRWSculptCallbackData scd = {
+ .ob = ob,
+ .shading_groups = shgroups,
+ .use_wire = false,
+ .use_mats = true,
+ .use_mask = false,
+ };
+ drw_sculpt_generate_calls(&scd, use_vcol);
}
-void DRW_shgroup_call_dynamic_add_array(DRWShadingGroup *shgroup,
- const void *attr[],
- uint attr_len)
+static GPUVertFormat inst_select_format = {0};
+
+DRWCallBuffer *DRW_shgroup_call_buffer(DRWShadingGroup *shgroup,
+ struct GPUVertFormat *format,
+ GPUPrimType prim_type)
{
+ BLI_assert(ELEM(prim_type, GPU_PRIM_POINTS, GPU_PRIM_LINES, GPU_PRIM_TRI_FAN));
+ BLI_assert(format != NULL);
+
+ DRWCall *call = BLI_memblock_alloc(DST.vmempool->calls);
+ BLI_LINKS_APPEND(&shgroup->calls, call);
+
+ call->state = drw_call_state_create(shgroup, NULL, NULL);
+ GPUVertBuf *buf = DRW_temp_buffer_request(DST.idatalist, format, &call->vert_count);
+ call->batch = DRW_temp_batch_request(DST.idatalist, buf, prim_type);
+ call->vert_first = 0;
+ call->vert_count = 0;
+ call->inst_count = 0;
+
#ifdef USE_GPU_SELECT
if (G.f & G_FLAG_PICKSEL) {
- if (shgroup->instance_count == shgroup->inst_selectid->vertex_len) {
- GPU_vertbuf_data_resize(shgroup->inst_selectid, shgroup->instance_count + 32);
+ /* Not actually used for rendering but alloced in one chunk. */
+ if (inst_select_format.attr_len == 0) {
+ GPU_vertformat_attr_add(&inst_select_format, "selectId", GPU_COMP_I32, 1, GPU_FETCH_INT);
}
- GPU_vertbuf_attr_set(shgroup->inst_selectid, 0, shgroup->instance_count, &DST.select_id);
+ call->inst_selectid = DRW_temp_buffer_request(
+ DST.idatalist, &inst_select_format, &call->vert_count);
}
#endif
+ return (DRWCallBuffer *)call;
+}
+
+DRWCallBuffer *DRW_shgroup_call_buffer_instance(DRWShadingGroup *shgroup,
+ struct GPUVertFormat *format,
+ GPUBatch *geom)
+{
+ BLI_assert(geom != NULL);
+ BLI_assert(format != NULL);
+
+ DRWCall *call = BLI_memblock_alloc(DST.vmempool->calls);
+ BLI_LINKS_APPEND(&shgroup->calls, call);
- BLI_assert(attr_len == shgroup->attrs_count);
+ call->state = drw_call_state_create(shgroup, NULL, NULL);
+ GPUVertBuf *buf = DRW_temp_buffer_request(DST.idatalist, format, &call->inst_count);
+ call->batch = DRW_temp_batch_instance_request(DST.idatalist, buf, geom);
+ call->vert_first = 0;
+ call->vert_count = 0; /* Auto from batch. */
+ call->inst_count = 0;
+
+#ifdef USE_GPU_SELECT
+ if (G.f & G_FLAG_PICKSEL) {
+ /* Not actually used for rendering but alloced in one chunk. */
+ if (inst_select_format.attr_len == 0) {
+ GPU_vertformat_attr_add(&inst_select_format, "selectId", GPU_COMP_I32, 1, GPU_FETCH_INT);
+ }
+ call->inst_selectid = DRW_temp_buffer_request(
+ DST.idatalist, &inst_select_format, &call->inst_count);
+ }
+#endif
+ return (DRWCallBuffer *)call;
+}
+
+void DRW_buffer_add_entry_array(DRWCallBuffer *callbuf, const void *attr[], uint attr_len)
+{
+ DRWCall *call = (DRWCall *)callbuf;
+ const bool is_instance = call->batch->inst != NULL;
+ GPUVertBuf *buf = is_instance ? call->batch->inst : call->batch->verts[0];
+ uint count = is_instance ? call->inst_count++ : call->vert_count++;
+ const bool resize = (count == buf->vertex_alloc);
+
+ BLI_assert(attr_len == buf->format.attr_len);
UNUSED_VARS_NDEBUG(attr_len);
+ if (UNLIKELY(resize)) {
+ GPU_vertbuf_data_resize(buf, count + DRW_BUFFER_VERTS_CHUNK);
+ }
+
for (int i = 0; i < attr_len; ++i) {
- if (shgroup->instance_count == shgroup->instance_vbo->vertex_len) {
- GPU_vertbuf_data_resize(shgroup->instance_vbo, shgroup->instance_count + 32);
- }
- GPU_vertbuf_attr_set(shgroup->instance_vbo, i, shgroup->instance_count, attr[i]);
+ GPU_vertbuf_attr_set(buf, i, count, attr[i]);
}
- shgroup->instance_count += 1;
+#ifdef USE_GPU_SELECT
+ if (G.f & G_FLAG_PICKSEL) {
+ if (UNLIKELY(resize)) {
+ GPU_vertbuf_data_resize(call->inst_selectid, count + DRW_BUFFER_VERTS_CHUNK);
+ }
+ GPU_vertbuf_attr_set(call->inst_selectid, 0, count, &DST.select_id);
+ }
+#endif
}
/** \} */
@@ -756,17 +856,7 @@ void DRW_shgroup_call_dynamic_add_array(DRWShadingGroup *shgroup,
static void drw_shgroup_init(DRWShadingGroup *shgroup, GPUShader *shader)
{
- shgroup->instance_geom = NULL;
- shgroup->instance_vbo = NULL;
- shgroup->instance_count = 0;
shgroup->uniforms = NULL;
-#ifdef USE_GPU_SELECT
- shgroup->inst_selectid = NULL;
- shgroup->override_selectid = -1;
-#endif
-#ifndef NDEBUG
- shgroup->attrs_count = 0;
-#endif
int view_ubo_location = GPU_shader_get_uniform_block(shader, "viewBlock");
@@ -776,178 +866,56 @@ 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);
}
+ /* Not supported. */
+ BLI_assert(GPU_shader_get_builtin_uniform(shader, GPU_UNIFORM_MODELVIEW_INV) == -1);
+ BLI_assert(GPU_shader_get_builtin_uniform(shader, GPU_UNIFORM_MODELVIEW) == -1);
+ BLI_assert(GPU_shader_get_builtin_uniform(shader, GPU_UNIFORM_NORMAL) == -1);
+
shgroup->model = GPU_shader_get_builtin_uniform(shader, GPU_UNIFORM_MODEL);
shgroup->modelinverse = GPU_shader_get_builtin_uniform(shader, GPU_UNIFORM_MODEL_INV);
- shgroup->modelview = GPU_shader_get_builtin_uniform(shader, GPU_UNIFORM_MODELVIEW);
- shgroup->modelviewinverse = GPU_shader_get_builtin_uniform(shader, GPU_UNIFORM_MODELVIEW_INV);
shgroup->modelviewprojection = GPU_shader_get_builtin_uniform(shader, GPU_UNIFORM_MVP);
- shgroup->normalview = GPU_shader_get_builtin_uniform(shader, GPU_UNIFORM_NORMAL);
- shgroup->normalviewinverse = GPU_shader_get_builtin_uniform(shader, GPU_UNIFORM_NORMAL_INV);
- shgroup->normalworld = GPU_shader_get_builtin_uniform(shader, GPU_UNIFORM_WORLDNORMAL);
shgroup->orcotexfac = GPU_shader_get_builtin_uniform(shader, GPU_UNIFORM_ORCO);
shgroup->objectinfo = GPU_shader_get_builtin_uniform(shader, GPU_UNIFORM_OBJECT_INFO);
- shgroup->eye = GPU_shader_get_builtin_uniform(shader, GPU_UNIFORM_EYE);
shgroup->callid = GPU_shader_get_builtin_uniform(shader, GPU_UNIFORM_CALLID);
shgroup->matflag = 0;
if (shgroup->modelinverse > -1) {
shgroup->matflag |= DRW_CALL_MODELINVERSE;
}
- if (shgroup->modelview > -1) {
- shgroup->matflag |= DRW_CALL_MODELVIEW;
- }
- if (shgroup->modelviewinverse > -1) {
- shgroup->matflag |= DRW_CALL_MODELVIEWINVERSE;
- }
if (shgroup->modelviewprojection > -1) {
shgroup->matflag |= DRW_CALL_MODELVIEWPROJECTION;
}
- if (shgroup->normalview > -1) {
- shgroup->matflag |= DRW_CALL_NORMALVIEW;
- }
- if (shgroup->normalviewinverse > -1) {
- shgroup->matflag |= DRW_CALL_NORMALVIEWINVERSE;
- }
- if (shgroup->normalworld > -1) {
- shgroup->matflag |= DRW_CALL_NORMALWORLD;
- }
if (shgroup->orcotexfac > -1) {
shgroup->matflag |= DRW_CALL_ORCOTEXFAC;
}
if (shgroup->objectinfo > -1) {
shgroup->matflag |= DRW_CALL_OBJECTINFO;
}
- if (shgroup->eye > -1) {
- shgroup->matflag |= DRW_CALL_EYEVEC;
- }
-}
-
-static void drw_shgroup_instance_init(DRWShadingGroup *shgroup,
- GPUShader *shader,
- GPUBatch *batch,
- GPUVertFormat *format)
-{
- BLI_assert(shgroup->type == DRW_SHG_INSTANCE);
- BLI_assert(batch != NULL);
- BLI_assert(format != NULL);
-
- drw_shgroup_init(shgroup, shader);
-
- shgroup->instance_geom = batch;
-#ifndef NDEBUG
- shgroup->attrs_count = format->attr_len;
-#endif
-
- DRW_instancing_buffer_request(
- DST.idatalist, format, batch, shgroup, &shgroup->instance_geom, &shgroup->instance_vbo);
-
-#ifdef USE_GPU_SELECT
- if (G.f & G_FLAG_PICKSEL) {
- /* Not actually used for rendering but alloced in one chunk.
- * Plus we don't have to care about ownership. */
- static GPUVertFormat inst_select_format = {0};
- if (inst_select_format.attr_len == 0) {
- GPU_vertformat_attr_add(&inst_select_format, "selectId", GPU_COMP_I32, 1, GPU_FETCH_INT);
- }
- GPUBatch *batch_dummy; /* Not used */
- DRW_batching_buffer_request(DST.idatalist,
- &inst_select_format,
- GPU_PRIM_POINTS,
- shgroup,
- &batch_dummy,
- &shgroup->inst_selectid);
- }
-#endif
-}
-
-static void drw_shgroup_batching_init(DRWShadingGroup *shgroup,
- GPUShader *shader,
- GPUVertFormat *format)
-{
- drw_shgroup_init(shgroup, shader);
-
-#ifndef NDEBUG
- shgroup->attrs_count = (format != NULL) ? format->attr_len : 0;
-#endif
- BLI_assert(format != NULL);
-
- GPUPrimType type;
- switch (shgroup->type) {
- case DRW_SHG_POINT_BATCH:
- type = GPU_PRIM_POINTS;
- break;
- case DRW_SHG_LINE_BATCH:
- type = GPU_PRIM_LINES;
- break;
- case DRW_SHG_TRIANGLE_BATCH:
- type = GPU_PRIM_TRIS;
- break;
- default:
- type = GPU_PRIM_NONE;
- BLI_assert(0);
- break;
- }
-
- DRW_batching_buffer_request(
- DST.idatalist, format, type, shgroup, &shgroup->batch_geom, &shgroup->batch_vbo);
-
-#ifdef USE_GPU_SELECT
- if (G.f & G_FLAG_PICKSEL) {
- /* Not actually used for rendering but alloced in one chunk. */
- static GPUVertFormat inst_select_format = {0};
- if (inst_select_format.attr_len == 0) {
- GPU_vertformat_attr_add(&inst_select_format, "selectId", GPU_COMP_I32, 1, GPU_FETCH_INT);
- }
- GPUBatch *batch; /* Not used */
- DRW_batching_buffer_request(DST.idatalist,
- &inst_select_format,
- GPU_PRIM_POINTS,
- shgroup,
- &batch,
- &shgroup->inst_selectid);
- }
-#endif
}
static DRWShadingGroup *drw_shgroup_create_ex(struct GPUShader *shader, DRWPass *pass)
{
- DRWShadingGroup *shgroup = BLI_mempool_alloc(DST.vmempool->shgroups);
+ DRWShadingGroup *shgroup = BLI_memblock_alloc(DST.vmempool->shgroups);
BLI_LINKS_APPEND(&pass->shgroups, shgroup);
- shgroup->type = DRW_SHG_NORMAL;
shgroup->shader = shader;
shgroup->state_extra = 0;
shgroup->state_extra_disable = ~0x0;
shgroup->stencil_mask = 0;
shgroup->calls.first = NULL;
shgroup->calls.last = NULL;
-#if 0 /* All the same in the union! */
- shgroup->batch_geom = NULL;
- shgroup->batch_vbo = NULL;
-
- shgroup->instance_geom = NULL;
- shgroup->instance_vbo = NULL;
-#endif
+ shgroup->tfeedback_target = NULL;
shgroup->pass_parent = pass;
return shgroup;
@@ -983,10 +951,9 @@ static DRWShadingGroup *drw_shgroup_material_inputs(DRWShadingGroup *grp,
GPUTexture *tex = NULL;
if (input->ima) {
- GPUTexture **tex_ref = BLI_mempool_alloc(DST.vmempool->images);
+ GPUTexture **tex_ref = BLI_memblock_alloc(DST.vmempool->images);
- *tex_ref = tex = GPU_texture_from_blender(
- input->ima, input->iuser, GL_TEXTURE_2D, input->image_isdata);
+ *tex_ref = tex = GPU_texture_from_blender(input->ima, input->iuser, GL_TEXTURE_2D);
GPU_texture_ref(tex);
}
@@ -1033,218 +1000,536 @@ DRWShadingGroup *DRW_shgroup_material_create(struct GPUMaterial *material, DRWPa
drw_shgroup_init(shgroup, GPU_pass_shader_get(gpupass));
drw_shgroup_material_inputs(shgroup, material);
}
-
return shgroup;
}
-DRWShadingGroup *DRW_shgroup_material_instance_create(
- struct GPUMaterial *material, DRWPass *pass, GPUBatch *geom, Object *ob, GPUVertFormat *format)
+DRWShadingGroup *DRW_shgroup_create(struct GPUShader *shader, DRWPass *pass)
{
- GPUPass *gpupass = GPU_material_get_pass(material);
- DRWShadingGroup *shgroup = drw_shgroup_material_create_ex(gpupass, pass);
-
- if (shgroup) {
- shgroup->type = DRW_SHG_INSTANCE;
- shgroup->instance_geom = geom;
- drw_call_calc_orco(ob, shgroup->instance_orcofac);
- drw_shgroup_instance_init(shgroup, GPU_pass_shader_get(gpupass), geom, format);
- drw_shgroup_material_inputs(shgroup, material);
- }
+ DRWShadingGroup *shgroup = drw_shgroup_create_ex(shader, pass);
+ drw_shgroup_init(shgroup, shader);
+ return shgroup;
+}
+DRWShadingGroup *DRW_shgroup_transform_feedback_create(struct GPUShader *shader,
+ DRWPass *pass,
+ GPUVertBuf *tf_target)
+{
+ BLI_assert(tf_target != NULL);
+ DRWShadingGroup *shgroup = drw_shgroup_create_ex(shader, pass);
+ drw_shgroup_init(shgroup, shader);
+ shgroup->tfeedback_target = tf_target;
return shgroup;
}
-DRWShadingGroup *DRW_shgroup_material_empty_tri_batch_create(struct GPUMaterial *material,
- DRWPass *pass,
- int tri_count)
+/**
+ * State is added to #Pass.state while drawing.
+ * Use to temporarily enable draw options.
+ */
+void DRW_shgroup_state_enable(DRWShadingGroup *shgroup, DRWState state)
{
-#ifdef USE_GPU_SELECT
- BLI_assert((G.f & G_FLAG_PICKSEL) == 0);
-#endif
- GPUPass *gpupass = GPU_material_get_pass(material);
- DRWShadingGroup *shgroup = drw_shgroup_material_create_ex(gpupass, pass);
+ shgroup->state_extra |= state;
+}
- if (shgroup) {
- /* Calling drw_shgroup_init will cause it to call GPU_draw_primitive(). */
- drw_shgroup_init(shgroup, GPU_pass_shader_get(gpupass));
- shgroup->type = DRW_SHG_TRIANGLE_BATCH;
- shgroup->instance_count = tri_count * 3;
- drw_shgroup_material_inputs(shgroup, material);
- }
+void DRW_shgroup_state_disable(DRWShadingGroup *shgroup, DRWState state)
+{
+ shgroup->state_extra_disable &= ~state;
+}
- return shgroup;
+void DRW_shgroup_stencil_mask(DRWShadingGroup *shgroup, uint mask)
+{
+ BLI_assert(mask <= 255);
+ shgroup->stencil_mask = mask;
}
-DRWShadingGroup *DRW_shgroup_create(struct GPUShader *shader, DRWPass *pass)
+bool DRW_shgroup_is_empty(DRWShadingGroup *shgroup)
{
- DRWShadingGroup *shgroup = drw_shgroup_create_ex(shader, pass);
- drw_shgroup_init(shgroup, shader);
- return shgroup;
+ return shgroup->calls.first == NULL;
}
-DRWShadingGroup *DRW_shgroup_instance_create(struct GPUShader *shader,
- DRWPass *pass,
- GPUBatch *geom,
- GPUVertFormat *format)
+DRWShadingGroup *DRW_shgroup_create_sub(DRWShadingGroup *shgroup)
{
- DRWShadingGroup *shgroup = drw_shgroup_create_ex(shader, pass);
- shgroup->type = DRW_SHG_INSTANCE;
- shgroup->instance_geom = geom;
- drw_call_calc_orco(NULL, shgroup->instance_orcofac);
- drw_shgroup_instance_init(shgroup, shader, geom, format);
+ /* Remove this assertion if needed but implement the other cases first! */
+ DRWShadingGroup *shgroup_new = BLI_memblock_alloc(DST.vmempool->shgroups);
- return shgroup;
+ *shgroup_new = *shgroup;
+ shgroup_new->uniforms = NULL;
+ shgroup_new->calls.first = NULL;
+ shgroup_new->calls.last = NULL;
+
+ BLI_LINKS_INSERT_AFTER(&shgroup->pass_parent->shgroups, shgroup, shgroup_new);
+
+ return shgroup_new;
}
-DRWShadingGroup *DRW_shgroup_point_batch_create(struct GPUShader *shader, DRWPass *pass)
-{
- DRW_shgroup_instance_format(g_pos_format, {{"pos", DRW_ATTR_FLOAT, 3}});
+/** \} */
- DRWShadingGroup *shgroup = drw_shgroup_create_ex(shader, pass);
- shgroup->type = DRW_SHG_POINT_BATCH;
+/* -------------------------------------------------------------------- */
+/** \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
- drw_shgroup_batching_init(shgroup, shader, g_pos_format);
+ projmat_dimensions(projmat, &left, &right, &bottom, &top, &near, &far);
- return shgroup;
+ 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;
+ }
}
-DRWShadingGroup *DRW_shgroup_line_batch_create_with_format(struct GPUShader *shader,
- DRWPass *pass,
- GPUVertFormat *format)
+static void draw_frustum_bound_sphere_calc(const BoundBox *bbox,
+ const float (*viewinv)[4],
+ const float (*projmat)[4],
+ const float (*projinv)[4],
+ BoundSphere *bsphere)
{
- DRWShadingGroup *shgroup = drw_shgroup_create_ex(shader, pass);
- shgroup->type = DRW_SHG_LINE_BATCH;
+ /* 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];
- drw_shgroup_batching_init(shgroup, shader, format);
+ /* 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. */
- return shgroup;
+ /* 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);
+ }
}
-DRWShadingGroup *DRW_shgroup_line_batch_create(struct GPUShader *shader, DRWPass *pass)
+static void draw_view_matrix_state_update(DRWViewUboStorage *storage,
+ const float viewmat[4][4],
+ const float winmat[4][4])
{
- DRW_shgroup_instance_format(g_pos_format, {{"pos", DRW_ATTR_FLOAT, 3}});
+ /* 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);
- return DRW_shgroup_line_batch_create_with_format(shader, pass, g_pos_format);
+ 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);
}
-/**
- * Very special batch. Use this if you position
- * your vertices with the vertex shader
- * and dont need any VBO attribute.
- */
-DRWShadingGroup *DRW_shgroup_empty_tri_batch_create(struct GPUShader *shader,
- DRWPass *pass,
- int tri_count)
+/* 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)
{
-#ifdef USE_GPU_SELECT
- BLI_assert((G.f & G_FLAG_PICKSEL) == 0);
-#endif
- DRWShadingGroup *shgroup = drw_shgroup_create_ex(shader, pass);
+ DRWView *view = BLI_memblock_alloc(DST.vmempool->views);
- /* Calling drw_shgroup_init will cause it to call GPU_draw_primitive(). */
- drw_shgroup_init(shgroup, shader);
+ 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;
- shgroup->type = DRW_SHG_TRIANGLE_BATCH;
- shgroup->instance_count = tri_count * 3;
+ copy_v4_fl4(view->storage.viewcamtexcofac, 1.0f, 1.0f, 0.0f, 0.0f);
- return shgroup;
+ DRW_view_update(view, viewmat, winmat, culling_viewmat, culling_winmat);
+
+ return view;
}
-DRWShadingGroup *DRW_shgroup_transform_feedback_create(struct GPUShader *shader,
- DRWPass *pass,
- GPUVertBuf *tf_target)
+/* 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(tf_target != NULL);
- DRWShadingGroup *shgroup = drw_shgroup_create_ex(shader, pass);
- shgroup->type = DRW_SHG_FEEDBACK_TRANSFORM;
+ BLI_assert(parent_view && parent_view->parent == NULL);
- drw_shgroup_init(shgroup, shader);
+ DRWView *view = BLI_memblock_alloc(DST.vmempool->views);
- shgroup->tfeedback_target = tf_target;
+ /* Perform copy. */
+ *view = *parent_view;
+ view->parent = (DRWView *)parent_view;
- return shgroup;
+ DRW_view_update_sub(view, viewmat, winmat);
+
+ return view;
}
/**
- * Specify an external batch instead of adding each attribute one by one.
- */
-void DRW_shgroup_instance_batch(DRWShadingGroup *shgroup, struct GPUBatch *batch)
+ * 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(shgroup->type == DRW_SHG_INSTANCE);
- BLI_assert(shgroup->instance_count == 0);
- /* You cannot use external instancing batch without a dummy format. */
- BLI_assert(shgroup->attrs_count != 0);
+ BLI_assert(view->parent != NULL);
- shgroup->type = DRW_SHG_INSTANCE_EXTERNAL;
- drw_call_calc_orco(NULL, shgroup->instance_orcofac);
- /* PERF : This destroys the vaos cache so better check if it's necessary. */
- /* Note: This WILL break if batch->verts[0] is destroyed and reallocated
- * at the same address. Bindings/VAOs would remain obsolete. */
- // if (shgroup->instancing_geom->inst != batch->verts[0])
- GPU_batch_instbuf_set(shgroup->instance_geom, batch->verts[0], false);
+ view->is_dirty = true;
-#ifdef USE_GPU_SELECT
- shgroup->override_selectid = DST.select_id;
+ 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
}
-uint DRW_shgroup_get_instance_count(const DRWShadingGroup *shgroup)
+/* Return default view if it is a viewport render. */
+const DRWView *DRW_view_default_get(void)
{
- return shgroup->instance_count;
+ 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;
}
/**
- * State is added to #Pass.state while drawing.
- * Use to temporarily enable draw options.
+ * 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_shgroup_state_enable(DRWShadingGroup *shgroup, DRWState state)
+void DRW_view_clip_planes_set(DRWView *view, float (*planes)[4], int plane_len)
{
- shgroup->state_extra |= state;
+ 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_shgroup_state_disable(DRWShadingGroup *shgroup, DRWState state)
+void DRW_view_camtexco_set(DRWView *view, float texco[4])
{
- shgroup->state_extra_disable &= ~state;
+ copy_v4_v4(view->storage.viewcamtexcofac, texco);
}
-void DRW_shgroup_stencil_mask(DRWShadingGroup *shgroup, uint mask)
+/* Return world space frustum corners. */
+void DRW_view_frustum_corners_get(const DRWView *view, BoundBox *corners)
{
- BLI_assert(mask <= 255);
- shgroup->stencil_mask = mask;
+ memcpy(corners, &view->frustum_corners, sizeof(view->frustum_corners));
}
-bool DRW_shgroup_is_empty(DRWShadingGroup *shgroup)
+/* 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])
{
- switch (shgroup->type) {
- case DRW_SHG_NORMAL:
- case DRW_SHG_FEEDBACK_TRANSFORM:
- return shgroup->calls.first == NULL;
- case DRW_SHG_POINT_BATCH:
- case DRW_SHG_LINE_BATCH:
- case DRW_SHG_TRIANGLE_BATCH:
- case DRW_SHG_INSTANCE:
- case DRW_SHG_INSTANCE_EXTERNAL:
- return shgroup->instance_count == 0;
- }
- BLI_assert(!"Shading Group type not supported");
- return true;
+ memcpy(planes, &view->frustum_planes, sizeof(view->frustum_planes));
}
-DRWShadingGroup *DRW_shgroup_create_sub(DRWShadingGroup *shgroup)
+bool DRW_view_is_persp_get(const DRWView *view)
{
- /* Remove this assertion if needed but implement the other cases first! */
- BLI_assert(shgroup->type == DRW_SHG_NORMAL);
+ view = (view) ? view : DST.view_default;
+ return view->storage.winmat[3][3] == 0.0f;
+}
- DRWShadingGroup *shgroup_new = BLI_mempool_alloc(DST.vmempool->shgroups);
+float DRW_view_near_distance_get(const DRWView *view)
+{
+ view = (view) ? view : DST.view_default;
+ const float(*projmat)[4] = view->storage.winmat;
- *shgroup_new = *shgroup;
- shgroup_new->uniforms = NULL;
- shgroup_new->calls.first = NULL;
- shgroup_new->calls.last = NULL;
+ 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];
+ }
+}
- BLI_LINKS_INSERT_AFTER(&shgroup->pass_parent->shgroups, shgroup, shgroup_new);
+float DRW_view_far_distance_get(const DRWView *view)
+{
+ view = (view) ? view : DST.view_default;
+ const float(*projmat)[4] = view->storage.winmat;
- return shgroup_new;
+ 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);
}
/** \} */
@@ -1255,7 +1540,7 @@ DRWShadingGroup *DRW_shgroup_create_sub(DRWShadingGroup *shgroup)
DRWPass *DRW_pass_create(const char *name, DRWState state)
{
- DRWPass *pass = BLI_mempool_alloc(DST.vmempool->passes);
+ DRWPass *pass = BLI_memblock_alloc(DST.vmempool->passes);
pass->state = state;
if (((G.debug_value > 20) && (G.debug_value < 30)) || (G.debug & G_DEBUG)) {
BLI_strncpy(pass->name, name, MAX_PASS_NAME);
@@ -1292,12 +1577,6 @@ void DRW_pass_state_remove(DRWPass *pass, DRWState state)
pass->state &= ~state;
}
-void DRW_pass_free(DRWPass *pass)
-{
- pass->shgroups.first = NULL;
- pass->shgroups.last = NULL;
-}
-
void DRW_pass_foreach_shgroup(DRWPass *pass,
void (*callback)(void *userData, DRWShadingGroup *shgrp),
void *userData)
@@ -1308,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)
@@ -1372,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 8e23a616ff5..7c53d8f4fff 100644
--- a/source/blender/draw/intern/draw_manager_exec.c
+++ b/source/blender/draw/intern/draw_manager_exec.c
@@ -23,13 +23,14 @@
#include "draw_manager.h"
#include "BLI_math_bits.h"
-#include "BLI_mempool.h"
+#include "BLI_memblock.h"
#include "BKE_global.h"
#include "GPU_draw.h"
#include "GPU_extensions.h"
#include "intern/gpu_shader_private.h"
+#include "intern/gpu_primitive_private.h"
#ifdef USE_GPU_SELECT
# include "GPU_select.h"
@@ -167,18 +168,11 @@ void drw_state_set(DRWState state)
/* Wire Width */
{
int test;
- if (CHANGED_ANY_STORE_VAR(DRW_STATE_WIRE | DRW_STATE_WIRE_WIDE | DRW_STATE_WIRE_SMOOTH,
- test)) {
- if (test & DRW_STATE_WIRE_WIDE) {
- GPU_line_width(3.0f);
- }
- else if (test & DRW_STATE_WIRE_SMOOTH) {
+ if ((test = CHANGED_TO(DRW_STATE_WIRE_SMOOTH))) {
+ if (test == 1) {
GPU_line_width(2.0f);
GPU_line_smooth(true);
}
- else if (test & DRW_STATE_WIRE) {
- GPU_line_width(1.0f);
- }
else {
GPU_line_width(1.0f);
GPU_line_smooth(false);
@@ -186,20 +180,6 @@ void drw_state_set(DRWState state)
}
}
- /* Points Size */
- {
- int test;
- if ((test = CHANGED_TO(DRW_STATE_POINT))) {
- if (test == 1) {
- GPU_enable_program_point_size();
- glPointSize(5.0f);
- }
- else {
- GPU_disable_program_point_size();
- }
- }
- }
-
/* Blending (all buffer) */
{
int test;
@@ -258,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);
}
}
@@ -400,320 +380,67 @@ void DRW_state_reset(void)
{
DRW_state_reset_ex(DRW_STATE_DEFAULT);
+ GPU_point_size(5);
+ GPU_enable_program_point_size();
+
/* Reset blending function */
glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
}
-/* NOTE : Make sure to reset after use! */
-void DRW_state_invert_facing(void)
-{
- SWAP(GLenum, DST.backface, DST.frontface);
- glFrontFace(DST.frontface);
-}
-
-/**
- * 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 = len_squared_v3v3(bsphere->center, frustum_bsphere->center);
- if (center_dist > SQUARE(bsphere->radius + frustum_bsphere->radius)) {
+ 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)) {
return false;
}
+ /* TODO we could test against the inscribed sphere of the frustum to early out positively. */
/* Test against the 6 frustum planes. */
+ /* 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. */
@@ -725,202 +452,166 @@ 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);
}
-/** \} */
-
-/* -------------------------------------------------------------------- */
-/** \name Draw (DRW_draw)
- * \{ */
-
-static void draw_visibility_eval(DRWCallState *st)
+/* 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])
{
- bool culled = st->flag & DRW_CALL_CULLED;
-
- if (st->cache_id != DST.state_cache_id) {
- /* Update culling result for this view. */
- culled = !DRW_culling_sphere_test(&st->bsphere);
- }
+ view = view ? view : DST.view_default;
+ return draw_culling_plane_test(&view->frustum_corners, plane);
+}
- if (st->visibility_cb) {
- culled = !st->visibility_cb(!culled, st->user_data);
- }
+void DRW_culling_frustum_corners_get(const DRWView *view, BoundBox *corners)
+{
+ view = view ? view : DST.view_default;
+ *corners = view->frustum_corners;
+}
- SET_FLAG_FROM_TEST(st->flag, culled, DRW_CALL_CULLED);
+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_matrices_model_prepare(DRWCallState *st)
+static void draw_compute_culling(DRWView *view)
{
- if (st->cache_id == DST.state_cache_id) {
- /* Values are already updated for this view. */
- return;
- }
- else {
- st->cache_id = DST.state_cache_id;
- }
+ view = view->parent ? view->parent : view;
- /* 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) {
+ /* TODO(fclem) multithread this. */
+ /* TODO(fclem) compute all dirty views at once. */
+ if (!view->is_dirty) {
return;
}
- /* Order matters */
- if (st->matflag &
- (DRW_CALL_MODELVIEW | DRW_CALL_MODELVIEWINVERSE | DRW_CALL_NORMALVIEW | DRW_CALL_EYEVEC)) {
- mul_m4_m4m4(st->modelview, DST.view_data.matstate.mat[DRW_MAT_VIEW], st->model);
- }
- if (st->matflag & DRW_CALL_MODELVIEWINVERSE) {
- invert_m4_m4(st->modelviewinverse, st->modelview);
- }
- if (st->matflag & DRW_CALL_MODELVIEWPROJECTION) {
- mul_m4_m4m4(st->modelviewprojection, DST.view_data.matstate.mat[DRW_MAT_PERS], st->model);
- }
- if (st->matflag & (DRW_CALL_NORMALVIEW | DRW_CALL_NORMALVIEWINVERSE | DRW_CALL_EYEVEC)) {
- copy_m3_m4(st->normalview, st->modelview);
- invert_m3(st->normalview);
- transpose_m3(st->normalview);
- }
- if (st->matflag & (DRW_CALL_NORMALVIEWINVERSE | DRW_CALL_EYEVEC)) {
- invert_m3_m3(st->normalviewinverse, st->normalview);
- }
- /* TODO remove eye vec (unused) */
- if (st->matflag & DRW_CALL_EYEVEC) {
- /* Used by orthographic wires */
- copy_v3_fl3(st->eyevec, 0.0f, 0.0f, 1.0f);
- /* set eye vector, transformed to object coords */
- mul_m3_v3(st->normalviewinverse, st->eyevec);
- }
- /* Non view dependent */
- if (st->matflag & DRW_CALL_MODELINVERSE) {
- invert_m4_m4(st->modelinverse, st->model);
- st->matflag &= ~DRW_CALL_MODELINVERSE;
- }
- if (st->matflag & DRW_CALL_NORMALWORLD) {
- copy_m3_m4(st->normalworld, st->model);
- invert_m3(st->normalworld);
- transpose_m3(st->normalworld);
- st->matflag &= ~DRW_CALL_NORMALWORLD;
+
+ 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);
+ }
}
+
+ view->is_dirty = false;
}
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Draw (DRW_draw)
+ * \{ */
+
static void draw_geometry_prepare(DRWShadingGroup *shgroup, DRWCall *call)
{
- /* step 1 : bind object dependent matrices */
- if (call != NULL) {
- DRWCallState *state = call->state;
- float objectinfo[4];
- objectinfo[0] = state->objectinfo[0];
- objectinfo[1] = call->single.ma_index; /* WATCH this is only valid for single drawcalls. */
- objectinfo[2] = state->objectinfo[1];
- objectinfo[3] = (state->flag & DRW_CALL_NEGSCALE) ? -1.0f : 1.0f;
+ BLI_assert(call);
+ DRWCallState *state = call->state;
+ 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);
- GPU_shader_uniform_vector(
- shgroup->shader, shgroup->modelview, 16, 1, (float *)state->modelview);
- GPU_shader_uniform_vector(
- shgroup->shader, shgroup->modelviewinverse, 16, 1, (float *)state->modelviewinverse);
- GPU_shader_uniform_vector(
- shgroup->shader, shgroup->modelviewprojection, 16, 1, (float *)state->modelviewprojection);
- GPU_shader_uniform_vector(
- shgroup->shader, shgroup->normalview, 9, 1, (float *)state->normalview);
- GPU_shader_uniform_vector(
- shgroup->shader, shgroup->normalviewinverse, 9, 1, (float *)state->normalviewinverse);
- GPU_shader_uniform_vector(
- shgroup->shader, shgroup->normalworld, 9, 1, (float *)state->normalworld);
- GPU_shader_uniform_vector(shgroup->shader, shgroup->objectinfo, 4, 1, (float *)objectinfo);
+ }
+ 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);
- GPU_shader_uniform_vector(shgroup->shader, shgroup->eye, 3, 1, (float *)state->eyevec);
}
- else {
- BLI_assert((shgroup->normalview == -1) && (shgroup->normalworld == -1) &&
- (shgroup->eye == -1));
- /* For instancing and batching. */
- float unitmat[4][4];
- unit_m4(unitmat);
- GPU_shader_uniform_vector(shgroup->shader, shgroup->model, 16, 1, (float *)unitmat);
- GPU_shader_uniform_vector(shgroup->shader, shgroup->modelinverse, 16, 1, (float *)unitmat);
- GPU_shader_uniform_vector(shgroup->shader,
- shgroup->modelview,
- 16,
- 1,
- (float *)DST.view_data.matstate.mat[DRW_MAT_VIEW]);
- GPU_shader_uniform_vector(shgroup->shader,
- shgroup->modelviewinverse,
- 16,
- 1,
- (float *)DST.view_data.matstate.mat[DRW_MAT_VIEWINV]);
- GPU_shader_uniform_vector(shgroup->shader,
- shgroup->modelviewprojection,
- 16,
- 1,
- (float *)DST.view_data.matstate.mat[DRW_MAT_PERS]);
- GPU_shader_uniform_vector(shgroup->shader, shgroup->objectinfo, 4, 1, (float *)unitmat);
- GPU_shader_uniform_vector(
- shgroup->shader, shgroup->orcotexfac, 3, 2, (float *)shgroup->instance_orcofac);
+ /* 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_execute_ex(
- DRWShadingGroup *shgroup, GPUBatch *geom, uint start, uint count, bool draw_instance)
+BLI_INLINE void draw_geometry_execute(DRWShadingGroup *shgroup,
+ GPUBatch *geom,
+ uint vert_first,
+ uint vert_count,
+ uint inst_first,
+ uint inst_count)
{
- /* Special case: empty drawcall, placement is done via shader, don't bind anything. */
- /* TODO use DRW_CALL_PROCEDURAL instead */
- if (geom == NULL) {
- BLI_assert(shgroup->type == DRW_SHG_TRIANGLE_BATCH); /* Add other type if needed. */
- /* Shader is already bound. */
- GPU_draw_primitive(GPU_PRIM_TRIS, count);
- return;
+ /* bind vertex array */
+ if (DST.batch != geom) {
+ DST.batch = geom;
+
+ GPU_batch_program_set_no_use(
+ geom, GPU_shader_get_program(shgroup->shader), GPU_shader_get_interface(shgroup->shader));
+
+ GPU_batch_bind(geom);
}
- /* 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 */
}
-static void draw_geometry_execute(DRWShadingGroup *shgroup, GPUBatch *geom)
-{
- draw_geometry_execute_ex(shgroup, geom, 0, 0, false);
-}
-
enum {
BIND_NONE = 0,
BIND_TEMP = 1, /* Release slot after this shading group. */
@@ -929,7 +620,7 @@ enum {
static void set_bound_flags(uint64_t *slots, uint64_t *persist_slots, int slot_idx, char bind_type)
{
- uint64_t slot = 1lu << slot_idx;
+ uint64_t slot = 1lu << (unsigned long)slot_idx;
*slots |= slot;
if (bind_type == BIND_PERSIST) {
*persist_slots |= slot;
@@ -1089,39 +780,11 @@ static void release_ubo_slots(bool with_persist)
}
}
-static void draw_shgroup(DRWShadingGroup *shgroup, DRWState pass_state)
+static void draw_update_uniforms(DRWShadingGroup *shgroup)
{
- BLI_assert(shgroup->shader);
-
- GPUTexture *tex;
- GPUUniformBuffer *ubo;
- int val;
- float fval;
- const bool shader_changed = (DST.shader != shgroup->shader);
- bool use_tfeedback = false;
-
- if (shader_changed) {
- if (DST.shader) {
- GPU_shader_unbind();
- }
- GPU_shader_bind(shgroup->shader);
- DST.shader = shgroup->shader;
- }
-
- if ((pass_state & DRW_STATE_TRANS_FEEDBACK) != 0 &&
- (shgroup->type == DRW_SHG_FEEDBACK_TRANSFORM)) {
- use_tfeedback = GPU_shader_transform_feedback_enable(shgroup->shader,
- shgroup->tfeedback_target->vbo_id);
- }
-
- release_ubo_slots(shader_changed);
- release_texture_slots(shader_changed);
-
- 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) {
+ GPUTexture *tex;
+ GPUUniformBuffer *ubo;
if (uni->location == -2) {
uni->location = GPU_shader_get_uniform_ensure(shgroup->shader,
DST.uniform_names.buffer + uni->name_ofs);
@@ -1129,34 +792,20 @@ static void draw_shgroup(DRWShadingGroup *shgroup, DRWState pass_state)
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_SHORT_TO_INT:
- val = (int)*((short *)uni->pvalue);
- GPU_shader_uniform_vector_int(
- shgroup->shader, uni->location, uni->length, uni->arraysize, &val);
- break;
- case DRW_UNIFORM_SHORT_TO_FLOAT:
- fval = (float)*((short *)uni->pvalue);
- GPU_shader_uniform_vector(
- shgroup->shader, uni->location, uni->length, uni->arraysize, (float *)&fval);
- break;
- case DRW_UNIFORM_BOOL_COPY:
case DRW_UNIFORM_INT_COPY:
- GPU_shader_uniform_vector_int(
- shgroup->shader, uni->location, uni->length, uni->arraysize, &uni->ivalue);
- break;
- case DRW_UNIFORM_BOOL:
case DRW_UNIFORM_INT:
GPU_shader_uniform_vector_int(
- shgroup->shader, uni->location, uni->length, uni->arraysize, (int *)uni->pvalue);
+ shgroup->shader, uni->location, uni->length, uni->arraysize, data);
break;
case DRW_UNIFORM_FLOAT_COPY:
- GPU_shader_uniform_vector(
- shgroup->shader, uni->location, uni->length, uni->arraysize, &uni->fvalue);
- break;
case DRW_UNIFORM_FLOAT:
GPU_shader_uniform_vector(
- shgroup->shader, uni->location, uni->length, uni->arraysize, (float *)uni->pvalue);
+ shgroup->shader, uni->location, uni->length, uni->arraysize, data);
break;
case DRW_UNIFORM_TEXTURE:
tex = (GPUTexture *)uni->pvalue;
@@ -1189,112 +838,93 @@ static void draw_shgroup(DRWShadingGroup *shgroup, DRWState pass_state)
}
}
-#ifdef USE_GPU_SELECT
-# define GPU_SELECT_LOAD_IF_PICKSEL(_select_id) \
- if (G.f & G_FLAG_PICKSEL) { \
- GPU_select_load_id(_select_id); \
- } \
- ((void)0)
-
-# define GPU_SELECT_LOAD_IF_PICKSEL_CALL(_call) \
- if ((G.f & G_FLAG_PICKSEL) && (_call)) { \
- GPU_select_load_id((_call)->select_id); \
- } \
- ((void)0)
-
-# define GPU_SELECT_LOAD_IF_PICKSEL_LIST(_shgroup, _start, _count) \
- _start = 0; \
- _count = _shgroup->instance_count; \
- int *select_id = NULL; \
- if (G.f & G_FLAG_PICKSEL) { \
- if (_shgroup->override_selectid == -1) { \
- /* Hack : get vbo data without actually drawing. */ \
- GPUVertBufRaw raw; \
- GPU_vertbuf_attr_get_raw_data(_shgroup->inst_selectid, 0, &raw); \
- select_id = GPU_vertbuf_raw_step(&raw); \
- switch (_shgroup->type) { \
- case DRW_SHG_TRIANGLE_BATCH: \
- _count = 3; \
- break; \
- case DRW_SHG_LINE_BATCH: \
- _count = 2; \
- break; \
- default: \
- _count = 1; \
- break; \
- } \
- } \
- else { \
- GPU_select_load_id(_shgroup->override_selectid); \
- } \
- } \
- while (_start < _shgroup->instance_count) { \
- if (select_id) { \
- GPU_select_load_id(select_id[_start]); \
- }
-
-# define GPU_SELECT_LOAD_IF_PICKSEL_LIST_END(_start, _count) \
- _start += _count; \
- } \
- ((void)0)
-
-#else
-# define GPU_SELECT_LOAD_IF_PICKSEL(select_id)
-# define GPU_SELECT_LOAD_IF_PICKSEL_CALL(call)
-# define GPU_SELECT_LOAD_IF_PICKSEL_LIST_END(start, count) ((void)0)
-# define GPU_SELECT_LOAD_IF_PICKSEL_LIST(_shgroup, _start, _count) \
- _start = 0; \
- _count = _shgroup->instance_count;
-
-#endif
-
BLI_assert(ubo_bindings_validate(shgroup));
+}
- /* Rendering Calls */
- if (!ELEM(shgroup->type, DRW_SHG_NORMAL, DRW_SHG_FEEDBACK_TRANSFORM)) {
- /* Replacing multiple calls with only one */
- if (ELEM(shgroup->type, DRW_SHG_INSTANCE, DRW_SHG_INSTANCE_EXTERNAL)) {
- if (shgroup->type == DRW_SHG_INSTANCE_EXTERNAL) {
- if (shgroup->instance_geom != NULL) {
- GPU_SELECT_LOAD_IF_PICKSEL(shgroup->override_selectid);
- draw_geometry_prepare(shgroup, NULL);
- draw_geometry_execute_ex(shgroup, shgroup->instance_geom, 0, 0, true);
- }
+BLI_INLINE bool draw_select_do_call(DRWShadingGroup *shgroup, DRWCall *call)
+{
+#ifdef USE_GPU_SELECT
+ if ((G.f & G_FLAG_PICKSEL) == 0) {
+ return false;
+ }
+ if (call->inst_selectid != NULL) {
+ const bool is_instancing = (call->inst_count != 0);
+ uint start = 0;
+ uint count = 1;
+ uint tot = is_instancing ? call->inst_count : call->vert_count;
+ /* Hack : get vbo data without actually drawing. */
+ GPUVertBufRaw raw;
+ GPU_vertbuf_attr_get_raw_data(call->inst_selectid, 0, &raw);
+ int *select_id = GPU_vertbuf_raw_step(&raw);
+
+ /* Batching */
+ if (!is_instancing) {
+ /* FIXME: Meh a bit nasty. */
+ if (call->batch->gl_prim_type == convert_prim_type_to_gl(GPU_PRIM_TRIS)) {
+ count = 3;
}
- else {
- if (shgroup->instance_count > 0) {
- uint count, start;
- draw_geometry_prepare(shgroup, NULL);
- GPU_SELECT_LOAD_IF_PICKSEL_LIST (shgroup, start, count) {
- draw_geometry_execute_ex(shgroup, shgroup->instance_geom, start, count, true);
- }
- GPU_SELECT_LOAD_IF_PICKSEL_LIST_END(start, count);
- }
+ else if (call->batch->gl_prim_type == convert_prim_type_to_gl(GPU_PRIM_LINES)) {
+ count = 2;
}
}
- else { /* DRW_SHG_***_BATCH */
- /* Some dynamic batch can have no geom (no call to aggregate) */
- if (shgroup->instance_count > 0) {
- uint count, start;
- draw_geometry_prepare(shgroup, NULL);
- GPU_SELECT_LOAD_IF_PICKSEL_LIST (shgroup, start, count) {
- draw_geometry_execute_ex(shgroup, shgroup->batch_geom, start, count, false);
- }
- GPU_SELECT_LOAD_IF_PICKSEL_LIST_END(start, count);
+
+ while (start < tot) {
+ GPU_select_load_id(select_id[start]);
+ 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;
}
else {
+ GPU_select_load_id(call->select_id);
+ return false;
+ }
+#else
+ return false;
+#endif
+}
+
+static void draw_shgroup(DRWShadingGroup *shgroup, DRWState pass_state)
+{
+ BLI_assert(shgroup->shader);
+
+ const bool shader_changed = (DST.shader != shgroup->shader);
+ bool use_tfeedback = false;
+
+ if (shader_changed) {
+ if (DST.shader) {
+ GPU_shader_unbind();
+ }
+ GPU_shader_bind(shgroup->shader);
+ DST.shader = shgroup->shader;
+ DST.batch = NULL;
+ }
+
+ if (shgroup->tfeedback_target != NULL) {
+ use_tfeedback = GPU_shader_transform_feedback_enable(shgroup->shader,
+ shgroup->tfeedback_target->vbo_id);
+ }
+
+ release_ubo_slots(shader_changed);
+ release_texture_slots(shader_changed);
+
+ drw_state_set((pass_state & shgroup->state_extra_disable) | shgroup->state_extra);
+ drw_stencil_set(shgroup->stencil_mask);
+
+ draw_update_uniforms(shgroup);
+
+ /* Rendering Calls */
+ {
bool prev_neg_scale = false;
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;
}
@@ -1307,37 +937,21 @@ 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;
}
- GPU_SELECT_LOAD_IF_PICKSEL_CALL(call);
draw_geometry_prepare(shgroup, call);
- switch (call->type) {
- case DRW_CALL_SINGLE:
- draw_geometry_execute(shgroup, call->single.geometry);
- break;
- case DRW_CALL_RANGE:
- draw_geometry_execute_ex(
- shgroup, call->range.geometry, call->range.start, call->range.count, false);
- break;
- case DRW_CALL_INSTANCES:
- draw_geometry_execute_ex(
- shgroup, call->instances.geometry, 0, *call->instances.count, true);
- break;
- case DRW_CALL_GENERATE:
- call->generate.geometry_fn(shgroup, draw_geometry_execute, call->generate.user_data);
- break;
- case DRW_CALL_PROCEDURAL:
- GPU_draw_primitive(call->procedural.prim_type, call->procedural.vert_count);
- break;
- default:
- BLI_assert(0);
+ if (draw_select_do_call(shgroup, call)) {
+ continue;
}
+
+ 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) {
@@ -1347,29 +961,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_mempool_iter iter;
- DRWCallState *state;
- BLI_mempool_iternew(DST.vmempool->states, &iter);
- while ((state = BLI_mempool_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,
@@ -1385,7 +983,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/intern/draw_manager_shader.c b/source/blender/draw/intern/draw_manager_shader.c
index b60a41ab0c9..186bbae5cad 100644
--- a/source/blender/draw/intern/draw_manager_shader.c
+++ b/source/blender/draw/intern/draw_manager_shader.c
@@ -394,6 +394,7 @@ GPUMaterial *DRW_shader_create_from_world(struct Scene *scene,
if (mat == NULL) {
scene = (Scene *)DEG_get_original_id(&DST.draw_ctx.scene->id);
mat = GPU_material_from_nodetree(scene,
+ NULL,
wo->nodetree,
&wo->gpumaterial,
engine_type,
@@ -430,6 +431,7 @@ GPUMaterial *DRW_shader_create_from_material(struct Scene *scene,
if (mat == NULL) {
scene = (Scene *)DEG_get_original_id(&DST.draw_ctx.scene->id);
mat = GPU_material_from_nodetree(scene,
+ ma,
ma->nodetree,
&ma->gpumaterial,
engine_type,
diff --git a/source/blender/draw/modes/edit_armature_mode.c b/source/blender/draw/modes/edit_armature_mode.c
index d1ef0d0e104..9a10323c4e8 100644
--- a/source/blender/draw/modes/edit_armature_mode.c
+++ b/source/blender/draw/modes/edit_armature_mode.c
@@ -95,7 +95,7 @@ static void EDIT_ARMATURE_cache_init(void *vedata)
psl->bone_envelope[i] = DRW_pass_create("Bone Envelope Outline Pass", state);
state = DRW_STATE_WRITE_COLOR | DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_LESS_EQUAL |
- DRW_STATE_BLEND | DRW_STATE_WIRE;
+ DRW_STATE_BLEND;
psl->relationship[i] = DRW_pass_create("Bone Relationship Pass", state);
}
diff --git a/source/blender/draw/modes/edit_curve_mode.c b/source/blender/draw/modes/edit_curve_mode.c
index e47393c88c4..ff9f433ad14 100644
--- a/source/blender/draw/modes/edit_curve_mode.c
+++ b/source/blender/draw/modes/edit_curve_mode.c
@@ -39,6 +39,7 @@
* Not needed for constant color. */
extern char datatoc_common_globals_lib_glsl[];
+extern char datatoc_common_view_lib_glsl[];
extern char datatoc_edit_curve_overlay_loosevert_vert_glsl[];
extern char datatoc_edit_curve_overlay_normals_vert_glsl[];
extern char datatoc_edit_curve_overlay_handle_vert_glsl[];
@@ -111,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) {
@@ -124,8 +121,10 @@ static void EDIT_CURVE_engine_init(void *UNUSED(vedata))
if (!sh_data->wire_normals_sh) {
sh_data->wire_normals_sh = GPU_shader_create_from_arrays({
- .vert =
- (const char *[]){sh_cfg_data->lib, datatoc_edit_curve_overlay_normals_vert_glsl, NULL},
+ .vert = (const char *[]){sh_cfg_data->lib,
+ datatoc_common_view_lib_glsl,
+ datatoc_edit_curve_overlay_normals_vert_glsl,
+ NULL},
.frag = (const char *[]){datatoc_gpu_shader_uniform_color_frag_glsl, NULL},
.defs = (const char *[]){sh_cfg_data->def, NULL},
});
@@ -133,8 +132,10 @@ static void EDIT_CURVE_engine_init(void *UNUSED(vedata))
if (!sh_data->overlay_edge_sh) {
sh_data->overlay_edge_sh = GPU_shader_create_from_arrays({
- .vert =
- (const char *[]){sh_cfg_data->lib, datatoc_edit_curve_overlay_handle_vert_glsl, NULL},
+ .vert = (const char *[]){sh_cfg_data->lib,
+ datatoc_common_view_lib_glsl,
+ datatoc_edit_curve_overlay_handle_vert_glsl,
+ NULL},
.geom = (const char *[]){sh_cfg_data->lib,
datatoc_common_globals_lib_glsl,
datatoc_edit_curve_overlay_handle_geom_glsl,
@@ -148,6 +149,7 @@ static void EDIT_CURVE_engine_init(void *UNUSED(vedata))
sh_data->overlay_vert_sh = GPU_shader_create_from_arrays({
.vert = (const char *[]){sh_cfg_data->lib,
datatoc_common_globals_lib_glsl,
+ datatoc_common_view_lib_glsl,
datatoc_edit_curve_overlay_loosevert_vert_glsl,
NULL},
.frag = (const char *[]){datatoc_gpu_shader_point_varying_color_frag_glsl, NULL},
@@ -201,9 +203,8 @@ static void EDIT_CURVE_cache_init(void *vedata)
DRWShadingGroup *grp;
/* Center-Line (wire) */
- psl->wire_pass = DRW_pass_create("Curve Wire",
- DRW_STATE_WRITE_COLOR | DRW_STATE_WRITE_DEPTH |
- DRW_STATE_DEPTH_LESS_EQUAL | DRW_STATE_WIRE);
+ psl->wire_pass = DRW_pass_create(
+ "Curve Wire", DRW_STATE_WRITE_COLOR | DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_LESS_EQUAL);
EDIT_CURVE_wire_shgrp_create(sh_data,
v3d,
rv3d,
@@ -211,9 +212,8 @@ static void EDIT_CURVE_cache_init(void *vedata)
&stl->g_data->wire_shgrp,
&stl->g_data->wire_normals_shgrp);
- psl->wire_pass_xray = DRW_pass_create("Curve Wire Xray",
- DRW_STATE_WRITE_COLOR | DRW_STATE_WRITE_DEPTH |
- DRW_STATE_DEPTH_ALWAYS | DRW_STATE_WIRE);
+ psl->wire_pass_xray = DRW_pass_create(
+ "Curve Wire Xray", DRW_STATE_WRITE_COLOR | DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_ALWAYS);
EDIT_CURVE_wire_shgrp_create(sh_data,
v3d,
rv3d,
@@ -233,8 +233,7 @@ static void EDIT_CURVE_cache_init(void *vedata)
}
stl->g_data->overlay_edge_shgrp = grp;
- psl->overlay_vert_pass = DRW_pass_create("Curve Vert Overlay",
- DRW_STATE_WRITE_COLOR | DRW_STATE_POINT);
+ psl->overlay_vert_pass = DRW_pass_create("Curve Vert Overlay", DRW_STATE_WRITE_COLOR);
grp = DRW_shgroup_create(sh_data->overlay_vert_sh, psl->overlay_vert_pass);
DRW_shgroup_uniform_block(grp, "globalsBlock", G_draw.block_ubo);
@@ -270,31 +269,30 @@ static void EDIT_CURVE_cache_populate(void *vedata, Object *ob)
}
geom = DRW_cache_curve_edge_wire_get(ob);
- DRW_shgroup_call_add(wire_shgrp, geom, ob->obmat);
+ DRW_shgroup_call(wire_shgrp, geom, ob->obmat);
if ((cu->flag & CU_3D) && (v3d->overlay.edit_flag & V3D_OVERLAY_EDIT_CU_NORMALS) != 0) {
- static uint instance_len = 2;
geom = DRW_cache_curve_edge_normal_get(ob);
- DRW_shgroup_call_instances_add(wire_normals_shgrp, geom, ob->obmat, &instance_len);
+ DRW_shgroup_call_instances(wire_normals_shgrp, geom, ob->obmat, 2);
}
geom = DRW_cache_curve_edge_overlay_get(ob);
if (geom) {
- DRW_shgroup_call_add(stl->g_data->overlay_edge_shgrp, geom, ob->obmat);
+ DRW_shgroup_call(stl->g_data->overlay_edge_shgrp, geom, ob->obmat);
}
geom = DRW_cache_curve_vert_overlay_get(ob, stl->g_data->show_handles);
- DRW_shgroup_call_add(stl->g_data->overlay_vert_shgrp, geom, ob->obmat);
+ DRW_shgroup_call(stl->g_data->overlay_vert_shgrp, geom, ob->obmat);
}
}
if (ob->type == OB_SURF) {
if (BKE_object_is_in_editmode(ob)) {
struct GPUBatch *geom = DRW_cache_curve_edge_overlay_get(ob);
- DRW_shgroup_call_add(stl->g_data->overlay_edge_shgrp, geom, ob->obmat);
+ DRW_shgroup_call(stl->g_data->overlay_edge_shgrp, geom, ob->obmat);
geom = DRW_cache_curve_vert_overlay_get(ob, false);
- DRW_shgroup_call_add(stl->g_data->overlay_vert_shgrp, geom, ob->obmat);
+ DRW_shgroup_call(stl->g_data->overlay_vert_shgrp, geom, ob->obmat);
}
}
}
@@ -332,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 273480b8127..42d377f2abd 100644
--- a/source/blender/draw/modes/edit_lattice_mode.c
+++ b/source/blender/draw/modes/edit_lattice_mode.c
@@ -32,6 +32,7 @@
#include "draw_mode_engines.h"
extern char datatoc_common_globals_lib_glsl[];
+extern char datatoc_common_view_lib_glsl[];
extern char datatoc_edit_lattice_overlay_loosevert_vert_glsl[];
extern char datatoc_edit_lattice_overlay_frag_glsl[];
@@ -138,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) {
@@ -152,6 +151,7 @@ static void EDIT_LATTICE_engine_init(void *vedata)
sh_data->overlay_vert = GPU_shader_create_from_arrays({
.vert = (const char *[]){sh_cfg_data->lib,
datatoc_common_globals_lib_glsl,
+ datatoc_common_view_lib_glsl,
datatoc_edit_lattice_overlay_loosevert_vert_glsl,
NULL},
.frag = (const char *[]){datatoc_common_globals_lib_glsl,
@@ -181,14 +181,14 @@ static void EDIT_LATTICE_cache_init(void *vedata)
{
psl->wire_pass = DRW_pass_create("Lattice Wire",
DRW_STATE_WRITE_COLOR | DRW_STATE_WRITE_DEPTH |
- DRW_STATE_DEPTH_LESS_EQUAL | DRW_STATE_WIRE);
+ 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);
}
- psl->vert_pass = DRW_pass_create(
- "Lattice Verts", DRW_STATE_WRITE_COLOR | DRW_STATE_WRITE_DEPTH | DRW_STATE_POINT);
+ psl->vert_pass = DRW_pass_create("Lattice Verts",
+ DRW_STATE_WRITE_COLOR | DRW_STATE_WRITE_DEPTH);
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) {
@@ -212,10 +212,10 @@ static void EDIT_LATTICE_cache_populate(void *vedata, Object *ob)
struct GPUBatch *geom;
geom = DRW_cache_lattice_wire_get(ob, true);
- DRW_shgroup_call_add(stl->g_data->wire_shgrp, geom, ob->obmat);
+ DRW_shgroup_call(stl->g_data->wire_shgrp, geom, ob->obmat);
geom = DRW_cache_lattice_vert_overlay_get(ob);
- DRW_shgroup_call_add(stl->g_data->vert_shgrp, geom, ob->obmat);
+ DRW_shgroup_call(stl->g_data->vert_shgrp, geom, ob->obmat);
}
}
}
diff --git a/source/blender/draw/modes/edit_mesh_mode.c b/source/blender/draw/modes/edit_mesh_mode.c
index ffe7fe5845c..2b17dd43ee5 100644
--- a/source/blender/draw/modes/edit_mesh_mode.c
+++ b/source/blender/draw/modes/edit_mesh_mode.c
@@ -60,6 +60,7 @@ extern char datatoc_edit_mesh_overlay_mesh_analysis_vert_glsl[];
extern char datatoc_edit_normals_vert_glsl[];
extern char datatoc_edit_normals_geom_glsl[];
extern char datatoc_common_globals_lib_glsl[];
+extern char datatoc_common_view_lib_glsl[];
extern char datatoc_gpu_shader_uniform_color_frag_glsl[];
extern char datatoc_gpu_shader_3D_smooth_color_frag_glsl[];
@@ -187,16 +188,13 @@ 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) {
sh_data->weight_face = GPU_shader_create_from_arrays({
.vert = (const char *[]){sh_cfg_data->lib,
datatoc_common_globals_lib_glsl,
+ datatoc_common_view_lib_glsl,
datatoc_paint_weight_vert_glsl,
NULL},
.frag = (const char *[]){datatoc_common_globals_lib_glsl,
@@ -207,6 +205,7 @@ static void EDIT_MESH_engine_init(void *vedata)
char *lib = BLI_string_joinN(sh_cfg_data->lib,
datatoc_common_globals_lib_glsl,
+ datatoc_common_view_lib_glsl,
datatoc_edit_mesh_overlay_common_lib_glsl);
/* Use geometry shader to draw edge wireframe. This ensure us
* the same result accross platforms and more flexibility. But
@@ -265,43 +264,43 @@ static void EDIT_MESH_engine_init(void *vedata)
sh_data->overlay_mix = DRW_shader_create_fullscreen(datatoc_edit_mesh_overlay_mix_frag_glsl,
NULL);
+ lib = BLI_string_joinN(sh_cfg_data->lib, datatoc_common_view_lib_glsl);
+
sh_data->normals_face = GPU_shader_create_from_arrays({
- .vert = (const char *[]){sh_cfg_data->lib, datatoc_edit_normals_vert_glsl, NULL},
- .geom = (const char *[]){sh_cfg_data->lib, datatoc_edit_normals_geom_glsl, NULL},
+ .vert = (const char *[]){lib, datatoc_edit_normals_vert_glsl, NULL},
+ .geom = (const char *[]){lib, datatoc_edit_normals_geom_glsl, NULL},
.frag = (const char *[]){datatoc_gpu_shader_uniform_color_frag_glsl, NULL},
.defs = (const char *[]){sh_cfg_data->def, "#define FACE_NORMALS\n", NULL},
});
sh_data->normals_loop = GPU_shader_create_from_arrays({
- .vert = (const char *[]){sh_cfg_data->lib, datatoc_edit_normals_vert_glsl, NULL},
- .geom = (const char *[]){sh_cfg_data->lib, datatoc_edit_normals_geom_glsl, NULL},
+ .vert = (const char *[]){lib, datatoc_edit_normals_vert_glsl, NULL},
+ .geom = (const char *[]){lib, datatoc_edit_normals_geom_glsl, NULL},
.frag = (const char *[]){datatoc_gpu_shader_uniform_color_frag_glsl, NULL},
.defs = (const char *[]){sh_cfg_data->def, "#define LOOP_NORMALS\n", NULL},
});
sh_data->normals = GPU_shader_create_from_arrays({
- .vert = (const char *[]){sh_cfg_data->lib, datatoc_edit_normals_vert_glsl, NULL},
- .geom = (const char *[]){sh_cfg_data->lib, datatoc_edit_normals_geom_glsl, NULL},
+ .vert = (const char *[]){lib, datatoc_edit_normals_vert_glsl, NULL},
+ .geom = (const char *[]){lib, datatoc_edit_normals_geom_glsl, NULL},
.frag = (const char *[]){datatoc_gpu_shader_uniform_color_frag_glsl, NULL},
.defs = (const char *[]){sh_cfg_data->def, NULL},
});
/* Mesh Analysis */
sh_data->mesh_analysis_face = GPU_shader_create_from_arrays({
- .vert = (const char *[]){sh_cfg_data->lib,
- datatoc_edit_mesh_overlay_mesh_analysis_vert_glsl,
- NULL},
+ .vert = (const char *[]){lib, datatoc_edit_mesh_overlay_mesh_analysis_vert_glsl, NULL},
.frag = (const char *[]){datatoc_edit_mesh_overlay_mesh_analysis_frag_glsl, NULL},
.defs = (const char *[]){sh_cfg_data->def, "#define FACE_COLOR\n", NULL},
});
sh_data->mesh_analysis_vertex = GPU_shader_create_from_arrays({
- .vert = (const char *[]){sh_cfg_data->lib,
- datatoc_edit_mesh_overlay_mesh_analysis_vert_glsl,
- NULL},
+ .vert = (const char *[]){lib, datatoc_edit_mesh_overlay_mesh_analysis_vert_glsl, NULL},
.frag = (const char *[]){datatoc_edit_mesh_overlay_mesh_analysis_frag_glsl, NULL},
.defs = (const char *[]){sh_cfg_data->def, "#define VERTEX_COLOR\n", NULL},
});
+ MEM_freeN(lib);
+
sh_data->depth = DRW_shader_create_3d_depth_only(draw_ctx->sh_cfg);
}
}
@@ -327,15 +326,15 @@ static DRWPass *edit_mesh_create_overlay_pass(float *face_alpha,
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]));
}
const float depth_ofs = bglPolygonOffsetCalc((float *)winmat, viewdist, 1.0f);
- DRWPass *pass = DRW_pass_create("Edit Mesh Face Overlay Pass",
- DRW_STATE_WRITE_COLOR | DRW_STATE_POINT | statemod);
+ DRWPass *pass = DRW_pass_create("Edit Mesh Face Overlay Pass", DRW_STATE_WRITE_COLOR | statemod);
DRWShadingGroup *grp;
@@ -603,7 +602,7 @@ static void EDIT_MESH_cache_init(void *vedata)
psl->mix_occlude = DRW_pass_create("Mix Occluded Wires",
DRW_STATE_WRITE_COLOR | DRW_STATE_BLEND);
DRWShadingGroup *mix_shgrp = DRW_shgroup_create(sh_data->overlay_mix, psl->mix_occlude);
- DRW_shgroup_call_add(mix_shgrp, quad, NULL);
+ DRW_shgroup_call(mix_shgrp, quad, NULL);
DRW_shgroup_uniform_float(mix_shgrp, "alpha", &backwire_opacity, 1);
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);
@@ -636,17 +635,17 @@ static void edit_mesh_add_ob_to_pass(Scene *scene,
geom_tris = DRW_mesh_batch_cache_get_edit_triangles(ob->data);
geom_edges = DRW_mesh_batch_cache_get_edit_edges(ob->data);
- DRW_shgroup_call_add(edge_shgrp, geom_edges, ob->obmat);
- DRW_shgroup_call_add(face_shgrp, geom_tris, ob->obmat);
+ DRW_shgroup_call(edge_shgrp, geom_edges, ob->obmat);
+ DRW_shgroup_call(face_shgrp, geom_tris, ob->obmat);
if ((tsettings->selectmode & SCE_SELECT_VERTEX) != 0) {
geom_verts = DRW_mesh_batch_cache_get_edit_vertices(ob->data);
- DRW_shgroup_call_add(vert_shgrp, geom_verts, ob->obmat);
+ DRW_shgroup_call(vert_shgrp, geom_verts, ob->obmat);
}
if (facedot_shgrp && (tsettings->selectmode & SCE_SELECT_FACE) != 0) {
geom_fcenter = DRW_mesh_batch_cache_get_edit_facedots(ob->data);
- DRW_shgroup_call_add(facedot_shgrp, geom_fcenter, ob->obmat);
+ DRW_shgroup_call(facedot_shgrp, geom_fcenter, ob->obmat);
}
}
@@ -691,7 +690,7 @@ static void EDIT_MESH_cache_populate(void *vedata, Object *ob)
if (do_show_weight) {
geom = DRW_cache_mesh_surface_weights_get(ob);
- DRW_shgroup_call_add(g_data->fweights_shgrp, geom, ob->obmat);
+ DRW_shgroup_call(g_data->fweights_shgrp, geom, ob->obmat);
}
if (do_show_mesh_analysis) {
@@ -702,30 +701,30 @@ static void EDIT_MESH_cache_populate(void *vedata, Object *ob)
if (is_original) {
geom = DRW_cache_mesh_surface_mesh_analysis_get(ob);
if (geom) {
- DRW_shgroup_call_add(g_data->mesh_analysis_shgrp, geom, ob->obmat);
+ DRW_shgroup_call(g_data->mesh_analysis_shgrp, geom, ob->obmat);
}
}
}
if (do_occlude_wire || do_in_front) {
geom = DRW_cache_mesh_surface_get(ob);
- DRW_shgroup_call_add(do_in_front ? g_data->depth_shgrp_hidden_wire_in_front :
- g_data->depth_shgrp_hidden_wire,
- geom,
- ob->obmat);
+ DRW_shgroup_call(do_in_front ? g_data->depth_shgrp_hidden_wire_in_front :
+ g_data->depth_shgrp_hidden_wire,
+ geom,
+ ob->obmat);
}
if (vnormals_do) {
geom = DRW_mesh_batch_cache_get_edit_vertices(ob->data);
- DRW_shgroup_call_add(g_data->vnormals_shgrp, geom, ob->obmat);
+ DRW_shgroup_call(g_data->vnormals_shgrp, geom, ob->obmat);
}
if (lnormals_do) {
geom = DRW_mesh_batch_cache_get_edit_lnors(ob->data);
- DRW_shgroup_call_add(g_data->lnormals_shgrp, geom, ob->obmat);
+ DRW_shgroup_call(g_data->lnormals_shgrp, geom, ob->obmat);
}
if (fnormals_do) {
geom = DRW_mesh_batch_cache_get_edit_facedots(ob->data);
- DRW_shgroup_call_add(g_data->fnormals_shgrp, geom, ob->obmat);
+ DRW_shgroup_call(g_data->fnormals_shgrp, geom, ob->obmat);
}
if (g_data->do_zbufclip) {
@@ -822,8 +821,6 @@ 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);
}
-
- 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 aa7c6863423..82b1ddbd66d 100644
--- a/source/blender/draw/modes/edit_metaball_mode.c
+++ b/source/blender/draw/modes/edit_metaball_mode.c
@@ -26,6 +26,8 @@
#include "BKE_object.h"
+#include "DEG_depsgraph_query.h"
+
#include "ED_mball.h"
/* If builtin shaders are needed */
@@ -86,19 +88,11 @@ typedef struct EDIT_METABALL_Data {
typedef struct EDIT_METABALL_PrivateData {
/* This keeps the references of the shading groups for
* easy access in EDIT_METABALL_cache_populate() */
- DRWShadingGroup *group;
+ DRWCallBuffer *group;
} EDIT_METABALL_PrivateData; /* Transient data */
/* *********** 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)
@@ -115,11 +109,11 @@ static void EDIT_METABALL_cache_init(void *vedata)
{
/* Create a pass */
DRWState state = (DRW_STATE_WRITE_COLOR | DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_LESS_EQUAL |
- DRW_STATE_BLEND | DRW_STATE_WIRE);
+ DRW_STATE_BLEND);
psl->pass = DRW_pass_create("My Pass", state);
/* Create a shadingGroup using a function in draw_common.c or custom one */
- stl->g_data->group = shgroup_instance_mball_handles(psl->pass, draw_ctx->sh_cfg);
+ stl->g_data->group = buffer_instance_mball_handles(psl->pass, draw_ctx->sh_cfg);
}
}
@@ -131,7 +125,7 @@ static void EDIT_METABALL_cache_populate(void *vedata, Object *ob)
if (ob->type == OB_MBALL) {
const DRWContextState *draw_ctx = DRW_context_state_get();
- DRWShadingGroup *group = stl->g_data->group;
+ DRWCallBuffer *group = stl->g_data->group;
if ((ob == draw_ctx->object_edit) || BKE_object_is_in_editmode(ob)) {
MetaBall *mb = ob->data;
@@ -160,7 +154,8 @@ static void EDIT_METABALL_cache_populate(void *vedata, Object *ob)
copy_v3_v3(draw_scale_xform[2], scamat[2]);
}
- int select_id = ob->select_id;
+ const Object *orig_object = DEG_get_original_object(ob);
+ int select_id = orig_object->runtime.select_id;
for (MetaElem *ml = mb->editelems->first; ml != NULL; ml = ml->next, select_id += 0x10000) {
float world_pos[3];
mul_v3_m4v3(world_pos, ob->obmat, &ml->x);
@@ -181,7 +176,7 @@ static void EDIT_METABALL_cache_populate(void *vedata, Object *ob)
DRW_select_load_id(select_id | MBALLSEL_RADIUS);
}
- DRW_shgroup_call_dynamic_add(group, draw_scale_xform, &ml->rad, color);
+ DRW_buffer_add_entry(group, draw_scale_xform, &ml->rad, color);
if ((ml->flag & SELECT) && !(ml->flag & MB_SCALE_RAD)) {
color = col_stiffness_select;
@@ -194,7 +189,7 @@ static void EDIT_METABALL_cache_populate(void *vedata, Object *ob)
DRW_select_load_id(select_id | MBALLSEL_STIFF);
}
- DRW_shgroup_call_dynamic_add(group, draw_scale_xform, &draw_stiffness_radius, color);
+ DRW_buffer_add_entry(group, draw_scale_xform, &draw_stiffness_radius, color);
}
}
}
@@ -206,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.
@@ -229,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/edit_text_mode.c b/source/blender/draw/modes/edit_text_mode.c
index 5f44a74b24e..b7215d5ef08 100644
--- a/source/blender/draw/modes/edit_text_mode.c
+++ b/source/blender/draw/modes/edit_text_mode.c
@@ -102,8 +102,8 @@ typedef struct EDIT_TEXT_PrivateData {
DRWShadingGroup *wire_shgrp;
DRWShadingGroup *overlay_select_shgrp;
DRWShadingGroup *overlay_cursor_shgrp;
- DRWShadingGroup *box_shgrp;
- DRWShadingGroup *box_active_shgrp;
+ DRWCallBuffer *box_shgrp;
+ DRWCallBuffer *box_active_shgrp;
} EDIT_TEXT_PrivateData; /* Transient data */
/* *********** FUNCTIONS *********** */
@@ -162,9 +162,8 @@ static void EDIT_TEXT_cache_init(void *vedata)
{
/* Text outline (fast drawing!) */
- psl->wire_pass = DRW_pass_create("Font Wire",
- DRW_STATE_WRITE_COLOR | DRW_STATE_WRITE_DEPTH |
- DRW_STATE_DEPTH_LESS_EQUAL | DRW_STATE_WIRE);
+ psl->wire_pass = DRW_pass_create(
+ "Font Wire", DRW_STATE_WRITE_COLOR | DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_LESS_EQUAL);
stl->g_data->wire_shgrp = DRW_shgroup_create(e_data.wire_sh, psl->wire_pass);
psl->overlay_select_pass = DRW_pass_create("Font Select",
@@ -179,9 +178,9 @@ static void EDIT_TEXT_cache_init(void *vedata)
psl->text_box_pass = DRW_pass_create("Font Text Boxes",
DRW_STATE_WRITE_COLOR | DRW_STATE_WRITE_DEPTH);
- stl->g_data->box_shgrp = shgroup_dynlines_dashed_uniform_color(
+ stl->g_data->box_shgrp = buffer_dynlines_dashed_uniform_color(
psl->text_box_pass, G_draw.block.colorWire, draw_ctx->sh_cfg);
- stl->g_data->box_active_shgrp = shgroup_dynlines_dashed_uniform_color(
+ stl->g_data->box_active_shgrp = buffer_dynlines_dashed_uniform_color(
psl->text_box_pass, G_draw.block.colorActive, draw_ctx->sh_cfg);
}
}
@@ -241,7 +240,7 @@ static void edit_text_cache_populate_select(void *vedata, Object *ob)
v2_quad_corners_to_mat4(box, final_mat);
mul_m4_m4m4(final_mat, ob->obmat, final_mat);
- DRW_shgroup_call_add(stl->g_data->overlay_select_shgrp, geom, final_mat);
+ DRW_shgroup_call(stl->g_data->overlay_select_shgrp, geom, final_mat);
}
}
@@ -257,7 +256,7 @@ static void edit_text_cache_populate_cursor(void *vedata, Object *ob)
mul_m4_m4m4(mat, ob->obmat, mat);
struct GPUBatch *geom = DRW_cache_quad_get();
- DRW_shgroup_call_add(stl->g_data->overlay_cursor_shgrp, geom, mat);
+ DRW_shgroup_call(stl->g_data->overlay_cursor_shgrp, geom, mat);
}
static void edit_text_cache_populate_boxes(void *vedata, Object *ob)
@@ -265,7 +264,7 @@ static void edit_text_cache_populate_boxes(void *vedata, Object *ob)
EDIT_TEXT_StorageList *stl = ((EDIT_TEXT_Data *)vedata)->stl;
const Curve *cu = ob->data;
- DRWShadingGroup *shading_groups[] = {
+ DRWCallBuffer *callbufs[] = {
stl->g_data->box_active_shgrp,
stl->g_data->box_shgrp,
};
@@ -279,7 +278,7 @@ static void edit_text_cache_populate_boxes(void *vedata, Object *ob)
}
const bool is_active = i == (cu->actbox - 1);
- DRWShadingGroup *shading_group = shading_groups[is_active ? 0 : 1];
+ DRWCallBuffer *callbuf = callbufs[is_active ? 0 : 1];
vec[0] = cu->xof + tb->x;
vec[1] = cu->yof + tb->y + cu->fsize_realtime;
@@ -289,29 +288,29 @@ static void edit_text_cache_populate_boxes(void *vedata, Object *ob)
vec[0] += tb->w;
mul_v3_m4v3(vec2, ob->obmat, vec);
- DRW_shgroup_call_dynamic_add(shading_group, vec1);
- DRW_shgroup_call_dynamic_add(shading_group, vec2);
+ DRW_buffer_add_entry(callbuf, vec1);
+ DRW_buffer_add_entry(callbuf, vec2);
vec[1] -= tb->h;
copy_v3_v3(vec1, vec2);
mul_v3_m4v3(vec2, ob->obmat, vec);
- DRW_shgroup_call_dynamic_add(shading_group, vec1);
- DRW_shgroup_call_dynamic_add(shading_group, vec2);
+ DRW_buffer_add_entry(callbuf, vec1);
+ DRW_buffer_add_entry(callbuf, vec2);
vec[0] -= tb->w;
copy_v3_v3(vec1, vec2);
mul_v3_m4v3(vec2, ob->obmat, vec);
- DRW_shgroup_call_dynamic_add(shading_group, vec1);
- DRW_shgroup_call_dynamic_add(shading_group, vec2);
+ DRW_buffer_add_entry(callbuf, vec1);
+ DRW_buffer_add_entry(callbuf, vec2);
vec[1] += tb->h;
copy_v3_v3(vec1, vec2);
mul_v3_m4v3(vec2, ob->obmat, vec);
- DRW_shgroup_call_dynamic_add(shading_group, vec1);
- DRW_shgroup_call_dynamic_add(shading_group, vec2);
+ DRW_buffer_add_entry(callbuf, vec1);
+ DRW_buffer_add_entry(callbuf, vec2);
}
}
@@ -334,7 +333,7 @@ static void EDIT_TEXT_cache_populate(void *vedata, Object *ob)
if ((cu->flag & CU_FAST) || !has_surface) {
geom = DRW_cache_text_edge_wire_get(ob);
if (geom) {
- DRW_shgroup_call_add(stl->g_data->wire_shgrp, geom, ob->obmat);
+ DRW_shgroup_call(stl->g_data->wire_shgrp, geom, ob->obmat);
}
}
else {
diff --git a/source/blender/draw/modes/object_mode.c b/source/blender/draw/modes/object_mode.c
index ee2c660ca06..68af4fc0c4a 100644
--- a/source/blender/draw/modes/object_mode.c
+++ b/source/blender/draw/modes/object_mode.c
@@ -88,6 +88,7 @@ extern char datatoc_object_particle_prim_vert_glsl[];
extern char datatoc_object_particle_dot_vert_glsl[];
extern char datatoc_object_particle_dot_frag_glsl[];
extern char datatoc_common_globals_lib_glsl[];
+extern char datatoc_common_view_lib_glsl[];
extern char datatoc_common_fxaa_lib_glsl[];
extern char datatoc_gpu_shader_flat_color_frag_glsl[];
extern char datatoc_gpu_shader_flat_id_frag_glsl[];
@@ -171,82 +172,82 @@ typedef struct OBJECT_ShadingGroupList {
struct DRWPass *bone_axes;
/* Empties */
- DRWShadingGroup *plain_axes;
- DRWShadingGroup *cube;
- DRWShadingGroup *circle;
- DRWShadingGroup *sphere;
- DRWShadingGroup *sphere_solid;
- DRWShadingGroup *cylinder;
- DRWShadingGroup *capsule_cap;
- DRWShadingGroup *capsule_body;
- DRWShadingGroup *cone;
- DRWShadingGroup *single_arrow;
- DRWShadingGroup *single_arrow_line;
- DRWShadingGroup *empty_axes;
+ DRWCallBuffer *plain_axes;
+ DRWCallBuffer *cube;
+ DRWCallBuffer *circle;
+ DRWCallBuffer *sphere;
+ DRWCallBuffer *sphere_solid;
+ DRWCallBuffer *cylinder;
+ DRWCallBuffer *capsule_cap;
+ DRWCallBuffer *capsule_body;
+ DRWCallBuffer *cone;
+ DRWCallBuffer *single_arrow;
+ DRWCallBuffer *single_arrow_line;
+ DRWCallBuffer *empty_axes;
/* Force Field */
- DRWShadingGroup *field_wind;
- DRWShadingGroup *field_force;
- DRWShadingGroup *field_vortex;
- DRWShadingGroup *field_curve_sta;
- DRWShadingGroup *field_curve_end;
- DRWShadingGroup *field_tube_limit;
- DRWShadingGroup *field_cone_limit;
+ DRWCallBuffer *field_wind;
+ DRWCallBuffer *field_force;
+ DRWCallBuffer *field_vortex;
+ DRWCallBuffer *field_curve_sta;
+ DRWCallBuffer *field_curve_end;
+ DRWCallBuffer *field_tube_limit;
+ DRWCallBuffer *field_cone_limit;
/* Grease Pencil */
- DRWShadingGroup *gpencil_axes;
+ DRWCallBuffer *gpencil_axes;
/* Speaker */
- DRWShadingGroup *speaker;
+ DRWCallBuffer *speaker;
/* Probe */
- DRWShadingGroup *probe_cube;
- DRWShadingGroup *probe_planar;
- DRWShadingGroup *probe_grid;
+ DRWCallBuffer *probe_cube;
+ DRWCallBuffer *probe_planar;
+ DRWCallBuffer *probe_grid;
/* MetaBalls */
- DRWShadingGroup *mball_handle;
+ DRWCallBuffer *mball_handle;
/* Lights */
- DRWShadingGroup *light_center;
- DRWShadingGroup *light_groundpoint;
- DRWShadingGroup *light_groundline;
- DRWShadingGroup *light_circle;
- DRWShadingGroup *light_circle_shadow;
- DRWShadingGroup *light_sunrays;
- DRWShadingGroup *light_distance;
- DRWShadingGroup *light_buflimit;
- DRWShadingGroup *light_buflimit_points;
- DRWShadingGroup *light_area_sphere;
- DRWShadingGroup *light_area_square;
- DRWShadingGroup *light_area_disk;
- DRWShadingGroup *light_hemi;
- DRWShadingGroup *light_spot_cone;
- DRWShadingGroup *light_spot_blend;
- DRWShadingGroup *light_spot_pyramid;
- DRWShadingGroup *light_spot_blend_rect;
- DRWShadingGroup *light_spot_volume;
- DRWShadingGroup *light_spot_volume_rect;
- DRWShadingGroup *light_spot_volume_outside;
- DRWShadingGroup *light_spot_volume_rect_outside;
+ DRWCallBuffer *light_center;
+ DRWCallBuffer *light_groundpoint;
+ DRWCallBuffer *light_groundline;
+ DRWCallBuffer *light_circle;
+ DRWCallBuffer *light_circle_shadow;
+ DRWCallBuffer *light_sunrays;
+ DRWCallBuffer *light_distance;
+ DRWCallBuffer *light_buflimit;
+ DRWCallBuffer *light_buflimit_points;
+ DRWCallBuffer *light_area_sphere;
+ DRWCallBuffer *light_area_square;
+ DRWCallBuffer *light_area_disk;
+ DRWCallBuffer *light_hemi;
+ DRWCallBuffer *light_spot_cone;
+ DRWCallBuffer *light_spot_blend;
+ DRWCallBuffer *light_spot_pyramid;
+ DRWCallBuffer *light_spot_blend_rect;
+ DRWCallBuffer *light_spot_volume;
+ DRWCallBuffer *light_spot_volume_rect;
+ DRWCallBuffer *light_spot_volume_outside;
+ DRWCallBuffer *light_spot_volume_rect_outside;
/* Helpers */
- DRWShadingGroup *relationship_lines;
- DRWShadingGroup *constraint_lines;
+ DRWCallBuffer *relationship_lines;
+ DRWCallBuffer *constraint_lines;
/* Camera */
- DRWShadingGroup *camera;
- DRWShadingGroup *camera_frame;
- DRWShadingGroup *camera_tria;
- DRWShadingGroup *camera_focus;
- DRWShadingGroup *camera_clip;
- DRWShadingGroup *camera_clip_points;
- DRWShadingGroup *camera_mist;
- DRWShadingGroup *camera_mist_points;
- DRWShadingGroup *camera_stereo_plane;
- DRWShadingGroup *camera_stereo_plane_wires;
- DRWShadingGroup *camera_stereo_volume;
- DRWShadingGroup *camera_stereo_volume_wires;
+ DRWCallBuffer *camera;
+ DRWCallBuffer *camera_frame;
+ DRWCallBuffer *camera_tria;
+ DRWCallBuffer *camera_focus;
+ DRWCallBuffer *camera_clip;
+ DRWCallBuffer *camera_clip_points;
+ DRWCallBuffer *camera_mist;
+ DRWCallBuffer *camera_mist_points;
+ DRWCallBuffer *camera_stereo_plane;
+ DRWCallBuffer *camera_stereo_plane_wires;
+ DRWCallBuffer *camera_stereo_volume;
+ DRWCallBuffer *camera_stereo_volume_wires;
ListBase camera_path;
/* Wire */
@@ -268,7 +269,7 @@ typedef struct OBJECT_ShadingGroupList {
DRWShadingGroup *points_dupli_select;
/* Texture Space */
- DRWShadingGroup *texspace;
+ DRWCallBuffer *texspace;
} OBJECT_ShadingGroupList;
typedef struct OBJECT_PrivateData {
@@ -284,22 +285,22 @@ typedef struct OBJECT_PrivateData {
DRWShadingGroup *outlines_transform;
/* Lightprobes */
- DRWShadingGroup *lightprobes_cube_select;
- DRWShadingGroup *lightprobes_cube_select_dupli;
- DRWShadingGroup *lightprobes_cube_active;
- DRWShadingGroup *lightprobes_cube_transform;
+ DRWCallBuffer *lightprobes_cube_select;
+ DRWCallBuffer *lightprobes_cube_select_dupli;
+ DRWCallBuffer *lightprobes_cube_active;
+ DRWCallBuffer *lightprobes_cube_transform;
- DRWShadingGroup *lightprobes_planar_select;
- DRWShadingGroup *lightprobes_planar_select_dupli;
- DRWShadingGroup *lightprobes_planar_active;
- DRWShadingGroup *lightprobes_planar_transform;
+ DRWCallBuffer *lightprobes_planar_select;
+ DRWCallBuffer *lightprobes_planar_select_dupli;
+ DRWCallBuffer *lightprobes_planar_active;
+ DRWCallBuffer *lightprobes_planar_transform;
/* Objects Centers */
- DRWShadingGroup *center_active;
- DRWShadingGroup *center_selected;
- DRWShadingGroup *center_deselected;
- DRWShadingGroup *center_selected_lib;
- DRWShadingGroup *center_deselected_lib;
+ DRWCallBuffer *center_active;
+ DRWCallBuffer *center_selected;
+ DRWCallBuffer *center_deselected;
+ DRWCallBuffer *center_selected_lib;
+ DRWCallBuffer *center_deselected_lib;
/* Outlines id offset (accessed as an array) */
int id_ofs_active;
@@ -316,15 +317,20 @@ typedef struct OBJECT_PrivateData {
bool xray_enabled_and_not_wire;
} OBJECT_PrivateData; /* Transient data */
+typedef struct OBJECT_DupliData {
+ DRWShadingGroup *outline_shgrp;
+ GPUBatch *outline_geom;
+ DRWShadingGroup *extra_shgrp;
+ GPUBatch *extra_geom;
+} OBJECT_DupliData;
+
static struct {
/* Instance Data format */
- struct GPUVertFormat *particle_format;
struct GPUVertFormat *empty_image_format;
struct GPUVertFormat *empty_image_wire_format;
OBJECT_Shaders sh_data[GPU_SHADER_CFG_LEN];
- float camera_pos[3];
float grid_settings[5];
float grid_mesh_size;
int grid_flag;
@@ -412,8 +418,14 @@ static void OBJECT_engine_init(void *vedata)
.defs = (const char *[]){sh_cfg_data->def, NULL},
});
sh_data->outline_prepass_wire = GPU_shader_create_from_arrays({
- .vert = (const char *[]){sh_cfg_data->lib, datatoc_object_outline_prepass_vert_glsl, NULL},
- .geom = (const char *[]){sh_cfg_data->lib, datatoc_object_outline_prepass_geom_glsl, NULL},
+ .vert = (const char *[]){sh_cfg_data->lib,
+ datatoc_common_view_lib_glsl,
+ datatoc_object_outline_prepass_vert_glsl,
+ NULL},
+ .geom = (const char *[]){sh_cfg_data->lib,
+ datatoc_common_view_lib_glsl,
+ datatoc_object_outline_prepass_geom_glsl,
+ NULL},
.frag = (const char *[]){datatoc_object_outline_prepass_frag_glsl, NULL},
.defs = (const char *[]){sh_cfg_data->def, NULL},
});
@@ -455,37 +467,53 @@ static void OBJECT_engine_init(void *vedata)
"#define DEPTH_BACK " STRINGIFY(OB_EMPTY_IMAGE_DEPTH_BACK) "\n");
sh_data->object_empty_image = GPU_shader_create_from_arrays({
- .vert = (const char *[]){sh_cfg_data->lib, datatoc_object_empty_image_vert_glsl, NULL},
+ .vert = (const char *[]){sh_cfg_data->lib,
+ datatoc_common_view_lib_glsl,
+ datatoc_object_empty_image_vert_glsl,
+ NULL},
.frag = (const char *[]){datatoc_object_empty_image_frag_glsl, NULL},
.defs = (const char *[]){sh_cfg_data->def, empty_image_defs, NULL},
});
sh_data->object_empty_image_wire = GPU_shader_create_from_arrays({
- .vert = (const char *[]){sh_cfg_data->lib, datatoc_object_empty_image_vert_glsl, NULL},
+ .vert = (const char *[]){sh_cfg_data->lib,
+ datatoc_common_view_lib_glsl,
+ datatoc_object_empty_image_vert_glsl,
+ NULL},
.frag = (const char *[]){datatoc_object_empty_image_frag_glsl, NULL},
.defs = (const char *[]){sh_cfg_data->def, "#define USE_WIRE\n", empty_image_defs, NULL},
});
}
/* Grid */
- sh_data->grid = DRW_shader_create_with_lib(datatoc_object_grid_vert_glsl,
- NULL,
- datatoc_object_grid_frag_glsl,
- datatoc_common_globals_lib_glsl,
- NULL);
+ sh_data->grid = GPU_shader_create_from_arrays({
+ .vert = (const char *[]){datatoc_common_globals_lib_glsl,
+ datatoc_common_view_lib_glsl,
+ datatoc_object_grid_vert_glsl,
+ NULL},
+ .frag = (const char *[]){datatoc_common_globals_lib_glsl,
+ datatoc_common_view_lib_glsl,
+ datatoc_object_grid_frag_glsl,
+ NULL},
+ });
/* Particles */
- sh_data->part_prim = DRW_shader_create(datatoc_object_particle_prim_vert_glsl,
- NULL,
- datatoc_gpu_shader_flat_color_frag_glsl,
- NULL);
-
- sh_data->part_axis = DRW_shader_create(datatoc_object_particle_prim_vert_glsl,
- NULL,
- datatoc_gpu_shader_flat_color_frag_glsl,
- "#define USE_AXIS\n");
-
- sh_data->part_dot = DRW_shader_create(
- datatoc_object_particle_dot_vert_glsl, NULL, datatoc_object_particle_dot_frag_glsl, NULL);
+ sh_data->part_prim = DRW_shader_create_with_lib(datatoc_object_particle_prim_vert_glsl,
+ NULL,
+ datatoc_gpu_shader_flat_color_frag_glsl,
+ datatoc_common_view_lib_glsl,
+ NULL);
+
+ sh_data->part_axis = DRW_shader_create_with_lib(datatoc_object_particle_prim_vert_glsl,
+ NULL,
+ datatoc_gpu_shader_flat_color_frag_glsl,
+ datatoc_common_view_lib_glsl,
+ "#define USE_AXIS\n");
+
+ sh_data->part_dot = DRW_shader_create_with_lib(datatoc_object_particle_dot_vert_glsl,
+ NULL,
+ datatoc_object_particle_dot_frag_glsl,
+ datatoc_common_view_lib_glsl,
+ NULL);
/* Lightprobes */
sh_data->lightprobe_grid = DRW_shader_create(datatoc_object_lightprobe_grid_vert_glsl,
@@ -503,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;
@@ -518,13 +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);
-
- /* Setup camera pos */
- copy_v3_v3(e_data.camera_pos, invviewmat[3]);
+ 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) {
@@ -536,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 */
}
@@ -597,8 +622,9 @@ static void OBJECT_engine_init(void *vedata)
if (((rv3d->view == RV3D_VIEW_USER) || (rv3d->persp != RV3D_ORTHO)) && show_axis_z) {
e_data.zpos_flag = SHOW_AXIS_Z;
- float zvec[4] = {0.0f, 0.0f, -1.0f, 0.0f};
- mul_m4_v4(invviewmat, zvec);
+ float zvec[3], campos[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])) {
@@ -612,7 +638,7 @@ static void OBJECT_engine_init(void *vedata)
/* Persp : If camera is below floor plane, we switch clipping
* Ortho : If eye vector is looking up, we switch clipping */
- if (((winmat[3][3] == 0.0f) && (e_data.camera_pos[2] > 0.0f)) ||
+ if (((winmat[3][3] == 0.0f) && (campos[2] > 0.0f)) ||
((winmat[3][3] != 0.0f) && (zvec[2] < 0.0f))) {
e_data.zpos_flag |= CLIP_ZPOS;
e_data.zneg_flag |= CLIP_ZNEG;
@@ -661,7 +687,6 @@ static void OBJECT_engine_init(void *vedata)
static void OBJECT_engine_free(void)
{
- MEM_SAFE_FREE(e_data.particle_format);
MEM_SAFE_FREE(e_data.empty_image_format);
MEM_SAFE_FREE(e_data.empty_image_wire_format);
@@ -771,8 +796,8 @@ static int *shgroup_theme_id_to_outline_counter(OBJECT_StorageList *stl,
}
}
-static DRWShadingGroup *shgroup_theme_id_to_probe_planar_outline_shgrp(OBJECT_StorageList *stl,
- int theme_id)
+static DRWCallBuffer *buffer_theme_id_to_probe_planar_outline_shgrp(OBJECT_StorageList *stl,
+ int theme_id)
{
/* does not increment counter */
switch (theme_id) {
@@ -786,9 +811,9 @@ static DRWShadingGroup *shgroup_theme_id_to_probe_planar_outline_shgrp(OBJECT_St
}
}
-static DRWShadingGroup *shgroup_theme_id_to_probe_cube_outline_shgrp(OBJECT_StorageList *stl,
- int theme_id,
- const int base_flag)
+static DRWCallBuffer *buffer_theme_id_to_probe_cube_outline_shgrp(OBJECT_StorageList *stl,
+ int theme_id,
+ const int base_flag)
{
/* does not increment counter */
if (UNLIKELY(base_flag & BASE_FROM_DUPLI)) {
@@ -961,7 +986,7 @@ static void DRW_shgroup_empty_image(OBJECT_Shaders *sh_data,
GPUTexture *tex = NULL;
if (ob->data != NULL) {
- tex = GPU_texture_from_blender(ob->data, ob->iuser, GL_TEXTURE_2D, false);
+ tex = GPU_texture_from_blender(ob->data, ob->iuser, GL_TEXTURE_2D);
if (tex) {
size[0] = GPU_texture_width(tex);
size[1] = GPU_texture_height(tex);
@@ -985,9 +1010,7 @@ static void DRW_shgroup_empty_image(OBJECT_Shaders *sh_data,
{
DRWShadingGroup *grp = DRW_shgroup_create(sh_data->object_empty_image_wire, sgl->non_meshes);
- /* TODO(fclem) implement DRW_shgroup_uniform_vec2_copy */
- DRW_shgroup_uniform_float_copy(grp, "aspectX", image_aspect[0]);
- DRW_shgroup_uniform_float_copy(grp, "aspectY", image_aspect[1]);
+ DRW_shgroup_uniform_vec2_copy(grp, "aspect", image_aspect);
DRW_shgroup_uniform_int_copy(grp, "depthMode", depth_mode);
DRW_shgroup_uniform_float(grp, "size", &ob->empty_drawsize, 1);
DRW_shgroup_uniform_vec2(grp, "offset", ob->ima_ofs, 1);
@@ -995,7 +1018,7 @@ static void DRW_shgroup_empty_image(OBJECT_Shaders *sh_data,
if (sh_cfg == GPU_SHADER_CFG_CLIPPED) {
DRW_shgroup_world_clip_planes_from_rv3d(grp, DRW_context_state_get()->rv3d);
}
- DRW_shgroup_call_add(grp, DRW_cache_image_plane_wire_get(), ob->obmat);
+ DRW_shgroup_call(grp, DRW_cache_image_plane_wire_get(), ob->obmat);
}
if (!BKE_object_empty_image_data_is_visible_in_view3d(ob, rv3d)) {
@@ -1005,8 +1028,7 @@ static void DRW_shgroup_empty_image(OBJECT_Shaders *sh_data,
if (tex && ((ob->color[3] > 0.0f) || !use_alpha_blend)) {
DRWShadingGroup *grp = DRW_shgroup_create(
sh_data->object_empty_image, (use_alpha_blend) ? sgl->image_empties : sgl->non_meshes);
- DRW_shgroup_uniform_float_copy(grp, "aspectX", image_aspect[0]);
- DRW_shgroup_uniform_float_copy(grp, "aspectY", image_aspect[1]);
+ DRW_shgroup_uniform_vec2_copy(grp, "aspect", image_aspect);
DRW_shgroup_uniform_int_copy(grp, "depthMode", depth_mode);
DRW_shgroup_uniform_float(grp, "size", &ob->empty_drawsize, 1);
DRW_shgroup_uniform_vec2(grp, "offset", ob->ima_ofs, 1);
@@ -1016,7 +1038,7 @@ static void DRW_shgroup_empty_image(OBJECT_Shaders *sh_data,
if (sh_cfg == GPU_SHADER_CFG_CLIPPED) {
DRW_shgroup_world_clip_planes_from_rv3d(grp, DRW_context_state_get()->rv3d);
}
- DRW_shgroup_call_add(grp, DRW_cache_image_plane_get(), ob->obmat);
+ DRW_shgroup_call(grp, DRW_cache_image_plane_get(), ob->obmat);
}
}
@@ -1048,8 +1070,7 @@ static void OBJECT_cache_init(void *vedata)
g_data->custom_shapes = BLI_ghash_ptr_new(__func__);
{
- DRWState state = DRW_STATE_WRITE_COLOR | DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_LESS_EQUAL |
- DRW_STATE_WIRE;
+ DRWState state = DRW_STATE_WRITE_COLOR | DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_LESS_EQUAL;
psl->outlines = DRW_pass_create("Outlines Depth Pass", state);
GPUShader *sh = sh_data->outline_prepass;
@@ -1074,30 +1095,29 @@ static void OBJECT_cache_init(void *vedata)
}
{
- DRWState state = DRW_STATE_WRITE_COLOR | DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_LESS_EQUAL |
- DRW_STATE_POINT;
+ DRWState state = DRW_STATE_WRITE_COLOR | DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_LESS_EQUAL;
DRWPass *pass = psl->lightprobes = DRW_pass_create("Object Probe Pass", state);
struct GPUBatch *sphere = DRW_cache_sphere_get();
struct GPUBatch *quad = DRW_cache_quad_get();
/* Cubemap */
- g_data->lightprobes_cube_select = shgroup_instance_outline(
+ g_data->lightprobes_cube_select = buffer_instance_outline(
pass, sphere, &g_data->id_ofs_prb_select);
- g_data->lightprobes_cube_select_dupli = shgroup_instance_outline(
+ g_data->lightprobes_cube_select_dupli = buffer_instance_outline(
pass, sphere, &g_data->id_ofs_prb_select_dupli);
- g_data->lightprobes_cube_active = shgroup_instance_outline(
+ g_data->lightprobes_cube_active = buffer_instance_outline(
pass, sphere, &g_data->id_ofs_prb_active);
- g_data->lightprobes_cube_transform = shgroup_instance_outline(
+ g_data->lightprobes_cube_transform = buffer_instance_outline(
pass, sphere, &g_data->id_ofs_prb_transform);
/* Planar */
- g_data->lightprobes_planar_select = shgroup_instance_outline(
+ g_data->lightprobes_planar_select = buffer_instance_outline(
pass, quad, &g_data->id_ofs_prb_select);
- g_data->lightprobes_planar_select_dupli = shgroup_instance_outline(
+ g_data->lightprobes_planar_select_dupli = buffer_instance_outline(
pass, quad, &g_data->id_ofs_prb_select_dupli);
- g_data->lightprobes_planar_active = shgroup_instance_outline(
+ g_data->lightprobes_planar_active = buffer_instance_outline(
pass, quad, &g_data->id_ofs_prb_active);
- g_data->lightprobes_planar_transform = shgroup_instance_outline(
+ g_data->lightprobes_planar_transform = buffer_instance_outline(
pass, quad, &g_data->id_ofs_prb_transform);
g_data->id_ofs_prb_select = 0;
@@ -1123,7 +1143,7 @@ static void OBJECT_cache_init(void *vedata)
DRW_shgroup_uniform_block(grp, "globalsBlock", G_draw.block_ubo);
DRW_shgroup_uniform_float_copy(grp, "alphaOcclu", alphaOcclu);
DRW_shgroup_uniform_int(grp, "idOffsets", &stl->g_data->id_ofs_active, 4);
- DRW_shgroup_call_add(grp, quad, NULL);
+ DRW_shgroup_call(grp, quad, NULL);
/* This is the bleed pass if do_outline_expand is false. */
GPUShader *fade_sh = (do_large_expand) ? sh_data->outline_fade_large : sh_data->outline_fade;
@@ -1132,7 +1152,7 @@ static void OBJECT_cache_init(void *vedata)
grp = DRW_shgroup_create(fade_sh, psl->outlines_expand);
DRW_shgroup_uniform_texture_ref(grp, "outlineColor", &e_data.outlines_blur_tx);
DRW_shgroup_uniform_bool_copy(grp, "doExpand", do_outline_expand);
- DRW_shgroup_call_add(grp, quad, NULL);
+ DRW_shgroup_call(grp, quad, NULL);
psl->outlines_bleed = DRW_pass_create("Outlines Bleed Pass", state);
@@ -1140,7 +1160,7 @@ static void OBJECT_cache_init(void *vedata)
grp = DRW_shgroup_create(sh_data->outline_fade, psl->outlines_bleed);
DRW_shgroup_uniform_texture_ref(grp, "outlineColor", &e_data.outlines_color_tx);
DRW_shgroup_uniform_bool_copy(grp, "doExpand", false);
- DRW_shgroup_call_add(grp, quad, NULL);
+ DRW_shgroup_call(grp, quad, NULL);
}
}
@@ -1155,7 +1175,7 @@ static void OBJECT_cache_init(void *vedata)
DRWShadingGroup *grp = DRW_shgroup_create(sh_data->outline_resolve_aa, psl->outlines_resolve);
DRW_shgroup_uniform_texture_ref(grp, "outlineBluredColor", outline_tx);
DRW_shgroup_uniform_vec2(grp, "rcpDimensions", e_data.inv_viewport_size, 1);
- DRW_shgroup_call_add(grp, quad, NULL);
+ DRW_shgroup_call(grp, quad, NULL);
}
{
@@ -1172,28 +1192,27 @@ static void OBJECT_cache_init(void *vedata)
DRWShadingGroup *grp = DRW_shgroup_create(sh_data->grid, psl->grid);
DRW_shgroup_uniform_int(grp, "gridFlag", &e_data.zneg_flag, 1);
DRW_shgroup_uniform_vec3(grp, "planeAxes", e_data.zplane_axes, 1);
- DRW_shgroup_uniform_vec3(grp, "cameraPos", e_data.camera_pos, 1);
DRW_shgroup_uniform_vec4(grp, "gridSettings", e_data.grid_settings, 1);
DRW_shgroup_uniform_float_copy(grp, "lineKernel", grid_line_size);
DRW_shgroup_uniform_float_copy(grp, "meshSize", e_data.grid_mesh_size);
DRW_shgroup_uniform_float(grp, "gridOneOverLogSubdiv", &e_data.grid_settings[4], 1);
DRW_shgroup_uniform_block(grp, "globalsBlock", G_draw.block_ubo);
DRW_shgroup_uniform_texture_ref(grp, "depthBuffer", &dtxl->depth);
- DRW_shgroup_call_add(grp, geom, mat);
+ DRW_shgroup_call(grp, geom, mat);
grp = DRW_shgroup_create(sh_data->grid, psl->grid);
DRW_shgroup_uniform_int(grp, "gridFlag", &e_data.grid_flag, 1);
DRW_shgroup_uniform_vec3(grp, "planeAxes", e_data.grid_axes, 1);
DRW_shgroup_uniform_block(grp, "globalsBlock", G_draw.block_ubo);
DRW_shgroup_uniform_texture_ref(grp, "depthBuffer", &dtxl->depth);
- DRW_shgroup_call_add(grp, geom, mat);
+ DRW_shgroup_call(grp, geom, mat);
grp = DRW_shgroup_create(sh_data->grid, psl->grid);
DRW_shgroup_uniform_int(grp, "gridFlag", &e_data.zpos_flag, 1);
DRW_shgroup_uniform_vec3(grp, "planeAxes", e_data.zplane_axes, 1);
DRW_shgroup_uniform_block(grp, "globalsBlock", G_draw.block_ubo);
DRW_shgroup_uniform_texture_ref(grp, "depthBuffer", &dtxl->depth);
- DRW_shgroup_call_add(grp, geom, mat);
+ DRW_shgroup_call(grp, geom, mat);
}
for (int i = 0; i < 2; ++i) {
@@ -1215,8 +1234,7 @@ static void OBJECT_cache_init(void *vedata)
sgl->bone_envelope = psl->bone_envelope[i] = DRW_pass_create("Bone Envelope Outline Pass",
state);
- state = DRW_STATE_WRITE_COLOR | DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_LESS_EQUAL |
- DRW_STATE_WIRE;
+ state = DRW_STATE_WRITE_COLOR | DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_LESS_EQUAL;
sgl->bone_axes = psl->bone_axes[i] = DRW_pass_create("Bone Axes Pass", state);
}
@@ -1228,121 +1246,119 @@ static void OBJECT_cache_init(void *vedata)
struct GPUShader *sh;
DRWState state = DRW_STATE_WRITE_COLOR | DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_LESS_EQUAL |
- DRW_STATE_BLEND | DRW_STATE_POINT | DRW_STATE_WIRE;
+ DRW_STATE_BLEND;
sgl->non_meshes = psl->non_meshes[i] = DRW_pass_create("Non Meshes Pass", state);
- state = DRW_STATE_WRITE_COLOR | DRW_STATE_DEPTH_LESS_EQUAL | DRW_STATE_BLEND | DRW_STATE_WIRE;
+ state = DRW_STATE_WRITE_COLOR | DRW_STATE_DEPTH_LESS_EQUAL | DRW_STATE_BLEND;
sgl->image_empties = psl->image_empties[i] = DRW_pass_create("Image Empties", state);
/* Empties */
geom = DRW_cache_plain_axes_get();
- sgl->plain_axes = shgroup_instance(sgl->non_meshes, geom, draw_ctx->sh_cfg);
+ sgl->plain_axes = buffer_instance(sgl->non_meshes, geom, draw_ctx->sh_cfg);
geom = DRW_cache_empty_cube_get();
- sgl->cube = shgroup_instance(sgl->non_meshes, geom, draw_ctx->sh_cfg);
+ sgl->cube = buffer_instance(sgl->non_meshes, geom, draw_ctx->sh_cfg);
geom = DRW_cache_circle_get();
- sgl->circle = shgroup_instance(sgl->non_meshes, geom, draw_ctx->sh_cfg);
+ sgl->circle = buffer_instance(sgl->non_meshes, geom, draw_ctx->sh_cfg);
geom = DRW_cache_empty_sphere_get();
- sgl->sphere = shgroup_instance(sgl->non_meshes, geom, draw_ctx->sh_cfg);
+ sgl->sphere = buffer_instance(sgl->non_meshes, geom, draw_ctx->sh_cfg);
geom = DRW_cache_sphere_get();
- sgl->sphere_solid = shgroup_instance_solid(sgl->non_meshes, geom);
+ sgl->sphere_solid = buffer_instance_solid(sgl->non_meshes, geom);
geom = DRW_cache_empty_cylinder_get();
- sgl->cylinder = shgroup_instance(sgl->non_meshes, geom, draw_ctx->sh_cfg);
+ sgl->cylinder = buffer_instance(sgl->non_meshes, geom, draw_ctx->sh_cfg);
geom = DRW_cache_empty_capsule_cap_get();
- sgl->capsule_cap = shgroup_instance(sgl->non_meshes, geom, draw_ctx->sh_cfg);
+ sgl->capsule_cap = buffer_instance(sgl->non_meshes, geom, draw_ctx->sh_cfg);
geom = DRW_cache_empty_capsule_body_get();
- sgl->capsule_body = shgroup_instance(sgl->non_meshes, geom, draw_ctx->sh_cfg);
+ sgl->capsule_body = buffer_instance(sgl->non_meshes, geom, draw_ctx->sh_cfg);
geom = DRW_cache_empty_cone_get();
- sgl->cone = shgroup_instance(sgl->non_meshes, geom, draw_ctx->sh_cfg);
+ sgl->cone = buffer_instance(sgl->non_meshes, geom, draw_ctx->sh_cfg);
geom = DRW_cache_single_arrow_get();
- sgl->single_arrow = shgroup_instance(sgl->non_meshes, geom, draw_ctx->sh_cfg);
+ sgl->single_arrow = buffer_instance(sgl->non_meshes, geom, draw_ctx->sh_cfg);
geom = DRW_cache_single_line_get();
- sgl->single_arrow_line = shgroup_instance(sgl->non_meshes, geom, draw_ctx->sh_cfg);
+ sgl->single_arrow_line = buffer_instance(sgl->non_meshes, geom, draw_ctx->sh_cfg);
geom = DRW_cache_bone_arrows_get();
- sgl->empty_axes = shgroup_instance_empty_axes(sgl->non_meshes, geom, draw_ctx->sh_cfg);
+ sgl->empty_axes = buffer_instance_empty_axes(sgl->non_meshes, geom, draw_ctx->sh_cfg);
/* Force Field */
geom = DRW_cache_field_wind_get();
- sgl->field_wind = shgroup_instance_scaled(sgl->non_meshes, geom, draw_ctx->sh_cfg);
+ sgl->field_wind = buffer_instance_scaled(sgl->non_meshes, geom, draw_ctx->sh_cfg);
geom = DRW_cache_field_force_get();
- sgl->field_force = shgroup_instance_screen_aligned(sgl->non_meshes, geom, draw_ctx->sh_cfg);
+ sgl->field_force = buffer_instance_screen_aligned(sgl->non_meshes, geom, draw_ctx->sh_cfg);
geom = DRW_cache_field_vortex_get();
- sgl->field_vortex = shgroup_instance_scaled(sgl->non_meshes, geom, draw_ctx->sh_cfg);
+ sgl->field_vortex = buffer_instance_scaled(sgl->non_meshes, geom, draw_ctx->sh_cfg);
geom = DRW_cache_screenspace_circle_get();
- sgl->field_curve_sta = shgroup_instance_screen_aligned(
- sgl->non_meshes, geom, draw_ctx->sh_cfg);
+ sgl->field_curve_sta = buffer_instance_screen_aligned(sgl->non_meshes, geom, draw_ctx->sh_cfg);
/* Grease Pencil */
geom = DRW_cache_gpencil_axes_get();
- sgl->gpencil_axes = shgroup_instance(sgl->non_meshes, geom, draw_ctx->sh_cfg);
+ sgl->gpencil_axes = buffer_instance(sgl->non_meshes, geom, draw_ctx->sh_cfg);
/* Speaker */
geom = DRW_cache_speaker_get();
- sgl->speaker = shgroup_instance(sgl->non_meshes, geom, draw_ctx->sh_cfg);
+ sgl->speaker = buffer_instance(sgl->non_meshes, geom, draw_ctx->sh_cfg);
/* Probe */
static float probeSize = 14.0f;
geom = DRW_cache_lightprobe_cube_get();
- sgl->probe_cube = shgroup_instance_screenspace(
+ sgl->probe_cube = buffer_instance_screenspace(
sgl->non_meshes, geom, &probeSize, draw_ctx->sh_cfg);
geom = DRW_cache_lightprobe_grid_get();
- sgl->probe_grid = shgroup_instance_screenspace(
+ sgl->probe_grid = buffer_instance_screenspace(
sgl->non_meshes, geom, &probeSize, draw_ctx->sh_cfg);
static float probePlanarSize = 20.0f;
geom = DRW_cache_lightprobe_planar_get();
- sgl->probe_planar = shgroup_instance_screenspace(
+ sgl->probe_planar = buffer_instance_screenspace(
sgl->non_meshes, geom, &probePlanarSize, draw_ctx->sh_cfg);
/* Camera */
geom = DRW_cache_camera_get();
- sgl->camera = shgroup_camera_instance(sgl->non_meshes, geom, draw_ctx->sh_cfg);
+ sgl->camera = buffer_camera_instance(sgl->non_meshes, geom, draw_ctx->sh_cfg);
geom = DRW_cache_camera_frame_get();
- sgl->camera_frame = shgroup_camera_instance(sgl->non_meshes, geom, draw_ctx->sh_cfg);
+ sgl->camera_frame = buffer_camera_instance(sgl->non_meshes, geom, draw_ctx->sh_cfg);
geom = DRW_cache_camera_tria_get();
- sgl->camera_tria = shgroup_camera_instance(sgl->non_meshes, geom, draw_ctx->sh_cfg);
+ sgl->camera_tria = buffer_camera_instance(sgl->non_meshes, geom, draw_ctx->sh_cfg);
geom = DRW_cache_plain_axes_get();
- sgl->camera_focus = shgroup_instance(sgl->non_meshes, geom, draw_ctx->sh_cfg);
+ sgl->camera_focus = buffer_instance(sgl->non_meshes, geom, draw_ctx->sh_cfg);
geom = DRW_cache_single_line_get();
- sgl->camera_clip = shgroup_distance_lines_instance(sgl->non_meshes, geom, draw_ctx->sh_cfg);
- sgl->camera_mist = shgroup_distance_lines_instance(sgl->non_meshes, geom, draw_ctx->sh_cfg);
+ sgl->camera_clip = buffer_distance_lines_instance(sgl->non_meshes, geom, draw_ctx->sh_cfg);
+ sgl->camera_mist = buffer_distance_lines_instance(sgl->non_meshes, geom, draw_ctx->sh_cfg);
geom = DRW_cache_single_line_endpoints_get();
- sgl->camera_clip_points = shgroup_distance_lines_instance(
+ sgl->camera_clip_points = buffer_distance_lines_instance(
sgl->non_meshes, geom, draw_ctx->sh_cfg);
- sgl->camera_mist_points = shgroup_distance_lines_instance(
+ sgl->camera_mist_points = buffer_distance_lines_instance(
sgl->non_meshes, geom, draw_ctx->sh_cfg);
geom = DRW_cache_quad_wires_get();
- sgl->camera_stereo_plane_wires = shgroup_instance(sgl->non_meshes, geom, draw_ctx->sh_cfg);
- DRW_shgroup_state_enable(sgl->camera_stereo_plane_wires, DRW_STATE_WIRE);
+ sgl->camera_stereo_plane_wires = buffer_instance(sgl->non_meshes, geom, draw_ctx->sh_cfg);
geom = DRW_cache_empty_cube_get();
- sgl->camera_stereo_volume_wires = shgroup_instance(sgl->non_meshes, geom, draw_ctx->sh_cfg);
+ sgl->camera_stereo_volume_wires = buffer_instance(sgl->non_meshes, geom, draw_ctx->sh_cfg);
BLI_listbase_clear(&sgl->camera_path);
/* Texture Space */
geom = DRW_cache_empty_cube_get();
- sgl->texspace = shgroup_instance(sgl->non_meshes, geom, draw_ctx->sh_cfg);
+ sgl->texspace = buffer_instance(sgl->non_meshes, geom, draw_ctx->sh_cfg);
/* Wires (for loose edges) */
sh = GPU_shader_get_builtin_shader_with_config(GPU_SHADER_3D_UNIFORM_COLOR, draw_ctx->sh_cfg);
@@ -1374,123 +1390,137 @@ static void OBJECT_cache_init(void *vedata)
DRW_shgroup_state_disable(sgl->points_dupli_select, DRW_STATE_BLEND);
/* Metaballs Handles */
- sgl->mball_handle = shgroup_instance_mball_handles(sgl->non_meshes, draw_ctx->sh_cfg);
+ sgl->mball_handle = buffer_instance_mball_handles(sgl->non_meshes, draw_ctx->sh_cfg);
/* Lights */
/* TODO
* for now we create multiple times the same VBO with only light center coordinates
* but ideally we would only create it once */
- /* start with buflimit because we don't want stipples */
- geom = DRW_cache_single_line_get();
- sgl->light_buflimit = shgroup_distance_lines_instance(sgl->non_meshes, geom, draw_ctx->sh_cfg);
+ sh = GPU_shader_get_builtin_shader_with_config(
+ GPU_SHADER_3D_POINT_UNIFORM_SIZE_UNIFORM_COLOR_AA, draw_ctx->sh_cfg);
+
+ DRWShadingGroup *grp = DRW_shgroup_create(sh, sgl->non_meshes);
+ 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);
+ }
- sgl->light_center = shgroup_dynpoints_uniform_color(
- sgl->non_meshes, gb->colorLightNoAlpha, &gb->sizeLightCenter, draw_ctx->sh_cfg);
+ sgl->light_center = buffer_dynpoints_uniform_color(grp);
+
+ geom = DRW_cache_single_line_get();
+ sgl->light_buflimit = buffer_distance_lines_instance(sgl->non_meshes, geom, draw_ctx->sh_cfg);
geom = DRW_cache_light_get();
- sgl->light_circle = shgroup_instance_screenspace(
+ sgl->light_circle = buffer_instance_screenspace(
sgl->non_meshes, geom, &gb->sizeLightCircle, draw_ctx->sh_cfg);
geom = DRW_cache_light_shadows_get();
- sgl->light_circle_shadow = shgroup_instance_screenspace(
+ sgl->light_circle_shadow = buffer_instance_screenspace(
sgl->non_meshes, geom, &gb->sizeLightCircleShadow, draw_ctx->sh_cfg);
geom = DRW_cache_light_sunrays_get();
- sgl->light_sunrays = shgroup_instance_screenspace(
+ sgl->light_sunrays = buffer_instance_screenspace(
sgl->non_meshes, geom, &gb->sizeLightCircle, draw_ctx->sh_cfg);
- sgl->light_groundline = shgroup_groundlines_uniform_color(
+ sgl->light_groundline = buffer_groundlines_uniform_color(
sgl->non_meshes, gb->colorLight, draw_ctx->sh_cfg);
- sgl->light_groundpoint = shgroup_groundpoints_uniform_color(
+ sgl->light_groundpoint = buffer_groundpoints_uniform_color(
sgl->non_meshes, gb->colorLight, draw_ctx->sh_cfg);
geom = DRW_cache_screenspace_circle_get();
- sgl->light_area_sphere = shgroup_instance_screen_aligned(
+ sgl->light_area_sphere = buffer_instance_screen_aligned(
sgl->non_meshes, geom, draw_ctx->sh_cfg);
geom = DRW_cache_light_area_square_get();
- sgl->light_area_square = shgroup_instance(sgl->non_meshes, geom, draw_ctx->sh_cfg);
+ sgl->light_area_square = buffer_instance(sgl->non_meshes, geom, draw_ctx->sh_cfg);
geom = DRW_cache_light_area_disk_get();
- sgl->light_area_disk = shgroup_instance(sgl->non_meshes, geom, draw_ctx->sh_cfg);
+ sgl->light_area_disk = buffer_instance(sgl->non_meshes, geom, draw_ctx->sh_cfg);
geom = DRW_cache_light_hemi_get();
- sgl->light_hemi = shgroup_instance(sgl->non_meshes, geom, draw_ctx->sh_cfg);
+ sgl->light_hemi = buffer_instance(sgl->non_meshes, geom, draw_ctx->sh_cfg);
geom = DRW_cache_single_line_get();
- sgl->light_distance = shgroup_distance_lines_instance(sgl->non_meshes, geom, draw_ctx->sh_cfg);
+ sgl->light_distance = buffer_distance_lines_instance(sgl->non_meshes, geom, draw_ctx->sh_cfg);
geom = DRW_cache_single_line_endpoints_get();
- sgl->light_buflimit_points = shgroup_distance_lines_instance(
+ sgl->light_buflimit_points = buffer_distance_lines_instance(
sgl->non_meshes, geom, draw_ctx->sh_cfg);
geom = DRW_cache_light_spot_get();
- sgl->light_spot_cone = shgroup_spot_instance(sgl->non_meshes, geom, draw_ctx->sh_cfg);
+ sgl->light_spot_cone = buffer_spot_instance(sgl->non_meshes, geom, draw_ctx->sh_cfg);
geom = DRW_cache_circle_get();
- sgl->light_spot_blend = shgroup_instance(sgl->non_meshes, geom, draw_ctx->sh_cfg);
+ sgl->light_spot_blend = buffer_instance(sgl->non_meshes, geom, draw_ctx->sh_cfg);
geom = DRW_cache_light_spot_square_get();
- sgl->light_spot_pyramid = shgroup_instance(sgl->non_meshes, geom, draw_ctx->sh_cfg);
+ sgl->light_spot_pyramid = buffer_instance(sgl->non_meshes, geom, draw_ctx->sh_cfg);
geom = DRW_cache_square_get();
- sgl->light_spot_blend_rect = shgroup_instance(sgl->non_meshes, geom, draw_ctx->sh_cfg);
+ sgl->light_spot_blend_rect = buffer_instance(sgl->non_meshes, geom, draw_ctx->sh_cfg);
/* -------- STIPPLES ------- */
/* Relationship Lines */
- sgl->relationship_lines = shgroup_dynlines_dashed_uniform_color(
+ sgl->relationship_lines = buffer_dynlines_dashed_uniform_color(
sgl->non_meshes, gb->colorWire, draw_ctx->sh_cfg);
- sgl->constraint_lines = shgroup_dynlines_dashed_uniform_color(
+ sgl->constraint_lines = buffer_dynlines_dashed_uniform_color(
sgl->non_meshes, gb->colorGridAxisZ, draw_ctx->sh_cfg);
/* Force Field Curve Guide End (here because of stipple) */
/* TODO port to shader stipple */
geom = DRW_cache_screenspace_circle_get();
- sgl->field_curve_end = shgroup_instance_screen_aligned(
- sgl->non_meshes, geom, draw_ctx->sh_cfg);
+ sgl->field_curve_end = buffer_instance_screen_aligned(sgl->non_meshes, geom, draw_ctx->sh_cfg);
/* Force Field Limits */
/* TODO port to shader stipple */
geom = DRW_cache_field_tube_limit_get();
- sgl->field_tube_limit = shgroup_instance_scaled(sgl->non_meshes, geom, draw_ctx->sh_cfg);
+ sgl->field_tube_limit = buffer_instance_scaled(sgl->non_meshes, geom, draw_ctx->sh_cfg);
/* TODO port to shader stipple */
geom = DRW_cache_field_cone_limit_get();
- sgl->field_cone_limit = shgroup_instance_scaled(sgl->non_meshes, geom, draw_ctx->sh_cfg);
+ sgl->field_cone_limit = buffer_instance_scaled(sgl->non_meshes, geom, draw_ctx->sh_cfg);
/* Transparent Shapes */
state = DRW_STATE_WRITE_COLOR | DRW_STATE_DEPTH_LESS_EQUAL | DRW_STATE_BLEND |
DRW_STATE_CULL_FRONT;
sgl->transp_shapes = psl->transp_shapes[i] = DRW_pass_create("Transparent Shapes", state);
+ sh = GPU_shader_get_builtin_shader_with_config(
+ GPU_SHADER_INSTANCE_VARIYING_COLOR_VARIYING_SIZE, draw_ctx->sh_cfg);
+
+ 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);
+ }
+
+ DRWShadingGroup *grp_cull_back = DRW_shgroup_create_sub(grp_transp);
+ DRW_shgroup_state_disable(grp_cull_back, DRW_STATE_CULL_FRONT);
+ DRW_shgroup_state_enable(grp_cull_back, DRW_STATE_CULL_BACK);
+
+ DRWShadingGroup *grp_cull_none = DRW_shgroup_create_sub(grp_transp);
+ DRW_shgroup_state_disable(grp_cull_none, DRW_STATE_CULL_FRONT);
+
/* Spot cones */
geom = DRW_cache_light_spot_volume_get();
- sgl->light_spot_volume = shgroup_instance_alpha(sgl->transp_shapes, geom, draw_ctx->sh_cfg);
+ sgl->light_spot_volume = buffer_instance_alpha(grp_transp, geom);
geom = DRW_cache_light_spot_square_volume_get();
- sgl->light_spot_volume_rect = shgroup_instance_alpha(
- sgl->transp_shapes, geom, draw_ctx->sh_cfg);
+ sgl->light_spot_volume_rect = buffer_instance_alpha(grp_transp, geom);
geom = DRW_cache_light_spot_volume_get();
- sgl->light_spot_volume_outside = shgroup_instance_alpha(
- sgl->transp_shapes, geom, draw_ctx->sh_cfg);
- DRW_shgroup_state_disable(sgl->light_spot_volume_outside, DRW_STATE_CULL_FRONT);
- DRW_shgroup_state_enable(sgl->light_spot_volume_outside, DRW_STATE_CULL_BACK);
+ sgl->light_spot_volume_outside = buffer_instance_alpha(grp_cull_back, geom);
geom = DRW_cache_light_spot_square_volume_get();
- sgl->light_spot_volume_rect_outside = shgroup_instance_alpha(
- sgl->transp_shapes, geom, draw_ctx->sh_cfg);
- DRW_shgroup_state_disable(sgl->light_spot_volume_rect_outside, DRW_STATE_CULL_FRONT);
- DRW_shgroup_state_enable(sgl->light_spot_volume_rect_outside, DRW_STATE_CULL_BACK);
+ sgl->light_spot_volume_rect_outside = buffer_instance_alpha(grp_cull_back, geom);
/* Camera stereo volumes */
geom = DRW_cache_cube_get();
- sgl->camera_stereo_volume = shgroup_instance_alpha(sgl->transp_shapes, geom, draw_ctx->sh_cfg);
+ sgl->camera_stereo_volume = buffer_instance_alpha(grp_transp, geom);
geom = DRW_cache_quad_get();
- sgl->camera_stereo_plane = shgroup_instance_alpha(sgl->transp_shapes, geom, draw_ctx->sh_cfg);
- DRW_shgroup_state_disable(sgl->camera_stereo_plane, DRW_STATE_CULL_FRONT);
+ sgl->camera_stereo_plane = buffer_instance_alpha(grp_cull_none, geom);
}
{
@@ -1498,7 +1528,7 @@ static void OBJECT_cache_init(void *vedata)
DRWShadingGroup *grp;
static float outlineWidth, size;
- DRWState state = DRW_STATE_WRITE_COLOR | DRW_STATE_BLEND | DRW_STATE_POINT;
+ DRWState state = DRW_STATE_WRITE_COLOR | DRW_STATE_BLEND;
psl->ob_center = DRW_pass_create("Obj Center Pass", state);
outlineWidth = 1.0f * U.pixelsize;
@@ -1508,7 +1538,7 @@ static void OBJECT_cache_init(void *vedata)
GPU_SHADER_3D_POINT_UNIFORM_SIZE_UNIFORM_COLOR_OUTLINE_AA, draw_ctx->sh_cfg);
/* Active */
- grp = DRW_shgroup_point_batch_create(sh, psl->ob_center);
+ grp = DRW_shgroup_create(sh, psl->ob_center);
DRW_shgroup_uniform_float(grp, "size", &size, 1);
DRW_shgroup_uniform_float(grp, "outlineWidth", &outlineWidth, 1);
DRW_shgroup_uniform_vec4(grp, "color", gb->colorActive, 1);
@@ -1516,47 +1546,35 @@ static void OBJECT_cache_init(void *vedata)
if (draw_ctx->sh_cfg == GPU_SHADER_CFG_CLIPPED) {
DRW_shgroup_world_clip_planes_from_rv3d(grp, draw_ctx->rv3d);
}
- stl->g_data->center_active = grp;
+ /* TODO find better name. */
+ stl->g_data->center_active = buffer_dynpoints_uniform_color(grp);
/* Select */
- grp = DRW_shgroup_point_batch_create(sh, psl->ob_center);
+ grp = DRW_shgroup_create_sub(grp);
DRW_shgroup_uniform_vec4(grp, "color", gb->colorSelect, 1);
- if (draw_ctx->sh_cfg == GPU_SHADER_CFG_CLIPPED) {
- DRW_shgroup_world_clip_planes_from_rv3d(grp, draw_ctx->rv3d);
- }
- stl->g_data->center_selected = grp;
+ stl->g_data->center_selected = buffer_dynpoints_uniform_color(grp);
/* Deselect */
- grp = DRW_shgroup_point_batch_create(sh, psl->ob_center);
+ grp = DRW_shgroup_create_sub(grp);
DRW_shgroup_uniform_vec4(grp, "color", gb->colorDeselect, 1);
- if (draw_ctx->sh_cfg == GPU_SHADER_CFG_CLIPPED) {
- DRW_shgroup_world_clip_planes_from_rv3d(grp, draw_ctx->rv3d);
- }
- stl->g_data->center_deselected = grp;
+ stl->g_data->center_deselected = buffer_dynpoints_uniform_color(grp);
/* Select (library) */
- grp = DRW_shgroup_point_batch_create(sh, psl->ob_center);
+ grp = DRW_shgroup_create_sub(grp);
DRW_shgroup_uniform_vec4(grp, "color", gb->colorLibrarySelect, 1);
- if (draw_ctx->sh_cfg == GPU_SHADER_CFG_CLIPPED) {
- DRW_shgroup_world_clip_planes_from_rv3d(grp, draw_ctx->rv3d);
- }
- stl->g_data->center_selected_lib = grp;
+ stl->g_data->center_selected_lib = buffer_dynpoints_uniform_color(grp);
/* Deselect (library) */
- grp = DRW_shgroup_point_batch_create(sh, psl->ob_center);
+ grp = DRW_shgroup_create_sub(grp);
DRW_shgroup_uniform_vec4(grp, "color", gb->colorLibrary, 1);
- if (draw_ctx->sh_cfg == GPU_SHADER_CFG_CLIPPED) {
- DRW_shgroup_world_clip_planes_from_rv3d(grp, draw_ctx->rv3d);
- }
- stl->g_data->center_deselected_lib = grp;
+ stl->g_data->center_deselected_lib = buffer_dynpoints_uniform_color(grp);
}
{
/* Particle Pass */
psl->particle = DRW_pass_create("Particle Pass",
DRW_STATE_WRITE_COLOR | DRW_STATE_WRITE_DEPTH |
- DRW_STATE_DEPTH_LESS_EQUAL | DRW_STATE_POINT |
- DRW_STATE_BLEND);
+ DRW_STATE_DEPTH_LESS_EQUAL | DRW_STATE_BLEND);
}
}
@@ -1593,7 +1611,7 @@ static void DRW_shgroup_mball_handles(OBJECT_ShadingGroupList *sgl,
draw_scale_xform[1][3] = world_pos[1];
draw_scale_xform[2][3] = world_pos[2];
- DRW_shgroup_call_dynamic_add(sgl->mball_handle, draw_scale_xform, &ml->rad, color);
+ DRW_buffer_add_entry(sgl->mball_handle, draw_scale_xform, &ml->rad, color);
}
}
@@ -1619,25 +1637,25 @@ static void DRW_shgroup_light(OBJECT_ShadingGroupList *sgl, Object *ob, ViewLaye
if ((ob->base_flag & (BASE_FROM_SET | BASE_FROM_DUPLI)) == 0) {
/* Don't draw the center if it's selected or active */
if (theme_id == TH_LIGHT) {
- DRW_shgroup_call_dynamic_add(sgl->light_center, ob->obmat[3]);
+ DRW_buffer_add_entry(sgl->light_center, ob->obmat[3]);
}
}
/* First circle */
- DRW_shgroup_call_dynamic_add(sgl->light_circle, ob->obmat[3], color);
+ DRW_buffer_add_entry(sgl->light_circle, ob->obmat[3], color);
/* draw dashed outer circle for shadow */
- DRW_shgroup_call_dynamic_add(sgl->light_circle_shadow, ob->obmat[3], color);
+ DRW_buffer_add_entry(sgl->light_circle_shadow, ob->obmat[3], color);
/* Distance */
if (ELEM(la->type, LA_SUN, LA_AREA)) {
- DRW_shgroup_call_dynamic_add(sgl->light_distance, color, &zero, &la->dist, ob->obmat);
+ DRW_buffer_add_entry(sgl->light_distance, color, &zero, &la->dist, ob->obmat);
}
copy_m4_m4(shapemat, ob->obmat);
if (la->type == LA_SUN) {
- DRW_shgroup_call_dynamic_add(sgl->light_sunrays, ob->obmat[3], color);
+ DRW_buffer_add_entry(sgl->light_sunrays, ob->obmat[3], color);
}
else if (la->type == LA_SPOT) {
float size[3], sizemat[4][4];
@@ -1659,42 +1677,39 @@ static void DRW_shgroup_light(OBJECT_ShadingGroupList *sgl, Object *ob, ViewLaye
mul_m4_m4m4(spotblendmat, shapemat, sizemat);
if (la->mode & LA_SQUARE) {
- DRW_shgroup_call_dynamic_add(sgl->light_spot_pyramid, color, &one, shapemat);
+ DRW_buffer_add_entry(sgl->light_spot_pyramid, color, &one, shapemat);
/* hide line if it is zero size or overlaps with outer border,
* previously it adjusted to always to show it but that seems
* confusing because it doesn't show the actual blend size */
if (blend != 0.0f && blend != 1.0f) {
- DRW_shgroup_call_dynamic_add(sgl->light_spot_blend_rect, color, &one, spotblendmat);
+ DRW_buffer_add_entry(sgl->light_spot_blend_rect, color, &one, spotblendmat);
}
if (la->mode & LA_SHOW_CONE) {
- DRW_shgroup_call_dynamic_add(sgl->light_spot_volume_rect, cone_inside, &one, shapemat);
- DRW_shgroup_call_dynamic_add(
- sgl->light_spot_volume_rect_outside, cone_outside, &one, shapemat);
+ DRW_buffer_add_entry(sgl->light_spot_volume_rect, cone_inside, &one, shapemat);
+ DRW_buffer_add_entry(sgl->light_spot_volume_rect_outside, cone_outside, &one, shapemat);
}
}
else {
- DRW_shgroup_call_dynamic_add(sgl->light_spot_cone, color, shapemat);
+ DRW_buffer_add_entry(sgl->light_spot_cone, color, shapemat);
/* hide line if it is zero size or overlaps with outer border,
* previously it adjusted to always to show it but that seems
* confusing because it doesn't show the actual blend size */
if (blend != 0.0f && blend != 1.0f) {
- DRW_shgroup_call_dynamic_add(sgl->light_spot_blend, color, &one, spotblendmat);
+ DRW_buffer_add_entry(sgl->light_spot_blend, color, &one, spotblendmat);
}
if (la->mode & LA_SHOW_CONE) {
- DRW_shgroup_call_dynamic_add(sgl->light_spot_volume, cone_inside, &one, shapemat);
- DRW_shgroup_call_dynamic_add(sgl->light_spot_volume_outside, cone_outside, &one, shapemat);
+ DRW_buffer_add_entry(sgl->light_spot_volume, cone_inside, &one, shapemat);
+ DRW_buffer_add_entry(sgl->light_spot_volume_outside, cone_outside, &one, shapemat);
}
}
- DRW_shgroup_call_dynamic_add(
- sgl->light_buflimit, color, &la->clipsta, &la->clipend, ob->obmat);
- DRW_shgroup_call_dynamic_add(
- sgl->light_buflimit_points, color, &la->clipsta, &la->clipend, ob->obmat);
+ DRW_buffer_add_entry(sgl->light_buflimit, color, &la->clipsta, &la->clipend, ob->obmat);
+ DRW_buffer_add_entry(sgl->light_buflimit_points, color, &la->clipsta, &la->clipend, ob->obmat);
}
else if (la->type == LA_AREA) {
float size[3] = {1.0f, 1.0f, 1.0f}, sizemat[4][4];
@@ -1706,10 +1721,10 @@ static void DRW_shgroup_light(OBJECT_ShadingGroupList *sgl, Object *ob, ViewLaye
}
if (ELEM(la->area_shape, LA_AREA_DISK, LA_AREA_ELLIPSE)) {
- DRW_shgroup_call_dynamic_add(sgl->light_area_disk, color, &la->area_size, shapemat);
+ DRW_buffer_add_entry(sgl->light_area_disk, color, &la->area_size, shapemat);
}
else {
- DRW_shgroup_call_dynamic_add(sgl->light_area_square, color, &la->area_size, shapemat);
+ DRW_buffer_add_entry(sgl->light_area_square, color, &la->area_size, shapemat);
}
}
@@ -1719,12 +1734,12 @@ static void DRW_shgroup_light(OBJECT_ShadingGroupList *sgl, Object *ob, ViewLaye
shapemat[0][1] = shapemat[0][2] = 0.0f;
shapemat[1][0] = shapemat[1][2] = 0.0f;
shapemat[2][0] = shapemat[2][1] = 0.0f;
- DRW_shgroup_call_dynamic_add(sgl->light_area_sphere, color, &la->area_size, shapemat);
+ DRW_buffer_add_entry(sgl->light_area_sphere, color, &la->area_size, shapemat);
}
/* Line and point going to the ground */
- DRW_shgroup_call_dynamic_add(sgl->light_groundline, ob->obmat[3]);
- DRW_shgroup_call_dynamic_add(sgl->light_groundpoint, ob->obmat[3]);
+ DRW_buffer_add_entry(sgl->light_groundline, ob->obmat[3]);
+ DRW_buffer_add_entry(sgl->light_groundpoint, ob->obmat[3]);
}
static GPUBatch *batch_camera_path_get(ListBase *camera_paths,
@@ -1820,19 +1835,19 @@ static void camera_view3d_stereoscopy_display_extra(OBJECT_ShadingGroupList *sgl
copy_v2_v2(drw_tria_dummy[eye][1], cam->runtime.drw_corners[eye][0]);
if (is_stereo3d_cameras) {
- DRW_shgroup_call_dynamic_add(sgl->camera_frame,
- color,
- cam->runtime.drw_corners[eye],
- &cam->runtime.drw_depth[eye],
- cam->runtime.drw_tria,
- obmat);
+ DRW_buffer_add_entry(sgl->camera_frame,
+ color,
+ cam->runtime.drw_corners[eye],
+ &cam->runtime.drw_depth[eye],
+ cam->runtime.drw_tria,
+ obmat);
- DRW_shgroup_call_dynamic_add(sgl->camera,
- color,
- cam->runtime.drw_corners[eye],
- &cam->runtime.drw_depth[eye],
- drw_tria_dummy[eye],
- obmat);
+ DRW_buffer_add_entry(sgl->camera,
+ color,
+ cam->runtime.drw_corners[eye],
+ &cam->runtime.drw_depth[eye],
+ drw_tria_dummy[eye],
+ obmat);
}
/* Connecting line. */
@@ -1841,8 +1856,8 @@ static void camera_view3d_stereoscopy_display_extra(OBJECT_ShadingGroupList *sgl
/* Draw connecting lines. */
if (is_stereo3d_cameras) {
- DRW_shgroup_call_dynamic_add(sgl->relationship_lines, origin[0]);
- DRW_shgroup_call_dynamic_add(sgl->relationship_lines, origin[1]);
+ DRW_buffer_add_entry(sgl->relationship_lines, origin[0]);
+ DRW_buffer_add_entry(sgl->relationship_lines, origin[1]);
}
/* Draw convergence plane. */
@@ -1879,9 +1894,9 @@ static void camera_view3d_stereoscopy_display_extra(OBJECT_ShadingGroupList *sgl
translate_m4(plane_mat, 2.0f * cam->shiftx, (width / height) * 2.0f * cam->shifty, 0.0f);
if (v3d->stereo3d_convergence_alpha > 0.0f) {
- DRW_shgroup_call_dynamic_add(sgl->camera_stereo_plane, color_plane[0], &one, plane_mat);
+ DRW_buffer_add_entry(sgl->camera_stereo_plane, color_plane[0], &one, plane_mat);
}
- DRW_shgroup_call_dynamic_add(sgl->camera_stereo_plane_wires, color_plane[1], &one, plane_mat);
+ DRW_buffer_add_entry(sgl->camera_stereo_plane_wires, color_plane[1], &one, plane_mat);
}
/* Draw convergence volume. */
@@ -1905,10 +1920,9 @@ static void camera_view3d_stereoscopy_display_extra(OBJECT_ShadingGroupList *sgl
invert_m4_m4(persinv, persmat);
if (v3d->stereo3d_volume_alpha > 0.0f) {
- DRW_shgroup_call_dynamic_add(sgl->camera_stereo_volume, color_volume[eye], &one, persinv);
+ DRW_buffer_add_entry(sgl->camera_stereo_volume, color_volume[eye], &one, persinv);
}
- DRW_shgroup_call_dynamic_add(
- sgl->camera_stereo_volume_wires, color_volume[2], &one, persinv);
+ DRW_buffer_add_entry(sgl->camera_stereo_volume_wires, color_volume[2], &one, persinv);
}
}
}
@@ -1916,13 +1930,14 @@ static void camera_view3d_stereoscopy_display_extra(OBJECT_ShadingGroupList *sgl
static void camera_view3d_reconstruction(OBJECT_ShadingGroupList *sgl,
Scene *scene,
View3D *v3d,
- const Object *camera_object,
+ Object *camera_object,
Object *ob,
const float color[4],
const bool is_select)
{
const DRWContextState *draw_ctx = DRW_context_state_get();
Camera *cam = ob->data;
+ const Object *orig_camera_object = DEG_get_original_object(camera_object);
if ((v3d->flag2 & V3D_SHOW_RECONSTRUCTION) == 0) {
return;
@@ -2003,7 +2018,7 @@ static void camera_view3d_reconstruction(OBJECT_ShadingGroupList *sgl,
}
if (is_select) {
- DRW_select_load_id(camera_object->select_id | (track_index << 16));
+ DRW_select_load_id(orig_camera_object->runtime.select_id | (track_index << 16));
track_index++;
}
@@ -2021,7 +2036,7 @@ static void camera_view3d_reconstruction(OBJECT_ShadingGroupList *sgl,
};
mul_m4_m4m4(bundle_mat, bundle_mat, bundle_scale_mat);
- DRW_shgroup_call_dynamic_add(sgl->sphere_solid, bundle_mat, bundle_color_v4);
+ DRW_buffer_add_entry(sgl->sphere_solid, bundle_mat, bundle_color_v4);
}
else {
DRW_shgroup_empty_ex(
@@ -2055,7 +2070,7 @@ static void camera_view3d_reconstruction(OBJECT_ShadingGroupList *sgl,
GPUShader *shader = GPU_shader_get_builtin_shader(GPU_SHADER_3D_UNIFORM_COLOR);
DRWShadingGroup *shading_group = DRW_shgroup_create(shader, sgl->non_meshes);
DRW_shgroup_uniform_vec4(shading_group, "color", camera_path_color, 1);
- DRW_shgroup_call_add(shading_group, geom, camera_mat);
+ DRW_shgroup_call(shading_group, geom, camera_mat);
}
}
}
@@ -2069,7 +2084,7 @@ static void DRW_shgroup_camera(OBJECT_ShadingGroupList *sgl, Object *ob, ViewLay
RegionView3D *rv3d = draw_ctx->rv3d;
Camera *cam = ob->data;
- const Object *camera_object = DEG_get_evaluated_object(draw_ctx->depsgraph, v3d->camera);
+ Object *camera_object = DEG_get_evaluated_object(draw_ctx->depsgraph, v3d->camera);
const bool is_select = DRW_state_is_select();
const bool is_active = (ob == camera_object);
const bool look_through = (is_active && (rv3d->persp == RV3D_CAMOB));
@@ -2136,31 +2151,31 @@ static void DRW_shgroup_camera(OBJECT_ShadingGroupList *sgl, Object *ob, ViewLay
copy_m4_m4(mat, ob->obmat);
}
- DRW_shgroup_call_dynamic_add(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) {
- DRW_shgroup_call_dynamic_add(sgl->camera,
- color,
- cam->runtime.drw_corners[0],
- &cam->runtime.drw_depth[0],
- cam->runtime.drw_tria,
- ob->obmat);
+ DRW_buffer_add_entry(sgl->camera,
+ color,
+ cam->runtime.drw_corners[0],
+ &cam->runtime.drw_depth[0],
+ cam->runtime.drw_tria,
+ ob->obmat);
}
/* Active cam */
if (is_active) {
- DRW_shgroup_call_dynamic_add(sgl->camera_tria,
- color,
- cam->runtime.drw_corners[0],
- &cam->runtime.drw_depth[0],
- cam->runtime.drw_tria,
- ob->obmat);
+ DRW_buffer_add_entry(sgl->camera_tria,
+ color,
+ cam->runtime.drw_corners[0],
+ &cam->runtime.drw_depth[0],
+ cam->runtime.drw_tria,
+ ob->obmat);
}
}
@@ -2177,16 +2192,16 @@ static void DRW_shgroup_camera(OBJECT_ShadingGroupList *sgl, Object *ob, ViewLay
size_to_mat4(sizemat, size);
mul_m4_m4m4(cam->runtime.drw_focusmat, cam->runtime.drw_focusmat, sizemat);
- DRW_shgroup_call_dynamic_add(
+ DRW_buffer_add_entry(
sgl->camera_focus, (is_active ? col_hi : col), &cam->drawsize, cam->runtime.drw_focusmat);
- DRW_shgroup_call_dynamic_add(
+ DRW_buffer_add_entry(
sgl->camera_clip, color, &cam->clip_start, &cam->clip_end, cam->runtime.drw_normalmat);
- DRW_shgroup_call_dynamic_add(sgl->camera_clip_points,
- (is_active ? col_hi : col),
- &cam->clip_start,
- &cam->clip_end,
- cam->runtime.drw_normalmat);
+ DRW_buffer_add_entry(sgl->camera_clip_points,
+ (is_active ? col_hi : col),
+ &cam->clip_start,
+ &cam->clip_end,
+ cam->runtime.drw_normalmat);
}
if (cam->flag & CAM_SHOWMIST) {
@@ -2195,13 +2210,13 @@ static void DRW_shgroup_camera(OBJECT_ShadingGroupList *sgl, Object *ob, ViewLay
if (world) {
static float col[4] = {0.5f, 0.5f, 0.5f, 1.0f}, col_hi[4] = {1.0f, 1.0f, 1.0f, 1.0f};
world->mistend = world->miststa + world->mistdist;
- DRW_shgroup_call_dynamic_add(
+ DRW_buffer_add_entry(
sgl->camera_mist, color, &world->miststa, &world->mistend, cam->runtime.drw_normalmat);
- DRW_shgroup_call_dynamic_add(sgl->camera_mist_points,
- (is_active ? col_hi : col),
- &world->miststa,
- &world->mistend,
- cam->runtime.drw_normalmat);
+ DRW_buffer_add_entry(sgl->camera_mist_points,
+ (is_active ? col_hi : col),
+ &world->miststa,
+ &world->mistend,
+ cam->runtime.drw_normalmat);
}
}
@@ -2223,26 +2238,26 @@ static void DRW_shgroup_empty_ex(OBJECT_ShadingGroupList *sgl,
{
switch (draw_type) {
case OB_PLAINAXES:
- DRW_shgroup_call_dynamic_add(sgl->plain_axes, color, draw_size, mat);
+ DRW_buffer_add_entry(sgl->plain_axes, color, draw_size, mat);
break;
case OB_SINGLE_ARROW:
- DRW_shgroup_call_dynamic_add(sgl->single_arrow, color, draw_size, mat);
- DRW_shgroup_call_dynamic_add(sgl->single_arrow_line, color, draw_size, mat);
+ DRW_buffer_add_entry(sgl->single_arrow, color, draw_size, mat);
+ DRW_buffer_add_entry(sgl->single_arrow_line, color, draw_size, mat);
break;
case OB_CUBE:
- DRW_shgroup_call_dynamic_add(sgl->cube, color, draw_size, mat);
+ DRW_buffer_add_entry(sgl->cube, color, draw_size, mat);
break;
case OB_CIRCLE:
- DRW_shgroup_call_dynamic_add(sgl->circle, color, draw_size, mat);
+ DRW_buffer_add_entry(sgl->circle, color, draw_size, mat);
break;
case OB_EMPTY_SPHERE:
- DRW_shgroup_call_dynamic_add(sgl->sphere, color, draw_size, mat);
+ DRW_buffer_add_entry(sgl->sphere, color, draw_size, mat);
break;
case OB_EMPTY_CONE:
- DRW_shgroup_call_dynamic_add(sgl->cone, color, draw_size, mat);
+ DRW_buffer_add_entry(sgl->cone, color, draw_size, mat);
break;
case OB_ARROWS:
- DRW_shgroup_call_dynamic_add(sgl->empty_axes, color, draw_size, mat);
+ DRW_buffer_add_entry(sgl->empty_axes, color, draw_size, mat);
break;
case OB_EMPTY_IMAGE:
BLI_assert(!"Should never happen, use DRW_shgroup_empty instead.");
@@ -2334,19 +2349,19 @@ static void DRW_shgroup_forcefield(OBJECT_ShadingGroupList *sgl, Object *ob, Vie
switch (pd->forcefield) {
case PFIELD_WIND:
- DRW_shgroup_call_dynamic_add(sgl->field_wind, color, &pd->drawvec1, ob->obmat);
+ DRW_buffer_add_entry(sgl->field_wind, color, &pd->drawvec1, ob->obmat);
break;
case PFIELD_FORCE:
- DRW_shgroup_call_dynamic_add(sgl->field_force, color, &pd->drawvec1, ob->obmat);
+ DRW_buffer_add_entry(sgl->field_force, color, &pd->drawvec1, ob->obmat);
break;
case PFIELD_VORTEX:
- DRW_shgroup_call_dynamic_add(sgl->field_vortex, color, &pd->drawvec1, ob->obmat);
+ DRW_buffer_add_entry(sgl->field_vortex, color, &pd->drawvec1, ob->obmat);
break;
case PFIELD_GUIDE:
if (cu && (cu->flag & CU_PATH) && ob->runtime.curve_cache->path &&
ob->runtime.curve_cache->path->data) {
- DRW_shgroup_call_dynamic_add(sgl->field_curve_sta, color, &pd->f_strength, ob->obmat);
- DRW_shgroup_call_dynamic_add(sgl->field_curve_end, color, &pd->f_strength, ob->obmat);
+ DRW_buffer_add_entry(sgl->field_curve_sta, color, &pd->f_strength, ob->obmat);
+ DRW_buffer_add_entry(sgl->field_curve_end, color, &pd->f_strength, ob->obmat);
}
break;
}
@@ -2354,33 +2369,29 @@ static void DRW_shgroup_forcefield(OBJECT_ShadingGroupList *sgl, Object *ob, Vie
if (pd->falloff == PFIELD_FALL_SPHERE) {
/* as last, guide curve alters it */
if ((pd->flag & PFIELD_USEMAX) != 0) {
- DRW_shgroup_call_dynamic_add(sgl->field_curve_end, color, &pd->maxdist, ob->obmat);
+ DRW_buffer_add_entry(sgl->field_curve_end, color, &pd->maxdist, ob->obmat);
}
if ((pd->flag & PFIELD_USEMIN) != 0) {
- DRW_shgroup_call_dynamic_add(sgl->field_curve_end, color, &pd->mindist, ob->obmat);
+ DRW_buffer_add_entry(sgl->field_curve_end, color, &pd->mindist, ob->obmat);
}
}
else if (pd->falloff == PFIELD_FALL_TUBE) {
if (pd->flag & (PFIELD_USEMAX | PFIELD_USEMAXR)) {
- DRW_shgroup_call_dynamic_add(
- sgl->field_tube_limit, color, &pd->drawvec_falloff_max, ob->obmat);
+ DRW_buffer_add_entry(sgl->field_tube_limit, color, &pd->drawvec_falloff_max, ob->obmat);
}
if (pd->flag & (PFIELD_USEMIN | PFIELD_USEMINR)) {
- DRW_shgroup_call_dynamic_add(
- sgl->field_tube_limit, color, &pd->drawvec_falloff_min, ob->obmat);
+ DRW_buffer_add_entry(sgl->field_tube_limit, color, &pd->drawvec_falloff_min, ob->obmat);
}
}
else if (pd->falloff == PFIELD_FALL_CONE) {
if (pd->flag & (PFIELD_USEMAX | PFIELD_USEMAXR)) {
- DRW_shgroup_call_dynamic_add(
- sgl->field_cone_limit, color, &pd->drawvec_falloff_max, ob->obmat);
+ DRW_buffer_add_entry(sgl->field_cone_limit, color, &pd->drawvec_falloff_max, ob->obmat);
}
if (pd->flag & (PFIELD_USEMIN | PFIELD_USEMINR)) {
- DRW_shgroup_call_dynamic_add(
- sgl->field_cone_limit, color, &pd->drawvec_falloff_min, ob->obmat);
+ DRW_buffer_add_entry(sgl->field_cone_limit, color, &pd->drawvec_falloff_min, ob->obmat);
}
}
}
@@ -2412,7 +2423,7 @@ static void DRW_shgroup_volume_extra(OBJECT_ShadingGroupList *sgl,
translate_m4(voxel_cubemat, 1.0f, 1.0f, 1.0f);
mul_m4_m4m4(voxel_cubemat, ob->obmat, voxel_cubemat);
- DRW_shgroup_call_dynamic_add(sgl->cube, color, &one, voxel_cubemat);
+ DRW_buffer_add_entry(sgl->cube, color, &one, voxel_cubemat);
/* Don't show smoke before simulation starts, this could be made an option in the future. */
if (!sds->draw_velocity || !sds->fluid || CFRA < sds->point_cache[0]->startframe) {
@@ -2426,12 +2437,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];
}
@@ -2446,7 +2456,7 @@ static void DRW_shgroup_volume_extra(OBJECT_ShadingGroupList *sgl,
DRW_shgroup_uniform_float_copy(grp, "displaySize", sds->vector_scale);
DRW_shgroup_uniform_float_copy(grp, "slicePosition", sds->slice_depth);
DRW_shgroup_uniform_int_copy(grp, "sliceAxis", slice_axis);
- DRW_shgroup_call_procedural_lines_add(grp, line_count, ob->obmat);
+ DRW_shgroup_call_procedural_lines(grp, line_count, ob->obmat);
BLI_addtail(&e_data.smoke_domains, BLI_genericNodeN(smd));
}
@@ -2472,7 +2482,7 @@ static void DRW_shgroup_speaker(OBJECT_ShadingGroupList *sgl, Object *ob, ViewLa
static float one = 1.0f;
DRW_object_wire_theme_get(ob, view_layer, &color);
- DRW_shgroup_call_dynamic_add(sgl->speaker, color, &one, ob->obmat);
+ DRW_buffer_add_entry(sgl->speaker, color, &one, ob->obmat);
}
typedef struct OBJECT_LightProbeEngineData {
@@ -2547,7 +2557,7 @@ static void DRW_shgroup_lightprobe(OBJECT_Shaders *sh_data,
DRW_shgroup_uniform_vec3(grp, "increment_y", prb_data->increment_y, 1);
DRW_shgroup_uniform_vec3(grp, "increment_z", prb_data->increment_z, 1);
DRW_shgroup_uniform_ivec3(grp, "grid_resolution", &prb->grid_resolution_x, 1);
- DRW_shgroup_call_procedural_points_add(grp, cell_count, NULL);
+ DRW_shgroup_call_procedural_points(grp, cell_count, NULL);
}
else if (prb->type == LIGHTPROBE_TYPE_CUBE) {
float draw_size = 1.0f;
@@ -2556,17 +2566,17 @@ static void DRW_shgroup_lightprobe(OBJECT_Shaders *sh_data,
// unit_m4(prb_data->probe_cube_mat);
// copy_v3_v3(prb_data->probe_cube_mat[3], ob->obmat[3]);
- DRWShadingGroup *grp = shgroup_theme_id_to_probe_cube_outline_shgrp(
+ DRWCallBuffer *buf = buffer_theme_id_to_probe_cube_outline_shgrp(
stl, theme_id, ob->base_flag);
/* TODO remove or change the drawing of the cube probes. Theses line draws nothing on purpose
* to keep the call ids correct. */
zero_m4(probe_cube_mat);
- DRW_shgroup_call_dynamic_add(grp, call_id, &draw_size, probe_cube_mat);
+ DRW_buffer_add_entry(buf, call_id, &draw_size, probe_cube_mat);
}
else {
float draw_size = 1.0f;
- DRWShadingGroup *grp = shgroup_theme_id_to_probe_planar_outline_shgrp(stl, theme_id);
- DRW_shgroup_call_dynamic_add(grp, call_id, &draw_size, ob->obmat);
+ DRWCallBuffer *buf = buffer_theme_id_to_probe_planar_outline_shgrp(stl, theme_id);
+ DRW_buffer_add_entry(buf, call_id, &draw_size, ob->obmat);
}
*call_id += 1;
@@ -2574,14 +2584,14 @@ static void DRW_shgroup_lightprobe(OBJECT_Shaders *sh_data,
switch (prb->type) {
case LIGHTPROBE_TYPE_PLANAR:
- DRW_shgroup_call_dynamic_add(sgl->probe_planar, ob->obmat[3], color);
+ DRW_buffer_add_entry(sgl->probe_planar, ob->obmat[3], color);
break;
case LIGHTPROBE_TYPE_GRID:
- DRW_shgroup_call_dynamic_add(sgl->probe_grid, ob->obmat[3], color);
+ DRW_buffer_add_entry(sgl->probe_grid, ob->obmat[3], color);
break;
case LIGHTPROBE_TYPE_CUBE:
default:
- DRW_shgroup_call_dynamic_add(sgl->probe_cube, ob->obmat[3], color);
+ DRW_buffer_add_entry(sgl->probe_cube, ob->obmat[3], color);
break;
}
@@ -2590,13 +2600,13 @@ static void DRW_shgroup_lightprobe(OBJECT_Shaders *sh_data,
copy_m4_m4(mat, ob->obmat);
normalize_m4(mat);
- DRW_shgroup_call_dynamic_add(sgl->single_arrow, color, &ob->empty_drawsize, mat);
- DRW_shgroup_call_dynamic_add(sgl->single_arrow_line, color, &ob->empty_drawsize, mat);
+ DRW_buffer_add_entry(sgl->single_arrow, color, &ob->empty_drawsize, mat);
+ DRW_buffer_add_entry(sgl->single_arrow_line, color, &ob->empty_drawsize, mat);
copy_m4_m4(mat, ob->obmat);
zero_v3(mat[2]);
- DRW_shgroup_call_dynamic_add(sgl->cube, color, &one, mat);
+ DRW_buffer_add_entry(sgl->cube, color, &one, mat);
}
if ((prb->flag & LIGHTPROBE_FLAG_SHOW_INFLUENCE) != 0) {
@@ -2610,8 +2620,8 @@ static void DRW_shgroup_lightprobe(OBJECT_Shaders *sh_data,
}
if (prb->type == LIGHTPROBE_TYPE_GRID || prb->attenuation_type == LIGHTPROBE_SHAPE_BOX) {
- DRW_shgroup_call_dynamic_add(sgl->cube, color, &prb->distgridinf, ob->obmat);
- DRW_shgroup_call_dynamic_add(sgl->cube, color, &prb->distfalloff, ob->obmat);
+ DRW_buffer_add_entry(sgl->cube, color, &prb->distgridinf, ob->obmat);
+ DRW_buffer_add_entry(sgl->cube, color, &prb->distfalloff, ob->obmat);
}
else if (prb->type == LIGHTPROBE_TYPE_PLANAR) {
float rangemat[4][4];
@@ -2619,17 +2629,17 @@ static void DRW_shgroup_lightprobe(OBJECT_Shaders *sh_data,
normalize_v3(rangemat[2]);
mul_v3_fl(rangemat[2], prb->distinf);
- DRW_shgroup_call_dynamic_add(sgl->cube, color, &one, rangemat);
+ DRW_buffer_add_entry(sgl->cube, color, &one, rangemat);
copy_m4_m4(rangemat, ob->obmat);
normalize_v3(rangemat[2]);
mul_v3_fl(rangemat[2], prb->distfalloff);
- DRW_shgroup_call_dynamic_add(sgl->cube, color, &one, rangemat);
+ DRW_buffer_add_entry(sgl->cube, color, &one, rangemat);
}
else {
- DRW_shgroup_call_dynamic_add(sgl->sphere, color, &prb->distgridinf, ob->obmat);
- DRW_shgroup_call_dynamic_add(sgl->sphere, color, &prb->distfalloff, ob->obmat);
+ DRW_buffer_add_entry(sgl->sphere, color, &prb->distgridinf, ob->obmat);
+ DRW_buffer_add_entry(sgl->sphere, color, &prb->distfalloff, ob->obmat);
}
}
@@ -2648,10 +2658,10 @@ static void DRW_shgroup_lightprobe(OBJECT_Shaders *sh_data,
}
if (prb->parallax_type == LIGHTPROBE_SHAPE_BOX) {
- DRW_shgroup_call_dynamic_add(sgl->cube, color, dist, obmat);
+ DRW_buffer_add_entry(sgl->cube, color, dist, obmat);
}
else {
- DRW_shgroup_call_dynamic_add(sgl->sphere, color, dist, obmat);
+ DRW_buffer_add_entry(sgl->sphere, color, dist, obmat);
}
}
}
@@ -2690,9 +2700,8 @@ static void DRW_shgroup_lightprobe(OBJECT_Shaders *sh_data,
normalize_m4_m4(clipmat, ob->obmat);
mul_m4_m4m4(clipmat, clipmat, cubefacemat[i]);
- DRW_shgroup_call_dynamic_add(
- sgl->light_buflimit, color, &prb->clipsta, &prb->clipend, clipmat);
- DRW_shgroup_call_dynamic_add(
+ DRW_buffer_add_entry(sgl->light_buflimit, color, &prb->clipsta, &prb->clipend, clipmat);
+ DRW_buffer_add_entry(
sgl->light_buflimit_points, color, &prb->clipsta, &prb->clipend, clipmat);
}
}
@@ -2700,8 +2709,8 @@ static void DRW_shgroup_lightprobe(OBJECT_Shaders *sh_data,
/* Line and point going to the ground */
if (prb->type == LIGHTPROBE_TYPE_CUBE) {
- DRW_shgroup_call_dynamic_add(sgl->light_groundline, ob->obmat[3]);
- DRW_shgroup_call_dynamic_add(sgl->light_groundpoint, ob->obmat[3]);
+ DRW_buffer_add_entry(sgl->light_groundline, ob->obmat[3]);
+ DRW_buffer_add_entry(sgl->light_groundpoint, ob->obmat[3]);
}
}
@@ -2711,20 +2720,20 @@ static void DRW_shgroup_relationship_lines(OBJECT_ShadingGroupList *sgl,
Object *ob)
{
if (ob->parent && (DRW_object_visibility_in_active_context(ob->parent) & OB_VISIBLE_SELF)) {
- DRW_shgroup_call_dynamic_add(sgl->relationship_lines, ob->runtime.parent_display_origin);
- DRW_shgroup_call_dynamic_add(sgl->relationship_lines, ob->obmat[3]);
+ DRW_buffer_add_entry(sgl->relationship_lines, ob->runtime.parent_display_origin);
+ DRW_buffer_add_entry(sgl->relationship_lines, ob->obmat[3]);
}
if (ob->rigidbody_constraint) {
Object *rbc_ob1 = ob->rigidbody_constraint->ob1;
Object *rbc_ob2 = ob->rigidbody_constraint->ob2;
if (rbc_ob1 && (DRW_object_visibility_in_active_context(rbc_ob1) & OB_VISIBLE_SELF)) {
- DRW_shgroup_call_dynamic_add(sgl->relationship_lines, rbc_ob1->obmat[3]);
- DRW_shgroup_call_dynamic_add(sgl->relationship_lines, ob->obmat[3]);
+ DRW_buffer_add_entry(sgl->relationship_lines, rbc_ob1->obmat[3]);
+ DRW_buffer_add_entry(sgl->relationship_lines, ob->obmat[3]);
}
if (rbc_ob2 && (DRW_object_visibility_in_active_context(rbc_ob2) & OB_VISIBLE_SELF)) {
- DRW_shgroup_call_dynamic_add(sgl->relationship_lines, rbc_ob2->obmat[3]);
- DRW_shgroup_call_dynamic_add(sgl->relationship_lines, ob->obmat[3]);
+ DRW_buffer_add_entry(sgl->relationship_lines, rbc_ob2->obmat[3]);
+ DRW_buffer_add_entry(sgl->relationship_lines, ob->obmat[3]);
}
}
@@ -2756,8 +2765,8 @@ static void DRW_shgroup_relationship_lines(OBJECT_ShadingGroupList *sgl,
}
if (camob) {
- DRW_shgroup_call_dynamic_add(sgl->constraint_lines, camob->obmat[3]);
- DRW_shgroup_call_dynamic_add(sgl->constraint_lines, ob->obmat[3]);
+ DRW_buffer_add_entry(sgl->constraint_lines, camob->obmat[3]);
+ DRW_buffer_add_entry(sgl->constraint_lines, ob->obmat[3]);
}
}
else {
@@ -2778,8 +2787,8 @@ static void DRW_shgroup_relationship_lines(OBJECT_ShadingGroupList *sgl,
unit_m4(ct->matrix);
}
- DRW_shgroup_call_dynamic_add(sgl->constraint_lines, ct->matrix[3]);
- DRW_shgroup_call_dynamic_add(sgl->constraint_lines, ob->obmat[3]);
+ DRW_buffer_add_entry(sgl->constraint_lines, ct->matrix[3]);
+ DRW_buffer_add_entry(sgl->constraint_lines, ob->obmat[3]);
}
if (cti->flush_constraint_targets) {
@@ -2802,32 +2811,32 @@ static void DRW_shgroup_object_center(OBJECT_StorageList *stl,
return;
}
const bool is_library = ob->id.us > 1 || ID_IS_LINKED(ob);
- DRWShadingGroup *shgroup;
+ DRWCallBuffer *buf;
if (ob == OBACT(view_layer)) {
- shgroup = stl->g_data->center_active;
+ buf = stl->g_data->center_active;
}
else if (ob->base_flag & BASE_SELECTED) {
if (is_library) {
- shgroup = stl->g_data->center_selected_lib;
+ buf = stl->g_data->center_selected_lib;
}
else {
- shgroup = stl->g_data->center_selected;
+ buf = stl->g_data->center_selected;
}
}
else if (v3d->flag & V3D_DRAW_CENTERS) {
if (is_library) {
- shgroup = stl->g_data->center_deselected_lib;
+ buf = stl->g_data->center_deselected_lib;
}
else {
- shgroup = stl->g_data->center_deselected;
+ buf = stl->g_data->center_deselected;
}
}
else {
return;
}
- DRW_shgroup_call_dynamic_add(shgroup, ob->obmat[3]);
+ DRW_buffer_add_entry(buf, ob->obmat[3]);
}
static void DRW_shgroup_texture_space(OBJECT_ShadingGroupList *sgl, Object *ob, int theme_id)
@@ -2877,7 +2886,7 @@ static void DRW_shgroup_texture_space(OBJECT_ShadingGroupList *sgl, Object *ob,
float color[4];
UI_GetThemeColor4fv(theme_id, color);
- DRW_shgroup_call_dynamic_add(sgl->texspace, color, &one, tmp);
+ DRW_buffer_add_entry(sgl->texspace, color, &one, tmp);
}
static void DRW_shgroup_bounds(OBJECT_ShadingGroupList *sgl, Object *ob, int theme_id)
@@ -2914,7 +2923,7 @@ static void DRW_shgroup_bounds(OBJECT_ShadingGroupList *sgl, Object *ob, int the
size_to_mat4(tmp, size);
copy_v3_v3(tmp[3], center);
mul_m4_m4m4(tmp, ob->obmat, tmp);
- DRW_shgroup_call_dynamic_add(sgl->cube, color, &one, tmp);
+ DRW_buffer_add_entry(sgl->cube, color, &one, tmp);
break;
case OB_BOUND_SPHERE:
size[0] = max_fff(size[0], size[1], size[2]);
@@ -2922,7 +2931,7 @@ static void DRW_shgroup_bounds(OBJECT_ShadingGroupList *sgl, Object *ob, int the
size_to_mat4(tmp, size);
copy_v3_v3(tmp[3], center);
mul_m4_m4m4(tmp, ob->obmat, tmp);
- DRW_shgroup_call_dynamic_add(sgl->sphere, color, &one, tmp);
+ DRW_buffer_add_entry(sgl->sphere, color, &one, tmp);
break;
case OB_BOUND_CYLINDER:
size[0] = max_ff(size[0], size[1]);
@@ -2930,7 +2939,7 @@ static void DRW_shgroup_bounds(OBJECT_ShadingGroupList *sgl, Object *ob, int the
size_to_mat4(tmp, size);
copy_v3_v3(tmp[3], center);
mul_m4_m4m4(tmp, ob->obmat, tmp);
- DRW_shgroup_call_dynamic_add(sgl->cylinder, color, &one, tmp);
+ DRW_buffer_add_entry(sgl->cylinder, color, &one, tmp);
break;
case OB_BOUND_CONE:
size[0] = max_ff(size[0], size[1]);
@@ -2941,7 +2950,7 @@ static void DRW_shgroup_bounds(OBJECT_ShadingGroupList *sgl, Object *ob, int the
swap_v3_v3(tmp[1], tmp[2]);
tmp[3][2] -= size[2];
mul_m4_m4m4(tmp, ob->obmat, tmp);
- DRW_shgroup_call_dynamic_add(sgl->cone, color, &one, tmp);
+ DRW_buffer_add_entry(sgl->cone, color, &one, tmp);
break;
case OB_BOUND_CAPSULE:
size[0] = max_ff(size[0], size[1]);
@@ -2950,14 +2959,14 @@ static void DRW_shgroup_bounds(OBJECT_ShadingGroupList *sgl, Object *ob, int the
copy_v2_v2(tmp[3], center);
tmp[3][2] = center[2] + max_ff(0.0f, size[2] - size[0]);
mul_m4_m4m4(final_mat, ob->obmat, tmp);
- DRW_shgroup_call_dynamic_add(sgl->capsule_cap, color, &one, final_mat);
+ DRW_buffer_add_entry(sgl->capsule_cap, color, &one, final_mat);
negate_v3(tmp[2]);
tmp[3][2] = center[2] - max_ff(0.0f, size[2] - size[0]);
mul_m4_m4m4(final_mat, ob->obmat, tmp);
- DRW_shgroup_call_dynamic_add(sgl->capsule_cap, color, &one, final_mat);
+ DRW_buffer_add_entry(sgl->capsule_cap, color, &one, final_mat);
tmp[2][2] = max_ff(0.0f, size[2] * 2.0f - size[0] * 2.0f);
mul_m4_m4m4(final_mat, ob->obmat, tmp);
- DRW_shgroup_call_dynamic_add(sgl->capsule_body, color, &one, final_mat);
+ DRW_buffer_add_entry(sgl->capsule_body, color, &one, final_mat);
break;
}
}
@@ -2980,13 +2989,10 @@ static void OBJECT_cache_populate_particles(OBJECT_Shaders *sh_data,
if (draw_as != PART_DRAW_PATH) {
struct GPUBatch *geom = DRW_cache_particles_get_dots(ob, psys);
DRWShadingGroup *shgrp = NULL;
- static int screen_space[2] = {0, 1};
+ struct GPUBatch *shape = NULL;
static float def_prim_col[3] = {0.5f, 0.5f, 0.5f};
static float def_sec_col[3] = {1.0f, 1.0f, 1.0f};
- /* Dummy particle format for instancing to work. */
- DRW_shgroup_instance_format(e_data.particle_format, {{"dummy", DRW_ATTR_FLOAT, 1}});
-
Material *ma = give_current_material(ob, part->omat);
switch (draw_as) {
@@ -2997,43 +3003,36 @@ static void OBJECT_cache_populate_particles(OBJECT_Shaders *sh_data,
DRW_shgroup_uniform_float(shgrp, "pixel_size", DRW_viewport_pixelsize_get(), 1);
DRW_shgroup_uniform_float(shgrp, "size", &part->draw_size, 1);
DRW_shgroup_uniform_texture(shgrp, "ramp", G_draw.ramp);
- DRW_shgroup_call_add(shgrp, geom, mat);
+ DRW_shgroup_call(shgrp, geom, mat);
break;
case PART_DRAW_CROSS:
- shgrp = DRW_shgroup_instance_create(sh_data->part_prim,
- psl->particle,
- DRW_cache_particles_get_prim(PART_DRAW_CROSS),
- e_data.particle_format);
+ shgrp = DRW_shgroup_create(sh_data->part_prim, psl->particle);
DRW_shgroup_uniform_texture(shgrp, "ramp", G_draw.ramp);
DRW_shgroup_uniform_vec3(shgrp, "color", ma ? &ma->r : def_prim_col, 1);
- DRW_shgroup_uniform_int(shgrp, "screen_space", &screen_space[0], 1);
+ DRW_shgroup_uniform_float(shgrp, "draw_size", &part->draw_size, 1);
+ DRW_shgroup_uniform_bool_copy(shgrp, "screen_space", false);
+ shape = DRW_cache_particles_get_prim(PART_DRAW_CROSS);
+ DRW_shgroup_call_instances_with_attribs(shgrp, shape, NULL, geom);
break;
case PART_DRAW_CIRC:
- shgrp = DRW_shgroup_instance_create(sh_data->part_prim,
- psl->particle,
- DRW_cache_particles_get_prim(PART_DRAW_CIRC),
- e_data.particle_format);
+ shape = DRW_cache_particles_get_prim(PART_DRAW_CIRC);
+ shgrp = DRW_shgroup_create(sh_data->part_prim, psl->particle);
DRW_shgroup_uniform_texture(shgrp, "ramp", G_draw.ramp);
DRW_shgroup_uniform_vec3(shgrp, "color", ma ? &ma->r : def_prim_col, 1);
- DRW_shgroup_uniform_int(shgrp, "screen_space", &screen_space[1], 1);
+ DRW_shgroup_uniform_float(shgrp, "draw_size", &part->draw_size, 1);
+ DRW_shgroup_uniform_bool_copy(shgrp, "screen_space", true);
+ DRW_shgroup_call_instances_with_attribs(shgrp, shape, NULL, geom);
break;
case PART_DRAW_AXIS:
- shgrp = DRW_shgroup_instance_create(sh_data->part_axis,
- psl->particle,
- DRW_cache_particles_get_prim(PART_DRAW_AXIS),
- e_data.particle_format);
- DRW_shgroup_uniform_int(shgrp, "screen_space", &screen_space[0], 1);
+ shape = DRW_cache_particles_get_prim(PART_DRAW_AXIS);
+ shgrp = DRW_shgroup_create(sh_data->part_axis, psl->particle);
+ DRW_shgroup_uniform_float(shgrp, "draw_size", &part->draw_size, 1);
+ DRW_shgroup_uniform_bool_copy(shgrp, "screen_space", false);
+ DRW_shgroup_call_instances_with_attribs(shgrp, shape, NULL, geom);
break;
default:
break;
}
-
- if (shgrp) {
- if (draw_as != PART_DRAW_DOT) {
- DRW_shgroup_uniform_float(shgrp, "draw_size", &part->draw_size, 1);
- DRW_shgroup_instance_batch(shgrp, geom);
- }
- }
}
}
}
@@ -3096,6 +3095,24 @@ static void OBJECT_gpencil_color_names(Object *ob, struct DRWTextStore *dt, ucha
}
}
+BLI_INLINE OBJECT_DupliData *OBJECT_duplidata_get(Object *ob, void *vedata, bool *init)
+{
+ OBJECT_DupliData **dupli_data = (OBJECT_DupliData **)DRW_duplidata_get(vedata);
+ *init = false;
+ if (!ELEM(ob->type, OB_MESH, OB_SURF, OB_LATTICE, OB_CURVE, OB_FONT)) {
+ return NULL;
+ }
+
+ if (dupli_data) {
+ if (*dupli_data == NULL) {
+ *dupli_data = MEM_callocN(sizeof(OBJECT_DupliData), "OBJECT_DupliData");
+ *init = true;
+ }
+ return *dupli_data;
+ }
+ return NULL;
+}
+
static void OBJECT_cache_populate(void *vedata, Object *ob)
{
OBJECT_PassList *psl = ((OBJECT_Data *)vedata)->psl;
@@ -3132,10 +3149,15 @@ static void OBJECT_cache_populate(void *vedata, Object *ob)
/* Show if this is the camera we're looking through since it's useful for selecting. */
(((rv3d->persp == RV3D_CAMOB) && ((ID *)v3d->camera == ob->id.orig_id)) == 0));
+ /* Fast path for duplis. */
+ bool init_duplidata;
+ OBJECT_DupliData *dupli_data = OBJECT_duplidata_get(ob, vedata, &init_duplidata);
+
if (do_outlines) {
if (!BKE_object_is_in_editmode(ob) &&
!((ob == draw_ctx->obact) && (draw_ctx->object_mode & OB_MODE_ALL_PAINT))) {
struct GPUBatch *geom;
+ DRWShadingGroup *shgroup = NULL;
/* This fixes only the biggest case which is a plane in ortho view. */
int flat_axis = 0;
@@ -3143,185 +3165,211 @@ static void OBJECT_cache_populate(void *vedata, Object *ob)
DRW_object_is_flat(ob, &flat_axis) &&
DRW_object_axis_orthogonal_to_view(ob, flat_axis));
- if (stl->g_data->xray_enabled_and_not_wire || is_flat_object_viewed_from_side) {
- geom = DRW_cache_object_edge_detection_get(ob, NULL);
+ if (dupli_data && !init_duplidata) {
+ geom = dupli_data->outline_geom;
+ shgroup = dupli_data->outline_shgrp;
}
else {
- geom = DRW_cache_object_surface_get(ob);
- }
+ if (stl->g_data->xray_enabled_and_not_wire || is_flat_object_viewed_from_side) {
+ geom = DRW_cache_object_edge_detection_get(ob, NULL);
+ }
+ else {
+ geom = DRW_cache_object_surface_get(ob);
+ }
- if (geom) {
- theme_id = DRW_object_wire_theme_get(ob, view_layer, NULL);
- DRWShadingGroup *shgroup = shgroup_theme_id_to_outline_or_null(
- stl, theme_id, ob->base_flag);
- if (shgroup != NULL) {
- DRW_shgroup_call_object_add(shgroup, geom, ob);
+ if (geom) {
+ theme_id = DRW_object_wire_theme_get(ob, view_layer, NULL);
+ shgroup = shgroup_theme_id_to_outline_or_null(stl, theme_id, ob->base_flag);
}
}
- }
- }
- switch (ob->type) {
- case OB_MESH: {
- if (hide_object_extra) {
- break;
+ if (shgroup && geom) {
+ DRW_shgroup_call_object(shgroup, geom, ob);
}
- Mesh *me = ob->data;
- if (!is_edit_mode && me->totedge == 0) {
- struct GPUBatch *geom = DRW_cache_mesh_all_verts_get(ob);
- if (geom) {
- if (theme_id == TH_UNDEFINED) {
- theme_id = DRW_object_wire_theme_get(ob, view_layer, NULL);
- }
- DRWShadingGroup *shgroup = shgroup_theme_id_to_point(sgl, theme_id, ob->base_flag);
- DRW_shgroup_call_object_add(shgroup, geom, ob);
- }
+
+ if (init_duplidata) {
+ dupli_data->outline_shgrp = shgroup;
+ dupli_data->outline_geom = geom;
}
- else {
- bool has_edit_mesh_cage = false;
- /* TODO: Should be its own function. */
- if (is_edit_mode) {
- BMEditMesh *embm = me->edit_mesh;
- has_edit_mesh_cage = embm->mesh_eval_cage &&
- (embm->mesh_eval_cage != embm->mesh_eval_final);
+ }
+ }
+
+ if (dupli_data && !init_duplidata) {
+ if (dupli_data->extra_shgrp && dupli_data->extra_geom) {
+ DRW_shgroup_call_object(dupli_data->extra_shgrp, dupli_data->extra_geom, ob);
+ }
+ }
+ else {
+ struct GPUBatch *geom = NULL;
+ DRWShadingGroup *shgroup = NULL;
+ switch (ob->type) {
+ case OB_MESH: {
+ if (hide_object_extra) {
+ break;
}
- if ((!is_edit_mode && me->totedge > 0) || has_edit_mesh_cage) {
- struct GPUBatch *geom = DRW_cache_mesh_loose_edges_get(ob);
+ Mesh *me = ob->data;
+ if (!is_edit_mode && me->totedge == 0) {
+ geom = DRW_cache_mesh_all_verts_get(ob);
if (geom) {
if (theme_id == TH_UNDEFINED) {
theme_id = DRW_object_wire_theme_get(ob, view_layer, NULL);
}
- DRWShadingGroup *shgroup = shgroup_theme_id_to_wire(sgl, theme_id, ob->base_flag);
- DRW_shgroup_call_object_add(shgroup, geom, ob);
+ shgroup = shgroup_theme_id_to_point(sgl, theme_id, ob->base_flag);
+ DRW_shgroup_call_object(shgroup, geom, ob);
+ }
+ }
+ else {
+ bool has_edit_mesh_cage = false;
+ /* TODO: Should be its own function. */
+ if (is_edit_mode) {
+ BMEditMesh *embm = me->edit_mesh;
+ has_edit_mesh_cage = embm->mesh_eval_cage &&
+ (embm->mesh_eval_cage != embm->mesh_eval_final);
+ }
+ if ((!is_edit_mode && me->totedge > 0) || has_edit_mesh_cage) {
+ geom = DRW_cache_mesh_loose_edges_get(ob);
+ if (geom) {
+ if (theme_id == TH_UNDEFINED) {
+ theme_id = DRW_object_wire_theme_get(ob, view_layer, NULL);
+ }
+ shgroup = shgroup_theme_id_to_wire(sgl, theme_id, ob->base_flag);
+ DRW_shgroup_call_object(shgroup, geom, ob);
+ }
}
}
- }
- break;
- }
- case OB_SURF: {
- if (hide_object_extra) {
- break;
- }
- struct GPUBatch *geom = DRW_cache_surf_edge_wire_get(ob);
- if (geom == NULL) {
break;
}
- if (theme_id == TH_UNDEFINED) {
- theme_id = DRW_object_wire_theme_get(ob, view_layer, NULL);
- }
- DRWShadingGroup *shgroup = shgroup_theme_id_to_wire(sgl, theme_id, ob->base_flag);
- DRW_shgroup_call_object_add(shgroup, geom, ob);
- break;
- }
- case OB_LATTICE: {
- if (!is_edit_mode) {
+ case OB_SURF: {
if (hide_object_extra) {
break;
}
- struct GPUBatch *geom = DRW_cache_lattice_wire_get(ob, false);
- if (theme_id == TH_UNDEFINED) {
- theme_id = DRW_object_wire_theme_get(ob, view_layer, NULL);
- }
-
- DRWShadingGroup *shgroup = shgroup_theme_id_to_wire(sgl, theme_id, ob->base_flag);
- DRW_shgroup_call_object_add(shgroup, geom, ob);
- }
- break;
- }
- case OB_CURVE: {
- if (!is_edit_mode) {
- if (hide_object_extra) {
+ geom = DRW_cache_surf_edge_wire_get(ob);
+ if (geom == NULL) {
break;
}
- struct GPUBatch *geom = DRW_cache_curve_edge_wire_get(ob);
if (theme_id == TH_UNDEFINED) {
theme_id = DRW_object_wire_theme_get(ob, view_layer, NULL);
}
- DRWShadingGroup *shgroup = shgroup_theme_id_to_wire(sgl, theme_id, ob->base_flag);
- DRW_shgroup_call_object_add(shgroup, geom, ob);
- }
- break;
- }
- case OB_MBALL: {
- if (!is_edit_mode) {
- DRW_shgroup_mball_handles(sgl, ob, view_layer);
- }
- break;
- }
- case OB_LAMP:
- if (hide_object_extra) {
+ shgroup = shgroup_theme_id_to_wire(sgl, theme_id, ob->base_flag);
+ DRW_shgroup_call_object(shgroup, geom, ob);
break;
}
- DRW_shgroup_light(sgl, ob, view_layer);
- break;
- case OB_CAMERA:
- if (hide_object_extra) {
+ case OB_LATTICE: {
+ if (!is_edit_mode) {
+ if (hide_object_extra) {
+ break;
+ }
+ geom = DRW_cache_lattice_wire_get(ob, false);
+ if (theme_id == TH_UNDEFINED) {
+ theme_id = DRW_object_wire_theme_get(ob, view_layer, NULL);
+ }
+
+ shgroup = shgroup_theme_id_to_wire(sgl, theme_id, ob->base_flag);
+ DRW_shgroup_call_object(shgroup, geom, ob);
+ }
break;
}
- DRW_shgroup_camera(sgl, ob, view_layer);
- break;
- case OB_EMPTY:
- if (hide_object_extra) {
+ case OB_CURVE: {
+ if (!is_edit_mode) {
+ if (hide_object_extra) {
+ break;
+ }
+ geom = DRW_cache_curve_edge_wire_get(ob);
+ if (theme_id == TH_UNDEFINED) {
+ theme_id = DRW_object_wire_theme_get(ob, view_layer, NULL);
+ }
+ shgroup = shgroup_theme_id_to_wire(sgl, theme_id, ob->base_flag);
+ DRW_shgroup_call_object(shgroup, geom, ob);
+ }
break;
}
- DRW_shgroup_empty(sh_data, sgl, ob, view_layer, rv3d, draw_ctx->sh_cfg);
- break;
- case OB_SPEAKER:
- if (hide_object_extra) {
+ case OB_MBALL: {
+ if (!is_edit_mode) {
+ DRW_shgroup_mball_handles(sgl, ob, view_layer);
+ }
break;
}
- DRW_shgroup_speaker(sgl, ob, view_layer);
- break;
- case OB_LIGHTPROBE:
- if (hide_object_extra) {
+ case OB_LAMP:
+ if (hide_object_extra) {
+ break;
+ }
+ DRW_shgroup_light(sgl, ob, view_layer);
break;
- }
- DRW_shgroup_lightprobe(sh_data, stl, psl, ob, view_layer);
- break;
- case OB_ARMATURE: {
- if ((v3d->flag2 & V3D_HIDE_OVERLAYS) || (v3d->overlay.flag & V3D_OVERLAY_HIDE_BONES) ||
- ((ob->dt < OB_WIRE) && !DRW_state_is_select())) {
+ case OB_CAMERA:
+ if (hide_object_extra) {
+ break;
+ }
+ DRW_shgroup_camera(sgl, ob, view_layer);
break;
- }
- bArmature *arm = ob->data;
- if (arm->edbo == NULL) {
- if (DRW_state_is_select() || !DRW_pose_mode_armature(ob, draw_ctx->obact)) {
- bool is_wire = (v3d->shading.type == OB_WIRE) || (ob->dt <= OB_WIRE) ||
- XRAY_FLAG_ENABLED(v3d);
- DRWArmaturePasses passes = {
- .bone_solid = (is_wire) ? NULL : sgl->bone_solid,
- .bone_outline = sgl->bone_outline,
- .bone_wire = sgl->bone_wire,
- .bone_envelope = sgl->bone_envelope,
- .bone_axes = sgl->bone_axes,
- .relationship_lines = NULL, /* Don't draw relationship lines */
- .custom_shapes = stl->g_data->custom_shapes,
- };
- DRW_shgroup_armature_object(ob, view_layer, passes, is_wire);
+ case OB_EMPTY:
+ if (hide_object_extra) {
+ break;
+ }
+ DRW_shgroup_empty(sh_data, sgl, ob, view_layer, rv3d, draw_ctx->sh_cfg);
+ break;
+ case OB_SPEAKER:
+ if (hide_object_extra) {
+ break;
+ }
+ DRW_shgroup_speaker(sgl, ob, view_layer);
+ break;
+ case OB_LIGHTPROBE:
+ if (hide_object_extra) {
+ break;
+ }
+ DRW_shgroup_lightprobe(sh_data, stl, psl, ob, view_layer);
+ break;
+ case OB_ARMATURE: {
+ if ((v3d->flag2 & V3D_HIDE_OVERLAYS) || (v3d->overlay.flag & V3D_OVERLAY_HIDE_BONES) ||
+ ((ob->dt < OB_WIRE) && !DRW_state_is_select())) {
+ break;
+ }
+ bArmature *arm = ob->data;
+ if (arm->edbo == NULL) {
+ if (DRW_state_is_select() || !DRW_pose_mode_armature(ob, draw_ctx->obact)) {
+ bool is_wire = (v3d->shading.type == OB_WIRE) || (ob->dt <= OB_WIRE) ||
+ XRAY_FLAG_ENABLED(v3d);
+ DRWArmaturePasses passes = {
+ .bone_solid = (is_wire) ? NULL : sgl->bone_solid,
+ .bone_outline = sgl->bone_outline,
+ .bone_wire = sgl->bone_wire,
+ .bone_envelope = sgl->bone_envelope,
+ .bone_axes = sgl->bone_axes,
+ .relationship_lines = NULL, /* Don't draw relationship lines */
+ .custom_shapes = stl->g_data->custom_shapes,
+ };
+ DRW_shgroup_armature_object(ob, view_layer, passes, is_wire);
+ }
}
- }
- break;
- }
- case OB_FONT: {
- if (hide_object_extra) {
break;
}
- Curve *cu = (Curve *)ob->data;
- bool has_surface = (cu->flag & (CU_FRONT | CU_BACK)) || cu->ext1 != 0.0f || cu->ext2 != 0.0f;
- if (!has_surface) {
- struct GPUBatch *geom = DRW_cache_text_edge_wire_get(ob);
- if (geom) {
- if (theme_id == TH_UNDEFINED) {
- theme_id = DRW_object_wire_theme_get(ob, view_layer, NULL);
+ case OB_FONT: {
+ if (hide_object_extra) {
+ break;
+ }
+ Curve *cu = (Curve *)ob->data;
+ bool has_surface = (cu->flag & (CU_FRONT | CU_BACK)) || cu->ext1 != 0.0f ||
+ cu->ext2 != 0.0f;
+ if (!has_surface) {
+ geom = DRW_cache_text_edge_wire_get(ob);
+ if (geom) {
+ if (theme_id == TH_UNDEFINED) {
+ theme_id = DRW_object_wire_theme_get(ob, view_layer, NULL);
+ }
+ shgroup = shgroup_theme_id_to_wire(sgl, theme_id, ob->base_flag);
+ DRW_shgroup_call_object(shgroup, geom, ob);
}
- DRWShadingGroup *shgroup = shgroup_theme_id_to_wire(sgl, theme_id, ob->base_flag);
- DRW_shgroup_call_object_add(shgroup, geom, ob);
}
+ break;
}
- break;
+ default:
+ break;
+ }
+
+ if (init_duplidata) {
+ dupli_data->extra_shgrp = shgroup;
+ dupli_data->extra_geom = geom;
}
- default:
- break;
}
if (ob->pd && ob->pd->forcefield) {
@@ -3386,7 +3434,7 @@ static void OBJECT_cache_populate(void *vedata, Object *ob)
float *color, axes_size = 1.0f;
DRW_object_wire_theme_get(ob, view_layer, &color);
- DRW_shgroup_call_dynamic_add(sgl->empty_axes, color, &axes_size, ob->obmat);
+ DRW_buffer_add_entry(sgl->empty_axes, color, &axes_size, ob->obmat);
}
if ((md = modifiers_findByType(ob, eModifierType_Smoke)) &&
diff --git a/source/blender/draw/modes/overlay_mode.c b/source/blender/draw/modes/overlay_mode.c
index ed96b2a05bc..8e50d08be23 100644
--- a/source/blender/draw/modes/overlay_mode.c
+++ b/source/blender/draw/modes/overlay_mode.c
@@ -46,6 +46,11 @@
/* Structures */
+typedef struct OVERLAY_DupliData {
+ DRWShadingGroup *shgrp;
+ struct GPUBatch *geom;
+} OVERLAY_DupliData;
+
typedef struct OVERLAY_StorageList {
struct OVERLAY_PrivateData *g_data;
} OVERLAY_StorageList;
@@ -95,6 +100,8 @@ extern char datatoc_overlay_face_wireframe_geom_glsl[];
extern char datatoc_overlay_face_wireframe_frag_glsl[];
extern char datatoc_gpu_shader_depth_only_frag_glsl[];
+extern char datatoc_common_view_lib_glsl[];
+
/* Functions */
static void overlay_engine_init(void *vedata)
{
@@ -104,10 +111,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__);
@@ -119,8 +122,10 @@ static void overlay_engine_init(void *vedata)
if (!sh_data->face_orientation) {
/* Face orientation */
sh_data->face_orientation = GPU_shader_create_from_arrays({
- .vert =
- (const char *[]){sh_cfg_data->lib, datatoc_overlay_face_orientation_vert_glsl, NULL},
+ .vert = (const char *[]){sh_cfg_data->lib,
+ datatoc_common_view_lib_glsl,
+ datatoc_overlay_face_orientation_vert_glsl,
+ NULL},
.frag = (const char *[]){datatoc_overlay_face_orientation_frag_glsl, NULL},
.defs = (const char *[]){sh_cfg_data->def, NULL},
});
@@ -128,7 +133,10 @@ static void overlay_engine_init(void *vedata)
if (!sh_data->face_wireframe) {
sh_data->select_wireframe = GPU_shader_create_from_arrays({
- .vert = (const char *[]){sh_cfg_data->lib, datatoc_overlay_face_wireframe_vert_glsl, NULL},
+ .vert = (const char *[]){sh_cfg_data->lib,
+ datatoc_common_view_lib_glsl,
+ datatoc_overlay_face_wireframe_vert_glsl,
+ NULL},
.geom = (const char *[]){sh_cfg_data->lib, datatoc_overlay_face_wireframe_geom_glsl, NULL},
.frag = (const char *[]){datatoc_gpu_shader_depth_only_frag_glsl, NULL},
.defs = (const char *[]){sh_cfg_data->def, "#define SELECT_EDGES\n", NULL},
@@ -136,14 +144,20 @@ static void overlay_engine_init(void *vedata)
#if USE_GEOM_SHADER_WORKAROUND
/* Apple drivers does not support wide wires. Use geometry shader as a workaround. */
sh_data->face_wireframe = GPU_shader_create_from_arrays({
- .vert = (const char *[]){sh_cfg_data->lib, datatoc_overlay_face_wireframe_vert_glsl, NULL},
+ .vert = (const char *[]){sh_cfg_data->lib,
+ datatoc_common_view_lib_glsl,
+ datatoc_overlay_face_wireframe_vert_glsl,
+ NULL},
.geom = (const char *[]){sh_cfg_data->lib, datatoc_overlay_face_wireframe_geom_glsl, NULL},
.frag = (const char *[]){datatoc_overlay_face_wireframe_frag_glsl, NULL},
.defs = (const char *[]){sh_cfg_data->def, "#define USE_GEOM\n", NULL},
});
#else
sh_data->face_wireframe = GPU_shader_create_from_arrays({
- .vert = (const char *[]){sh_cfg_data->lib, datatoc_overlay_face_wireframe_vert_glsl, NULL},
+ .vert = (const char *[]){sh_cfg_data->lib,
+ datatoc_common_view_lib_glsl,
+ datatoc_overlay_face_wireframe_vert_glsl,
+ NULL},
.frag = (const char *[]){datatoc_overlay_face_wireframe_frag_glsl, NULL},
.defs = (const char *[]){sh_cfg_data->def, NULL},
});
@@ -205,7 +219,7 @@ static void overlay_cache_init(void *vedata)
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]));
@@ -337,12 +351,27 @@ static void overlay_cache_populate(void *vedata, Object *ob)
if (DRW_object_is_renderable(ob) && pd->overlay.flag & V3D_OVERLAY_FACE_ORIENTATION) {
struct GPUBatch *geom = DRW_cache_object_surface_get(ob);
if (geom) {
- DRW_shgroup_call_add(pd->face_orientation_shgrp, geom, ob->obmat);
+ DRW_shgroup_call_object(pd->face_orientation_shgrp, geom, ob);
}
}
if ((pd->overlay.flag & V3D_OVERLAY_WIREFRAMES) || (v3d->shading.type == OB_WIRE) ||
(ob->dtx & OB_DRAWWIRE) || (ob->dt == OB_WIRE)) {
+
+ /* Fast path for duplis. */
+ OVERLAY_DupliData **dupli_data = (OVERLAY_DupliData **)DRW_duplidata_get(vedata);
+ if (dupli_data) {
+ if (*dupli_data == NULL) {
+ *dupli_data = MEM_callocN(sizeof(OVERLAY_DupliData), "OVERLAY_DupliData");
+ }
+ else {
+ if ((*dupli_data)->shgrp && (*dupli_data)->geom) {
+ DRW_shgroup_call_object((*dupli_data)->shgrp, (*dupli_data)->geom, ob);
+ }
+ return;
+ }
+ }
+
const bool is_edit_mode = BKE_object_is_in_editmode(ob);
bool has_edit_mesh_cage = false;
if (ob->type == OB_MESH) {
@@ -359,7 +388,7 @@ static void overlay_cache_populate(void *vedata, Object *ob)
if ((!pd->show_overlays) ||
(((ob != draw_ctx->object_edit) && !is_edit_mode) || has_edit_mesh_cage) ||
ob->type != OB_MESH) {
- const bool is_sculpt_mode = (ob->sculpt != NULL);
+ const bool is_sculpt_mode = DRW_object_use_pbvh_drawing(ob);
const bool all_wires = (ob->dtx & OB_DRAW_ALL_EDGES);
const bool is_wire = (ob->dt < OB_SOLID);
const bool use_coloring = (pd->show_overlays && !is_edit_mode && !is_sculpt_mode &&
@@ -389,12 +418,18 @@ static void overlay_cache_populate(void *vedata, Object *ob)
}
if (is_sculpt_mode) {
- DRW_shgroup_call_sculpt_wires_add(shgrp, ob, ob->obmat);
+ DRW_shgroup_call_sculpt(shgrp, ob, true, false, false);
}
else {
- DRW_shgroup_call_add(shgrp, geom, ob->obmat);
+ DRW_shgroup_call_object(shgrp, geom, ob);
}
}
+
+ if (dupli_data) {
+ (*dupli_data)->shgrp = shgrp;
+ (*dupli_data)->geom = geom;
+ }
+
if (is_wire && shgrp != NULL) {
/* If object is wireframe, don't try to use stencil test. */
DRW_shgroup_state_disable(shgrp, DRW_STATE_STENCIL_EQUAL);
diff --git a/source/blender/draw/modes/paint_texture_mode.c b/source/blender/draw/modes/paint_texture_mode.c
index 3e292f4e4bc..ee8ec78e91b 100644
--- a/source/blender/draw/modes/paint_texture_mode.c
+++ b/source/blender/draw/modes/paint_texture_mode.c
@@ -27,6 +27,8 @@
#include "BKE_node.h"
+#include "BLI_string_utils.h"
+
/* If builtin shaders are needed */
#include "GPU_shader.h"
#include "GPU_texture.h"
@@ -39,6 +41,7 @@
#include "DEG_depsgraph_query.h"
extern char datatoc_common_globals_lib_glsl[];
+extern char datatoc_common_view_lib_glsl[];
extern char datatoc_paint_texture_vert_glsl[];
extern char datatoc_paint_texture_frag_glsl[];
extern char datatoc_paint_wire_vert_glsl[];
@@ -60,8 +63,8 @@ typedef struct PAINT_TEXTURE_PassList {
* Only contains (DRWPass *) */
struct DRWPass *image_faces;
- struct DRWPass *wire_overlay;
- struct DRWPass *face_overlay;
+ struct DRWPass *wire_select_overlay;
+ struct DRWPass *face_select_overlay;
} PAINT_TEXTURE_PassList;
typedef struct PAINT_TEXTURE_FramebufferList {
@@ -97,20 +100,24 @@ typedef struct PAINT_TEXTURE_Data {
PAINT_TEXTURE_StorageList *stl;
} PAINT_TEXTURE_Data;
-/* *********** STATIC *********** */
-
-static struct {
+typedef struct PAINT_TEXTURE_Shaders {
/* Custom shaders :
* Add sources to source/blender/draw/modes/shaders
* init in PAINT_TEXTURE_engine_init();
* free in PAINT_TEXTURE_engine_free(); */
- struct GPUShader *fallback_sh;
- struct GPUShader *image_sh;
- struct GPUShader *image_masking_sh;
+ struct GPUShader *fallback;
+ struct GPUShader *image;
+ struct GPUShader *image_mask;
+
+ struct GPUShader *wire_select_overlay;
+ struct GPUShader *face_select_overlay;
+} PAINT_TEXTURE_Shaders;
- struct GPUShader *wire_overlay_shader;
- struct GPUShader *face_overlay_shader;
-} e_data = {NULL}; /* Engine data */
+/* *********** STATIC *********** */
+
+static struct {
+ PAINT_TEXTURE_Shaders sh_data[GPU_SHADER_CFG_LEN];
+} e_data = {{{NULL}}}; /* Engine data */
typedef struct PAINT_TEXTURE_PrivateData {
/* This keeps the references of the shading groups for
@@ -119,8 +126,8 @@ typedef struct PAINT_TEXTURE_PrivateData {
DRWShadingGroup **shgroup_image_array;
/* face-mask */
- DRWShadingGroup *lwire_shgrp;
- DRWShadingGroup *face_shgrp;
+ DRWShadingGroup *lwire_select_shgrp;
+ DRWShadingGroup *face_select_shgrp;
} PAINT_TEXTURE_PrivateData; /* Transient data */
/* *********** FUNCTIONS *********** */
@@ -129,29 +136,54 @@ typedef struct PAINT_TEXTURE_PrivateData {
* It is called for every frames. */
static void PAINT_TEXTURE_engine_init(void *UNUSED(vedata))
{
- if (!e_data.fallback_sh) {
- e_data.fallback_sh = GPU_shader_get_builtin_shader(GPU_SHADER_3D_UNIFORM_COLOR);
-
- e_data.image_sh = DRW_shader_create_with_lib(datatoc_paint_texture_vert_glsl,
- NULL,
- datatoc_paint_texture_frag_glsl,
- datatoc_common_globals_lib_glsl,
- NULL);
-
- e_data.image_masking_sh = DRW_shader_create_with_lib(datatoc_paint_texture_vert_glsl,
- NULL,
- datatoc_paint_texture_frag_glsl,
- datatoc_common_globals_lib_glsl,
- "#define TEXTURE_PAINT_MASK\n");
-
- e_data.wire_overlay_shader = DRW_shader_create_with_lib(datatoc_paint_wire_vert_glsl,
- NULL,
- datatoc_paint_wire_frag_glsl,
- datatoc_common_globals_lib_glsl,
- "#define VERTEX_MODE\n");
-
- e_data.face_overlay_shader = DRW_shader_create(
- datatoc_paint_face_vert_glsl, NULL, datatoc_gpu_shader_uniform_color_frag_glsl, NULL);
+ const DRWContextState *draw_ctx = DRW_context_state_get();
+ PAINT_TEXTURE_Shaders *sh_data = &e_data.sh_data[draw_ctx->sh_cfg];
+
+ if (!sh_data->fallback) {
+ const GPUShaderConfigData *sh_cfg_data = &GPU_shader_cfg_data[draw_ctx->sh_cfg];
+ sh_data->fallback = GPU_shader_get_builtin_shader_with_config(GPU_SHADER_3D_UNIFORM_COLOR,
+ draw_ctx->sh_cfg);
+
+ sh_data->image = 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, 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,
+ datatoc_common_view_lib_glsl,
+ datatoc_paint_wire_vert_glsl,
+ NULL},
+ .frag = (const char *[]){datatoc_paint_wire_frag_glsl, NULL},
+ .defs = (const char *[]){sh_cfg_data->def, "#define USE_SELECT\n", NULL},
+ });
+
+ sh_data->face_select_overlay = GPU_shader_create_from_arrays({
+ .vert = (const char *[]){sh_cfg_data->lib,
+ datatoc_common_view_lib_glsl,
+ datatoc_paint_face_vert_glsl,
+ NULL},
+ .frag = (const char *[]){datatoc_common_view_lib_glsl,
+ datatoc_gpu_shader_uniform_color_frag_glsl,
+ NULL},
+ .defs = (const char *[]){sh_cfg_data->def, NULL},
+ });
}
}
@@ -160,13 +192,14 @@ static DRWShadingGroup *create_texture_paint_shading_group(PAINT_TEXTURE_PassLis
const DRWContextState *draw_ctx,
const bool nearest_interp)
{
+ PAINT_TEXTURE_Shaders *sh_data = &e_data.sh_data[draw_ctx->sh_cfg];
Scene *scene = draw_ctx->scene;
const ImagePaintSettings *imapaint = &scene->toolsettings->imapaint;
const bool masking_enabled = imapaint->flag & IMAGEPAINT_PROJECT_LAYER_STENCIL &&
imapaint->stencil != NULL;
- DRWShadingGroup *grp = DRW_shgroup_create(
- masking_enabled ? e_data.image_masking_sh : e_data.image_sh, psl->image_faces);
+ DRWShadingGroup *grp = DRW_shgroup_create(masking_enabled ? sh_data->image_mask : sh_data->image,
+ psl->image_faces);
DRW_shgroup_uniform_texture(grp, "image", texture);
DRW_shgroup_uniform_float(grp, "alpha", &draw_ctx->v3d->overlay.texture_paint_mode_opacity, 1);
DRW_shgroup_uniform_block(grp, "globalsBlock", G_draw.block_ubo);
@@ -174,7 +207,7 @@ static DRWShadingGroup *create_texture_paint_shading_group(PAINT_TEXTURE_PassLis
if (masking_enabled) {
const bool masking_inverted = (imapaint->flag & IMAGEPAINT_PROJECT_LAYER_STENCIL_INV) > 0;
- GPUTexture *stencil = GPU_texture_from_blender(imapaint->stencil, NULL, GL_TEXTURE_2D, false);
+ GPUTexture *stencil = GPU_texture_from_blender(imapaint->stencil, NULL, GL_TEXTURE_2D);
DRW_shgroup_uniform_texture(grp, "maskingImage", stencil);
DRW_shgroup_uniform_vec3(grp, "maskingColor", imapaint->stencil_col, 1);
DRW_shgroup_uniform_bool_copy(grp, "maskingInvertStencil", masking_inverted);
@@ -195,87 +228,102 @@ static void PAINT_TEXTURE_cache_init(void *vedata)
stl->g_data->shgroup_image_array = NULL;
}
- {
- /* Create a pass */
- DRWState state = DRW_STATE_WRITE_COLOR | DRW_STATE_DEPTH_EQUAL | DRW_STATE_BLEND;
- psl->image_faces = DRW_pass_create("Image Color Pass", state);
+ const DRWContextState *draw_ctx = DRW_context_state_get();
+ PAINT_TEXTURE_Shaders *sh_data = &e_data.sh_data[draw_ctx->sh_cfg];
- stl->g_data->shgroup_fallback = DRW_shgroup_create(e_data.fallback_sh, psl->image_faces);
+ /* Create a pass */
+ {
+ DRWPass *pass = DRW_pass_create(
+ "Image Color Pass", DRW_STATE_WRITE_COLOR | DRW_STATE_DEPTH_EQUAL | DRW_STATE_BLEND);
+ DRWShadingGroup *shgrp = DRW_shgroup_create(sh_data->fallback, pass);
/* Uniforms need a pointer to it's value so be sure it's accessible at
* any given time (i.e. use static vars) */
static float color[4] = {1.0f, 0.0f, 1.0f, 1.0};
- DRW_shgroup_uniform_vec4(stl->g_data->shgroup_fallback, "color", color, 1);
-
- MEM_SAFE_FREE(stl->g_data->shgroup_image_array);
-
- const DRWContextState *draw_ctx = DRW_context_state_get();
- Object *ob = draw_ctx->obact;
- if (ob && ob->type == OB_MESH) {
- Scene *scene = draw_ctx->scene;
- const ImagePaintSettings *imapaint = &scene->toolsettings->imapaint;
- const bool use_material_slots = (imapaint->mode == IMAGEPAINT_MODE_MATERIAL);
- const Mesh *me = ob->data;
- const int mat_nr = max_ii(1, me->totcol);
-
- stl->g_data->shgroup_image_array = MEM_mallocN(
- sizeof(*stl->g_data->shgroup_image_array) * (use_material_slots ? mat_nr : 1), __func__);
-
- if (use_material_slots) {
- for (int i = 0; i < mat_nr; i++) {
- Material *ma = give_current_material(ob, i + 1);
- Image *ima = (ma && ma->texpaintslot) ? ma->texpaintslot[ma->paint_active_slot].ima :
- NULL;
- int interp = (ma && ma->texpaintslot) ? ma->texpaintslot[ma->paint_active_slot].interp :
- 0;
- GPUTexture *tex = GPU_texture_from_blender(ima, NULL, GL_TEXTURE_2D, false);
-
- if (tex) {
- DRWShadingGroup *grp = create_texture_paint_shading_group(
- psl, tex, draw_ctx, interp == SHD_INTERP_CLOSEST);
- stl->g_data->shgroup_image_array[i] = grp;
- }
- else {
- stl->g_data->shgroup_image_array[i] = NULL;
- }
- }
- }
- else {
- Image *ima = imapaint->canvas;
- GPUTexture *tex = GPU_texture_from_blender(ima, NULL, GL_TEXTURE_2D, false);
+ 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);
+ }
+ psl->image_faces = pass;
+ stl->g_data->shgroup_fallback = shgrp;
+ }
+
+ MEM_SAFE_FREE(stl->g_data->shgroup_image_array);
+
+ Object *ob = draw_ctx->obact;
+ if (ob && ob->type == OB_MESH) {
+ Scene *scene = draw_ctx->scene;
+ const ImagePaintSettings *imapaint = &scene->toolsettings->imapaint;
+ const bool use_material_slots = (imapaint->mode == IMAGEPAINT_MODE_MATERIAL);
+ const Mesh *me = ob->data;
+ const int mat_nr = max_ii(1, me->totcol);
+
+ stl->g_data->shgroup_image_array = MEM_mallocN(
+ sizeof(*stl->g_data->shgroup_image_array) * (use_material_slots ? mat_nr : 1), __func__);
+
+ if (use_material_slots) {
+ for (int i = 0; i < mat_nr; i++) {
+ Material *ma = give_current_material(ob, i + 1);
+ Image *ima = (ma && ma->texpaintslot) ? ma->texpaintslot[ma->paint_active_slot].ima : NULL;
+ int interp = (ma && ma->texpaintslot) ? ma->texpaintslot[ma->paint_active_slot].interp : 0;
+ GPUTexture *tex = GPU_texture_from_blender(ima, NULL, GL_TEXTURE_2D);
if (tex) {
DRWShadingGroup *grp = create_texture_paint_shading_group(
- psl, tex, draw_ctx, imapaint->interp == IMAGEPAINT_INTERP_CLOSEST);
- stl->g_data->shgroup_image_array[0] = grp;
+ psl, tex, draw_ctx, interp == SHD_INTERP_CLOSEST);
+ stl->g_data->shgroup_image_array[i] = grp;
}
else {
- stl->g_data->shgroup_image_array[0] = NULL;
+ stl->g_data->shgroup_image_array[i] = NULL;
}
}
}
+ else {
+ Image *ima = imapaint->canvas;
+ GPUTexture *tex = GPU_texture_from_blender(ima, NULL, GL_TEXTURE_2D);
+
+ if (tex) {
+ DRWShadingGroup *grp = create_texture_paint_shading_group(
+ psl, tex, draw_ctx, imapaint->interp == IMAGEPAINT_INTERP_CLOSEST);
+ stl->g_data->shgroup_image_array[0] = grp;
+ }
+ else {
+ stl->g_data->shgroup_image_array[0] = NULL;
+ }
+ }
}
/* Face Mask */
{
- psl->wire_overlay = 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 Mask Pass",
+ (DRW_STATE_WRITE_COLOR | DRW_STATE_WRITE_DEPTH |
+ DRW_STATE_DEPTH_LESS_EQUAL | DRW_STATE_OFFSET_NEGATIVE));
+ DRWShadingGroup *shgrp = DRW_shgroup_create(sh_data->wire_select_overlay, pass);
+
+ DRW_shgroup_uniform_block(shgrp, "globalsBlock", G_draw.block_ubo);
- stl->g_data->lwire_shgrp = DRW_shgroup_create(e_data.wire_overlay_shader, psl->wire_overlay);
- DRW_shgroup_uniform_block(stl->g_data->lwire_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);
+ }
+ psl->wire_select_overlay = pass;
+ stl->g_data->lwire_select_shgrp = shgrp;
}
{
- psl->face_overlay = DRW_pass_create("Face Mask Pass",
- DRW_STATE_WRITE_COLOR | DRW_STATE_WRITE_DEPTH |
- DRW_STATE_DEPTH_LESS_EQUAL | DRW_STATE_BLEND);
-
- stl->g_data->face_shgrp = DRW_shgroup_create(e_data.face_overlay_shader, psl->face_overlay);
+ DRWPass *pass = DRW_pass_create("Face Mask Pass",
+ DRW_STATE_WRITE_COLOR | DRW_STATE_WRITE_DEPTH |
+ DRW_STATE_DEPTH_LESS_EQUAL | DRW_STATE_BLEND);
+ 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(stl->g_data->face_shgrp, "color", col, 1);
+ 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);
+ }
+ psl->face_select_overlay = pass;
+ stl->g_data->face_select_shgrp = shgrp;
}
}
@@ -308,24 +356,23 @@ static void PAINT_TEXTURE_cache_populate(void *vedata, Object *ob)
for (int i = 0; i < mat_nr; i++) {
const int index = use_material_slots ? i : 0;
if ((i < me->totcol) && stl->g_data->shgroup_image_array[index]) {
- DRW_shgroup_call_add(
- stl->g_data->shgroup_image_array[index], geom_array[i], ob->obmat);
+ DRW_shgroup_call(stl->g_data->shgroup_image_array[index], geom_array[i], ob->obmat);
}
else {
- DRW_shgroup_call_add(stl->g_data->shgroup_fallback, geom_array[i], ob->obmat);
+ DRW_shgroup_call(stl->g_data->shgroup_fallback, geom_array[i], ob->obmat);
}
}
}
else {
if (stl->g_data->shgroup_image_array[0]) {
struct GPUBatch *geom = DRW_cache_mesh_surface_texpaint_single_get(ob);
- DRW_shgroup_call_add(stl->g_data->shgroup_image_array[0], geom, ob->obmat);
+ DRW_shgroup_call(stl->g_data->shgroup_image_array[0], geom, ob->obmat);
}
}
}
else {
struct GPUBatch *geom = DRW_cache_mesh_surface_get(ob);
- DRW_shgroup_call_add(stl->g_data->shgroup_fallback, geom, ob->obmat);
+ DRW_shgroup_call(stl->g_data->shgroup_fallback, geom, ob->obmat);
}
}
@@ -333,10 +380,10 @@ static void PAINT_TEXTURE_cache_populate(void *vedata, Object *ob)
if (use_face_sel) {
struct GPUBatch *geom;
geom = DRW_cache_mesh_surface_edges_get(ob);
- DRW_shgroup_call_add(stl->g_data->lwire_shgrp, geom, ob->obmat);
+ DRW_shgroup_call(stl->g_data->lwire_select_shgrp, geom, ob->obmat);
geom = DRW_cache_mesh_surface_get(ob);
- DRW_shgroup_call_add(stl->g_data->face_shgrp, geom, ob->obmat);
+ DRW_shgroup_call(stl->g_data->face_select_shgrp, geom, ob->obmat);
}
}
}
@@ -367,8 +414,8 @@ static void PAINT_TEXTURE_draw_scene(void *vedata)
DRW_draw_pass(psl->image_faces);
- DRW_draw_pass(psl->face_overlay);
- DRW_draw_pass(psl->wire_overlay);
+ DRW_draw_pass(psl->face_select_overlay);
+ DRW_draw_pass(psl->wire_select_overlay);
}
/* Cleanup when destroying the engine.
@@ -376,10 +423,15 @@ static void PAINT_TEXTURE_draw_scene(void *vedata)
* Mostly used for freeing shaders */
static void PAINT_TEXTURE_engine_free(void)
{
- DRW_SHADER_FREE_SAFE(e_data.image_sh);
- DRW_SHADER_FREE_SAFE(e_data.image_masking_sh);
- DRW_SHADER_FREE_SAFE(e_data.wire_overlay_shader);
- DRW_SHADER_FREE_SAFE(e_data.face_overlay_shader);
+ for (int sh_data_index = 0; sh_data_index < ARRAY_SIZE(e_data.sh_data); sh_data_index++) {
+ PAINT_TEXTURE_Shaders *sh_data = &e_data.sh_data[sh_data_index];
+ /* Don't free builtins. */
+ sh_data->fallback = NULL;
+ GPUShader **sh_data_as_array = (GPUShader **)sh_data;
+ for (int i = 0; i < (sizeof(PAINT_TEXTURE_Shaders) / sizeof(GPUShader *)); i++) {
+ DRW_SHADER_FREE_SAFE(sh_data_as_array[i]);
+ }
+ }
}
static const DrawEngineDataSize PAINT_TEXTURE_data_size = DRW_VIEWPORT_DATA_SIZE(
diff --git a/source/blender/draw/modes/paint_vertex_mode.c b/source/blender/draw/modes/paint_vertex_mode.c
index ef3af1255eb..815cf09487e 100644
--- a/source/blender/draw/modes/paint_vertex_mode.c
+++ b/source/blender/draw/modes/paint_vertex_mode.c
@@ -42,6 +42,7 @@ extern char datatoc_paint_wire_vert_glsl[];
extern char datatoc_paint_wire_frag_glsl[];
extern char datatoc_paint_vert_frag_glsl[];
extern char datatoc_common_globals_lib_glsl[];
+extern char datatoc_common_view_lib_glsl[];
extern char datatoc_gpu_shader_uniform_color_frag_glsl[];
@@ -108,19 +109,20 @@ static void PAINT_VERTEX_engine_init(void *UNUSED(vedata))
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) {
sh_data->by_mode[VERTEX_MODE].color_face = GPU_shader_create_from_arrays({
- .vert = (const char *[]){sh_cfg_data->lib, datatoc_paint_vertex_vert_glsl, NULL},
+ .vert = (const char *[]){sh_cfg_data->lib,
+ datatoc_common_view_lib_glsl,
+ datatoc_paint_vertex_vert_glsl,
+ NULL},
.frag = (const char *[]){datatoc_paint_vertex_frag_glsl, NULL},
.defs = (const char *[]){sh_cfg_data->def, NULL},
});
sh_data->by_mode[WEIGHT_MODE].color_face = GPU_shader_create_from_arrays({
.vert = (const char *[]){sh_cfg_data->lib,
+ datatoc_common_view_lib_glsl,
datatoc_common_globals_lib_glsl,
datatoc_paint_weight_vert_glsl,
NULL},
@@ -131,13 +133,17 @@ static void PAINT_VERTEX_engine_init(void *UNUSED(vedata))
});
sh_data->face_select_overlay = GPU_shader_create_from_arrays({
- .vert = (const char *[]){sh_cfg_data->lib, datatoc_paint_face_vert_glsl, NULL},
+ .vert = (const char *[]){sh_cfg_data->lib,
+ datatoc_common_view_lib_glsl,
+ datatoc_paint_face_vert_glsl,
+ NULL},
.frag = (const char *[]){datatoc_gpu_shader_uniform_color_frag_glsl, NULL},
.defs = (const char *[]){sh_cfg_data->def, NULL},
});
sh_data->vert_select_overlay = GPU_shader_create_from_arrays({
.vert = (const char *[]){sh_cfg_data->lib,
datatoc_common_globals_lib_glsl,
+ datatoc_common_view_lib_glsl,
datatoc_paint_wire_vert_glsl,
NULL},
.frag = (const char *[]){datatoc_paint_vert_frag_glsl, NULL},
@@ -152,6 +158,7 @@ static void PAINT_VERTEX_engine_init(void *UNUSED(vedata))
sh_data->by_mode[i].wire_overlay = GPU_shader_create_from_arrays({
.vert = (const char *[]){sh_cfg_data->lib,
datatoc_common_globals_lib_glsl,
+ datatoc_common_view_lib_glsl,
datatoc_paint_wire_vert_glsl,
NULL},
.frag = (const char *[]){datatoc_paint_wire_frag_glsl, NULL},
@@ -160,6 +167,7 @@ static void PAINT_VERTEX_engine_init(void *UNUSED(vedata))
sh_data->by_mode[i].wire_select_overlay = GPU_shader_create_from_arrays({
.vert = (const char *[]){sh_cfg_data->lib,
datatoc_common_globals_lib_glsl,
+ datatoc_common_view_lib_glsl,
datatoc_paint_wire_vert_glsl,
NULL},
.frag = (const char *[]){datatoc_paint_wire_frag_glsl, NULL},
@@ -301,24 +309,24 @@ static void PAINT_VERTEX_cache_populate(void *vedata, Object *ob)
}
}
if (geom != NULL) {
- DRW_shgroup_call_add(stl->g_data->by_mode[draw_mode].color_shgrp, geom, ob->obmat);
+ DRW_shgroup_call(stl->g_data->by_mode[draw_mode].color_shgrp, geom, ob->obmat);
}
if (use_face_sel || use_wire) {
DRWShadingGroup *shgrp = use_face_sel ? stl->g_data->by_mode[draw_mode].lwire_select_shgrp :
stl->g_data->by_mode[draw_mode].lwire_shgrp;
geom = DRW_cache_mesh_surface_edges_get(ob);
- DRW_shgroup_call_add(shgrp, geom, ob->obmat);
+ DRW_shgroup_call(shgrp, geom, ob->obmat);
}
if (use_face_sel) {
geom = DRW_cache_mesh_surface_get(ob);
- DRW_shgroup_call_add(stl->g_data->face_select_shgrp, geom, ob->obmat);
+ DRW_shgroup_call(stl->g_data->face_select_shgrp, geom, ob->obmat);
}
if (use_vert_sel) {
geom = DRW_cache_mesh_all_verts_get(ob);
- DRW_shgroup_call_add(stl->g_data->vert_select_shgrp, geom, ob->obmat);
+ DRW_shgroup_call(stl->g_data->vert_select_shgrp, geom, ob->obmat);
}
}
}
diff --git a/source/blender/draw/modes/particle_mode.c b/source/blender/draw/modes/particle_mode.c
index 600a29fecb4..ee35fa6d169 100644
--- a/source/blender/draw/modes/particle_mode.c
+++ b/source/blender/draw/modes/particle_mode.c
@@ -27,6 +27,8 @@
#include "BKE_pointcache.h"
+#include "BLI_string_utils.h"
+
#include "GPU_shader.h"
#include "draw_common.h"
@@ -39,6 +41,7 @@
extern char datatoc_particle_strand_vert_glsl[];
extern char datatoc_particle_strand_frag_glsl[];
extern char datatoc_common_globals_lib_glsl[];
+extern char datatoc_common_view_lib_glsl[];
/* *********** LISTS *********** */
@@ -86,23 +89,23 @@ typedef struct PARTICLE_PrivateData {
static void particle_engine_init(void *UNUSED(vedata))
{
if (!e_data.strands_shader) {
- e_data.strands_shader = DRW_shader_create_with_lib(datatoc_particle_strand_vert_glsl,
- NULL,
- datatoc_particle_strand_frag_glsl,
- datatoc_common_globals_lib_glsl,
- "");
+ char *lib = BLI_string_joinN(datatoc_common_globals_lib_glsl, datatoc_common_view_lib_glsl);
+
+ e_data.strands_shader = DRW_shader_create_with_lib(
+ datatoc_particle_strand_vert_glsl, NULL, datatoc_particle_strand_frag_glsl, lib, "");
e_data.strands_weight_shader = DRW_shader_create_with_lib(datatoc_particle_strand_vert_glsl,
NULL,
datatoc_particle_strand_frag_glsl,
- datatoc_common_globals_lib_glsl,
+ lib,
"#define USE_WEIGHT");
e_data.points_shader = DRW_shader_create_with_lib(datatoc_particle_strand_vert_glsl,
NULL,
datatoc_particle_strand_frag_glsl,
- datatoc_common_globals_lib_glsl,
+ lib,
"#define USE_POINTS");
+ MEM_freeN(lib);
}
}
@@ -120,10 +123,9 @@ static void particle_cache_init(void *vedata)
}
/* Create a pass */
- psl->psys_edit_pass = DRW_pass_create("PSys Edit Pass",
- (DRW_STATE_WRITE_COLOR | DRW_STATE_WRITE_DEPTH |
- DRW_STATE_DEPTH_LESS_EQUAL | DRW_STATE_WIRE |
- DRW_STATE_POINT));
+ psl->psys_edit_pass = DRW_pass_create(
+ "PSys Edit Pass",
+ (DRW_STATE_WRITE_COLOR | DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_LESS_EQUAL));
GPUShader *strand_shader = (use_weight) ? e_data.strands_weight_shader : e_data.strands_shader;
stl->g_data->strands_group = DRW_shgroup_create(strand_shader, psl->psys_edit_pass);
@@ -147,15 +149,15 @@ static void particle_edit_cache_populate(void *vedata,
{
struct GPUBatch *strands = DRW_cache_particles_get_edit_strands(
object, psys, edit, use_weight);
- DRW_shgroup_call_add(stl->g_data->strands_group, strands, NULL);
+ DRW_shgroup_call(stl->g_data->strands_group, strands, NULL);
}
if (pset->selectmode == SCE_SELECT_POINT) {
struct GPUBatch *points = DRW_cache_particles_get_edit_inner_points(object, psys, edit);
- DRW_shgroup_call_add(stl->g_data->inner_points_group, points, NULL);
+ DRW_shgroup_call(stl->g_data->inner_points_group, points, NULL);
}
if (ELEM(pset->selectmode, SCE_SELECT_POINT, SCE_SELECT_END)) {
struct GPUBatch *points = DRW_cache_particles_get_edit_tip_points(object, psys, edit);
- DRW_shgroup_call_add(stl->g_data->tip_points_group, points, NULL);
+ DRW_shgroup_call(stl->g_data->tip_points_group, points, NULL);
}
}
diff --git a/source/blender/draw/modes/pose_mode.c b/source/blender/draw/modes/pose_mode.c
index a37901a1fa9..08b6a99c453 100644
--- a/source/blender/draw/modes/pose_mode.c
+++ b/source/blender/draw/modes/pose_mode.c
@@ -138,7 +138,7 @@ static void POSE_cache_init(void *vedata)
psl->bone_envelope[i] = DRW_pass_create("Bone Envelope Outline Pass", state);
state = DRW_STATE_WRITE_COLOR | DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_LESS_EQUAL |
- DRW_STATE_BLEND | DRW_STATE_WIRE;
+ DRW_STATE_BLEND;
psl->relationship[i] = DRW_pass_create("Bone Relationship Pass", state);
ppd->custom_shapes[i] = BLI_ghash_ptr_new(__func__);
@@ -226,10 +226,10 @@ static void POSE_cache_populate(void *vedata, Object *ob)
struct GPUBatch *geom = DRW_cache_object_surface_get(ob);
if (geom) {
if (POSE_is_driven_by_active_armature(ob)) {
- DRW_shgroup_call_object_add(ppd->bone_selection_shgrp, geom, ob);
+ DRW_shgroup_call_object(ppd->bone_selection_shgrp, geom, ob);
}
else {
- DRW_shgroup_call_object_add(ppd->bone_selection_invert_shgrp, geom, ob);
+ DRW_shgroup_call_object(ppd->bone_selection_invert_shgrp, geom, ob);
}
}
}
diff --git a/source/blender/draw/modes/sculpt_mode.c b/source/blender/draw/modes/sculpt_mode.c
index 8adae0a4238..363476445c1 100644
--- a/source/blender/draw/modes/sculpt_mode.c
+++ b/source/blender/draw/modes/sculpt_mode.c
@@ -37,6 +37,7 @@
#include "draw_common.h"
#include "draw_mode_engines.h"
+extern char datatoc_common_view_lib_glsl[];
extern char datatoc_sculpt_mask_vert_glsl[];
extern char datatoc_gpu_shader_3D_smooth_color_frag_glsl[];
@@ -90,18 +91,11 @@ typedef struct SCULPT_Data {
/* *********** STATIC *********** */
static struct {
- /* Custom shaders :
- * Add sources to source/blender/draw/modes/shaders
- * init in SCULPT_engine_init();
- * free in SCULPT_engine_free(); */
- struct GPUShader *shader_smooth;
+ struct GPUShader *shader_mask;
} e_data = {NULL}; /* Engine data */
typedef struct SCULPT_PrivateData {
- /* This keeps the references of the shading groups for
- * easy access in SCULPT_cache_populate() */
- DRWShadingGroup *group_flat;
- DRWShadingGroup *group_smooth;
+ DRWShadingGroup *mask_overlay_grp;
} SCULPT_PrivateData; /* Transient data */
/* *********** FUNCTIONS *********** */
@@ -117,9 +111,12 @@ static void SCULPT_engine_init(void *vedata)
UNUSED_VARS(txl, fbl, stl);
- if (!e_data.shader_smooth) {
- e_data.shader_smooth = DRW_shader_create(
- datatoc_sculpt_mask_vert_glsl, NULL, datatoc_gpu_shader_3D_smooth_color_frag_glsl, NULL);
+ if (!e_data.shader_mask) {
+ e_data.shader_mask = DRW_shader_create_with_lib(datatoc_sculpt_mask_vert_glsl,
+ NULL,
+ datatoc_gpu_shader_3D_smooth_color_frag_glsl,
+ datatoc_common_view_lib_glsl,
+ NULL);
}
}
@@ -141,47 +138,9 @@ static void SCULPT_cache_init(void *vedata)
DRWState state = DRW_STATE_WRITE_COLOR | DRW_STATE_DEPTH_EQUAL | DRW_STATE_MULTIPLY;
psl->pass = DRW_pass_create("Sculpt Pass", state);
- DRWShadingGroup *shgrp = DRW_shgroup_create(e_data.shader_smooth, psl->pass);
+ DRWShadingGroup *shgrp = DRW_shgroup_create(e_data.shader_mask, psl->pass);
DRW_shgroup_uniform_float(shgrp, "maskOpacity", &v3d->overlay.sculpt_mode_mask_opacity, 1);
- stl->g_data->group_smooth = shgrp;
- }
-}
-
-static void sculpt_draw_mask_cb(DRWShadingGroup *shgroup,
- void (*draw_fn)(DRWShadingGroup *shgroup, struct GPUBatch *geom),
- void *user_data)
-{
- Object *ob = user_data;
- PBVH *pbvh = ob->sculpt->pbvh;
-
- if (pbvh) {
- BKE_pbvh_draw_cb(pbvh,
- NULL,
- NULL,
- false,
- false,
- true,
- false,
- (void (*)(void *, struct GPUBatch *))draw_fn,
- shgroup);
- }
-}
-
-static void sculpt_update_pbvh_normals(Object *object)
-{
- Mesh *mesh = object->data;
- PBVH *pbvh = object->sculpt->pbvh;
- SubdivCCG *subdiv_ccg = mesh->runtime.subdiv_ccg;
- if (pbvh == NULL || subdiv_ccg == NULL) {
- return;
- }
- BKE_sculpt_bvh_update_from_ccg(pbvh, subdiv_ccg);
- struct CCGFace **faces;
- int num_faces;
- BKE_pbvh_get_grid_updates(pbvh, 1, (void ***)&faces, &num_faces);
- if (num_faces > 0) {
- BKE_subdiv_ccg_update_normals(subdiv_ccg, faces, num_faces);
- MEM_freeN(faces);
+ stl->g_data->mask_overlay_grp = shgrp;
}
}
@@ -197,73 +156,24 @@ static void SCULPT_cache_populate(void *vedata, Object *ob)
const DRWContextState *draw_ctx = DRW_context_state_get();
if (ob->sculpt && (ob == draw_ctx->obact)) {
- sculpt_update_pbvh_normals(ob);
-
- /* XXX, needed for dyntopo-undo (which clears).
- * probably depsgraph should handlle? in 2.7x
- * getting derived-mesh does this (mesh_build_data). */
- if (ob->sculpt->pbvh == NULL) {
- /* create PBVH immediately (would be created on the fly too,
- * but this avoids waiting on first stroke) */
- Scene *scene = draw_ctx->scene;
-
- BKE_sculpt_update_mesh_elements(
- draw_ctx->depsgraph, scene, scene->toolsettings->sculpt, ob, false, false);
- }
-
PBVH *pbvh = ob->sculpt->pbvh;
if (pbvh && pbvh_has_mask(pbvh)) {
- DRW_shgroup_call_generate_add(
- stl->g_data->group_smooth, sculpt_draw_mask_cb, ob, ob->obmat);
+ DRW_shgroup_call_sculpt(stl->g_data->mask_overlay_grp, ob, false, true, false);
}
}
}
}
-/* Optional: Post-cache_populate callback */
-static void SCULPT_cache_finish(void *vedata)
-{
- SCULPT_PassList *psl = ((SCULPT_Data *)vedata)->psl;
- SCULPT_StorageList *stl = ((SCULPT_Data *)vedata)->stl;
-
- /* Do something here! dependent on the objects gathered */
- UNUSED_VARS(psl, stl);
-}
-
-/* Draw time ! Control rendering pipeline from here */
static void SCULPT_draw_scene(void *vedata)
{
SCULPT_PassList *psl = ((SCULPT_Data *)vedata)->psl;
- SCULPT_FramebufferList *fbl = ((SCULPT_Data *)vedata)->fbl;
-
- /* Default framebuffer and texture */
- DefaultFramebufferList *dfbl = DRW_viewport_framebuffer_list_get();
- DefaultTextureList *dtxl = DRW_viewport_texture_list_get();
-
- UNUSED_VARS(fbl, dfbl, dtxl);
- /* Show / hide entire passes, swap framebuffers ... whatever you fancy */
- /*
- * DRW_framebuffer_texture_detach(dtxl->depth);
- * DRW_framebuffer_bind(fbl->custom_fb);
- * DRW_draw_pass(psl->pass);
- * DRW_framebuffer_texture_attach(dfbl->default_fb, dtxl->depth, 0, 0);
- * DRW_framebuffer_bind(dfbl->default_fb);
- */
-
- /* ... or just 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 */
}
-/* Cleanup when destroying the engine.
- * This is not per viewport ! only when quitting blender.
- * Mostly used for freeing shaders */
static void SCULPT_engine_free(void)
{
- DRW_SHADER_FREE_SAFE(e_data.shader_smooth);
+ DRW_SHADER_FREE_SAFE(e_data.shader_mask);
}
static const DrawEngineDataSize SCULPT_data_size = DRW_VIEWPORT_DATA_SIZE(SCULPT_Data);
@@ -277,7 +187,7 @@ DrawEngineType draw_engine_sculpt_type = {
&SCULPT_engine_free,
&SCULPT_cache_init,
&SCULPT_cache_populate,
- &SCULPT_cache_finish,
+ NULL,
NULL, /* draw_background but not needed by mode engines */
&SCULPT_draw_scene,
NULL,
diff --git a/source/blender/draw/modes/shaders/armature_axes_vert.glsl b/source/blender/draw/modes/shaders/armature_axes_vert.glsl
index a689dce4d70..d7ed3e9ab71 100644
--- a/source/blender/draw/modes/shaders/armature_axes_vert.glsl
+++ b/source/blender/draw/modes/shaders/armature_axes_vert.glsl
@@ -1,9 +1,7 @@
uniform mat4 ViewProjectionMatrix;
uniform vec3 screenVecs[3];
-#ifdef USE_WORLD_CLIP_PLANES
-uniform mat4 ModelMatrix;
-#endif
+
/* ---- Instantiated Attrs ---- */
in float axis; /* position on the axis. [0.0-1.0] is X axis, [1.0-2.0] is Y, etc... */
in vec2 screenPos;
@@ -32,6 +30,6 @@ void main()
finalColor.a = 1.0;
#ifdef USE_WORLD_CLIP_PLANES
- world_clip_planes_calc_clip_distance((ModelMatrix * pos_4d).xyz);
+ world_clip_planes_calc_clip_distance(pos_4d.xyz);
#endif
}
diff --git a/source/blender/draw/modes/shaders/armature_envelope_outline_vert.glsl b/source/blender/draw/modes/shaders/armature_envelope_outline_vert.glsl
index 1e7fc4d11b8..c0bde90bf28 100644
--- a/source/blender/draw/modes/shaders/armature_envelope_outline_vert.glsl
+++ b/source/blender/draw/modes/shaders/armature_envelope_outline_vert.glsl
@@ -3,9 +3,6 @@ uniform mat4 ViewMatrix;
uniform mat4 ViewMatrixInverse;
uniform mat4 ViewProjectionMatrix;
uniform mat4 ProjectionMatrix;
-#ifdef USE_WORLD_CLIP_PLANES
-uniform mat4 ModelMatrix;
-#endif
uniform vec2 viewportSize;
uniform float lineThickness = 2.0;
@@ -145,7 +142,7 @@ void main()
vec4 pos_4d = vec4(wpos1, 1.0);
#ifdef USE_WORLD_CLIP_PLANES
- world_clip_planes_calc_clip_distance((ModelMatrix * pos_4d).xyz);
+ world_clip_planes_calc_clip_distance(pos_4d.xyz);
#endif
vec4 V = ViewMatrix * pos_4d;
diff --git a/source/blender/draw/modes/shaders/armature_envelope_solid_vert.glsl b/source/blender/draw/modes/shaders/armature_envelope_solid_vert.glsl
index 7f8ccc0c95a..d9567bb84f4 100644
--- a/source/blender/draw/modes/shaders/armature_envelope_solid_vert.glsl
+++ b/source/blender/draw/modes/shaders/armature_envelope_solid_vert.glsl
@@ -2,9 +2,6 @@
uniform mat4 ViewMatrix;
uniform mat4 ViewMatrixInverse;
uniform mat4 ViewProjectionMatrix;
-#ifdef USE_WORLD_CLIP_PLANES
-uniform mat4 ModelMatrix;
-#endif
/* ---- Instantiated Attrs ---- */
in vec3 pos;
@@ -57,6 +54,6 @@ void main()
vec4 pos_4d = vec4(sp, 1.0);
gl_Position = ViewProjectionMatrix * pos_4d;
#ifdef USE_WORLD_CLIP_PLANES
- world_clip_planes_calc_clip_distance((ModelMatrix * pos_4d).xyz);
+ world_clip_planes_calc_clip_distance(pos_4d.xyz);
#endif
}
diff --git a/source/blender/draw/modes/shaders/armature_shape_outline_geom.glsl b/source/blender/draw/modes/shaders/armature_shape_outline_geom.glsl
index 54315863a2e..dc84b8924d1 100644
--- a/source/blender/draw/modes/shaders/armature_shape_outline_geom.glsl
+++ b/source/blender/draw/modes/shaders/armature_shape_outline_geom.glsl
@@ -9,7 +9,6 @@ in vec2 ssNor[];
in vec4 vColSize[];
flat out vec4 finalColor;
-uniform mat4 ProjectionMatrix;
uniform vec2 viewportSize;
uniform float lineThickness = 2.0;
diff --git a/source/blender/draw/modes/shaders/armature_shape_outline_vert.glsl b/source/blender/draw/modes/shaders/armature_shape_outline_vert.glsl
index 82a483d91a5..fb2735c196c 100644
--- a/source/blender/draw/modes/shaders/armature_shape_outline_vert.glsl
+++ b/source/blender/draw/modes/shaders/armature_shape_outline_vert.glsl
@@ -1,8 +1,4 @@
-uniform mat3 NormalMatrix;
-
-uniform mat4 ViewMatrix;
-uniform mat4 ProjectionMatrix;
uniform vec2 viewportSize;
/* ---- Instantiated Attrs ---- */
@@ -27,20 +23,19 @@ vec2 proj(vec4 pos)
void main()
{
- /* This is slow and run per vertex, but it's still faster than
- * doing it per instance on CPU and sending it on via instance attribute. */
- mat3 NormalMatrix = transpose(inverse(mat3(ViewMatrix * InstanceModelMatrix)));
-
vec4 worldPosition = InstanceModelMatrix * vec4(pos, 1.0);
vec4 viewpos = ViewMatrix * worldPosition;
vPos = viewpos.xyz;
pPos = ProjectionMatrix * viewpos;
+ /* This is slow and run per vertex, but it's still faster than
+ * doing it per instance on CPU and sending it on via instance attribute. */
+ mat3 normal_mat = transpose(inverse(mat3(InstanceModelMatrix)));
/* TODO FIX: there is still a problem with this vector
* when the bone is scaled or in persp mode. But it's
* barelly visible at the outline corners. */
- ssNor = normalize((NormalMatrix * snor).xy);
+ ssNor = normalize(normal_world_to_view(normal_mat * snor).xy);
ssPos = proj(pPos);
diff --git a/source/blender/draw/modes/shaders/armature_shape_solid_vert.glsl b/source/blender/draw/modes/shaders/armature_shape_solid_vert.glsl
index 2df25bf0e03..df6a9ce2d76 100644
--- a/source/blender/draw/modes/shaders/armature_shape_solid_vert.glsl
+++ b/source/blender/draw/modes/shaders/armature_shape_solid_vert.glsl
@@ -1,11 +1,4 @@
-uniform mat3 NormalMatrix;
-uniform mat4 ViewMatrixInverse;
-uniform mat4 ViewProjectionMatrix;
-
-uniform mat4 ViewMatrix;
-uniform mat4 ProjectionMatrix;
-
/* ---- Instantiated Attrs ---- */
in vec3 pos;
in vec3 nor;
@@ -19,8 +12,10 @@ out vec4 finalColor;
void main()
{
- mat3 NormalMatrix = transpose(inverse(mat3(ViewMatrix * InstanceModelMatrix)));
- vec3 normal = normalize(NormalMatrix * nor);
+ /* This is slow and run per vertex, but it's still faster than
+ * doing it per instance on CPU and sending it on via instance attribute. */
+ mat3 normal_mat = transpose(inverse(mat3(InstanceModelMatrix)));
+ vec3 normal = normalize(normal_world_to_view(normal_mat * nor));
/* Do lighting at an angle to avoid flat shading on front facing bone. */
const vec3 light = vec3(0.1, 0.1, 0.8);
diff --git a/source/blender/draw/modes/shaders/armature_stick_vert.glsl b/source/blender/draw/modes/shaders/armature_stick_vert.glsl
index 9e5a3d76c0d..fd8a12fcd2c 100644
--- a/source/blender/draw/modes/shaders/armature_stick_vert.glsl
+++ b/source/blender/draw/modes/shaders/armature_stick_vert.glsl
@@ -1,7 +1,7 @@
uniform mat4 ProjectionMatrix;
uniform mat4 ViewProjectionMatrix;
-uniform mat4 ModelMatrix;
+
uniform mat4 ViewMatrix;
uniform vec2 viewportSize;
@@ -88,8 +88,7 @@ void main()
gl_Position.z += (is_bone) ? 0.0 : 1e-6; /* Avoid Z fighting of head/tails. */
#ifdef USE_WORLD_CLIP_PLANES
- world_clip_planes_calc_clip_distance(
- (ModelMatrix * (is_head ? boneStart_4d : boneEnd_4d)).xyz);
+ world_clip_planes_calc_clip_distance((is_head ? boneStart_4d : boneEnd_4d).xyz);
#endif
}
else {
diff --git a/source/blender/draw/modes/shaders/common_fullscreen_vert.glsl b/source/blender/draw/modes/shaders/common_fullscreen_vert.glsl
index a1e6bb0f43d..8a7fb97d98c 100644
--- a/source/blender/draw/modes/shaders/common_fullscreen_vert.glsl
+++ b/source/blender/draw/modes/shaders/common_fullscreen_vert.glsl
@@ -1,10 +1,11 @@
-in vec2 pos;
-in vec2 uvs;
out vec4 uvcoordsvar;
void main()
{
- uvcoordsvar = vec4(uvs, 0.0, 0.0);
- gl_Position = vec4(pos, 1.0, 1.0);
+ int v = gl_VertexID % 3;
+ float x = -1.0 + float((v & 1) << 2);
+ float y = -1.0 + float((v & 2) << 1);
+ gl_Position = vec4(x, y, 1.0, 1.0);
+ uvcoordsvar = vec4((gl_Position.xy + 1.0) * 0.5, 0.0, 0.0);
}
diff --git a/source/blender/draw/modes/shaders/common_hair_lib.glsl b/source/blender/draw/modes/shaders/common_hair_lib.glsl
index 1c0a31c59fd..f9c3df34658 100644
--- a/source/blender/draw/modes/shaders/common_hair_lib.glsl
+++ b/source/blender/draw/modes/shaders/common_hair_lib.glsl
@@ -160,9 +160,9 @@ void hair_get_pos_tan_binor_time(bool is_persp,
}
wpos = (hairDupliMatrix * vec4(wpos, 1.0)).xyz;
- wtan = mat3(hairDupliMatrix) * wtan;
+ wtan = -normalize(mat3(hairDupliMatrix) * wtan);
- vec3 camera_vec = (is_persp) ? wpos - camera_pos : -camera_z;
+ vec3 camera_vec = (is_persp) ? camera_pos - wpos : camera_z;
wbinor = normalize(cross(camera_vec, wtan));
thickness = hair_shaperadius(hairRadShape, hairRadRoot, hairRadTip, time);
diff --git a/source/blender/draw/modes/shaders/common_view_lib.glsl b/source/blender/draw/modes/shaders/common_view_lib.glsl
index de9c4e2a96e..845c615c75c 100644
--- a/source/blender/draw/modes/shaders/common_view_lib.glsl
+++ b/source/blender/draw/modes/shaders/common_view_lib.glsl
@@ -9,7 +9,51 @@ layout(std140) uniform viewBlock
mat4 ProjectionMatrix;
mat4 ProjectionMatrixInverse;
- vec4 CameraTexCoFactors;
+ vec4 clipPlanes[6];
- vec4 clipPlanes[2];
+ /* TODO move it elsewhere. */
+ vec4 CameraTexCoFactors;
};
+
+uniform mat4 ModelMatrix;
+uniform mat4 ModelMatrixInverse;
+
+/** Transform shortcuts. */
+/* Rule of thumb: Try to reuse world positions and normals because converting though viewspace
+ * will always be decomposed in at least 2 matrix operation. */
+
+/**
+ * Some clarification:
+ * Usually Normal matrix is transpose(inverse(ViewMatrix * ModelMatrix))
+ *
+ * But since it is slow to multiply matrices we decompose it. Decomposing
+ * inversion and transposition both invert the product order leaving us with
+ * the same original order:
+ * transpose(ViewMatrixInverse) * transpose(ModelMatrixInverse)
+ *
+ * Knowing that the view matrix is orthogonal, the transpose is also the inverse.
+ * Note: This is only valid because we are only using the mat3 of the ViewMatrixInverse.
+ * ViewMatrix * transpose(ModelMatrixInverse)
+ **/
+#define normal_object_to_view(n) (mat3(ViewMatrix) * (transpose(mat3(ModelMatrixInverse)) * n))
+#define normal_object_to_world(n) (transpose(mat3(ModelMatrixInverse)) * n)
+#define normal_world_to_object(n) (transpose(mat3(ModelMatrix)) * n)
+#define normal_world_to_view(n) (mat3(ViewMatrix) * n)
+
+#define point_object_to_ndc(p) (ViewProjectionMatrix * vec4((ModelMatrix * vec4(p, 1.0)).xyz, 1.0))
+#define point_object_to_view(p) ((ViewMatrix * vec4((ModelMatrix * vec4(p, 1.0)).xyz, 1.0)).xyz)
+#define point_object_to_world(p) ((ModelMatrix * vec4(p, 1.0)).xyz)
+#define point_view_to_ndc(p) (ProjectionMatrix * vec4(p, 1.0))
+#define point_view_to_object(p) ((ModelMatrixInverse * (ViewMatrixInverse * vec4(p, 1.0))).xyz)
+#define point_view_to_world(p) ((ViewMatrixInverse * vec4(p, 1.0)).xyz)
+#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 b7166382b19..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
@@ -1,6 +1,4 @@
/* Draw Curve Handles */
-uniform mat4 ModelViewProjectionMatrix;
-uniform mat4 ModelMatrix;
in vec3 pos;
in int data;
@@ -9,11 +7,13 @@ flat out int vertFlag;
void main()
{
- vec4 pos_4d = vec4(pos, 1.0);
- gl_Position = ModelViewProjectionMatrix * pos_4d;
+ GPU_INTEL_VERTEX_SHADER_WORKAROUND
+
+ vec3 world_pos = point_object_to_world(pos);
+ gl_Position = point_world_to_ndc(world_pos);
vertFlag = data;
#ifdef USE_WORLD_CLIP_PLANES
- world_clip_planes_calc_clip_distance((ModelMatrix * pos_4d).xyz);
+ world_clip_planes_calc_clip_distance(world_pos);
#endif
}
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 4718f11db65..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
@@ -1,6 +1,5 @@
/* Draw Curve Vertices */
-uniform mat4 ModelViewProjectionMatrix;
-uniform mat4 ModelMatrix;
+
uniform vec2 viewportSize;
in vec3 pos;
@@ -10,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;
@@ -22,10 +23,10 @@ void main()
finalColor = colorVertex;
}
- vec4 pos_4d = vec4(pos, 1.0);
- gl_Position = ModelViewProjectionMatrix * pos_4d;
+ vec3 world_pos = point_object_to_world(pos);
+ gl_Position = point_world_to_ndc(world_pos);
gl_PointSize = sizeVertex * 2.0;
#ifdef USE_WORLD_CLIP_PLANES
- world_clip_planes_calc_clip_distance((ModelMatrix * pos_4d).xyz);
+ world_clip_planes_calc_clip_distance(world_pos);
#endif
}
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 02244086711..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
@@ -1,6 +1,5 @@
/* Draw Curve Normals */
-uniform mat4 ModelViewProjectionMatrix;
-uniform mat4 ModelMatrix;
+
uniform float normalSize;
in vec3 pos;
@@ -10,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;
@@ -18,10 +19,10 @@ void main()
final_pos += normalSize * rad * (flip * nor - tan);
}
- vec4 final_pos_4d = vec4(final_pos, 1.0);
- gl_Position = ModelViewProjectionMatrix * final_pos_4d;
+ vec3 world_pos = point_object_to_world(final_pos);
+ gl_Position = point_world_to_ndc(world_pos);
#ifdef USE_WORLD_CLIP_PLANES
- world_clip_planes_calc_clip_distance((ModelMatrix * final_pos_4d).xyz);
+ world_clip_planes_calc_clip_distance(world_pos);
#endif
}
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 3cf808f3c52..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
@@ -1,8 +1,5 @@
-
/* Draw Lattice Vertices */
-uniform mat4 ModelViewProjectionMatrix;
-uniform mat4 ModelMatrix;
uniform vec2 viewportSize;
in vec3 pos;
@@ -25,9 +22,12 @@ vec2 proj(vec4 pos)
void main()
{
+ GPU_INTEL_VERTEX_SHADER_WORKAROUND
+
clipCase = 0;
- vec4 pPos = ModelViewProjectionMatrix * vec4(pos, 1.0);
+ vec3 world_pos = point_object_to_world(pos);
+ vec4 pPos = point_world_to_ndc(world_pos);
/* only vertex position 0 is used */
eData1 = eData2 = vec4(1e10);
@@ -39,6 +39,6 @@ void main()
gl_Position = pPos;
#ifdef USE_WORLD_CLIP_PLANES
- world_clip_planes_calc_clip_distance((ModelMatrix * vec4(pos, 1.0)).xyz);
+ world_clip_planes_calc_clip_distance(world_pos);
#endif
}
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 c84d97fa1c5..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
@@ -1,6 +1,4 @@
-uniform mat4 ModelViewProjectionMatrix;
-uniform mat4 ModelMatrix;
uniform ivec4 dataMask = ivec4(0xFF);
in vec3 pos;
@@ -10,13 +8,16 @@ flat out vec4 faceColor;
void main()
{
- gl_Position = ModelViewProjectionMatrix * vec4(pos, 1.0);
+ GPU_INTEL_VERTEX_SHADER_WORKAROUND
+
+ vec3 world_pos = point_object_to_world(pos);
+ gl_Position = point_world_to_ndc(world_pos);
ivec4 data_m = data & dataMask;
faceColor = EDIT_MESH_face_color(data_m.x);
#ifdef USE_WORLD_CLIP_PLANES
- world_clip_planes_calc_clip_distance((ModelMatrix * vec4(pos, 1.0)).xyz);
+ world_clip_planes_calc_clip_distance(world_pos);
#endif
}
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 94d8d2e701c..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
@@ -1,5 +1,3 @@
-uniform mat4 ModelViewProjectionMatrix;
-uniform mat4 ModelMatrix;
in vec3 pos;
in vec4 weight_color;
@@ -14,10 +12,13 @@ out vec4 weightColor;
void main()
{
- gl_Position = ModelViewProjectionMatrix * vec4(pos, 1.0);
+ 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);
#ifdef USE_WORLD_CLIP_PLANES
- world_clip_planes_calc_clip_distance((ModelMatrix * vec4(pos, 1.0)).xyz);
+ world_clip_planes_calc_clip_distance(world_pos);
#endif
}
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 d700e69fb57..fabc317cf4f 100644
--- a/source/blender/draw/modes/shaders/edit_mesh_overlay_vert.glsl
+++ b/source/blender/draw/modes/shaders/edit_mesh_overlay_vert.glsl
@@ -1,9 +1,4 @@
-uniform mat3 NormalMatrix;
-uniform mat4 ProjectionMatrix;
-uniform mat4 ModelViewMatrix;
-uniform mat4 ModelViewProjectionMatrix;
-uniform mat4 ModelMatrix;
uniform float faceAlphaMod;
uniform ivec4 dataMask = ivec4(0xFF);
uniform float ofs;
@@ -25,14 +20,19 @@ out int selectOveride;
void main()
{
+ GPU_INTEL_VERTEX_SHADER_WORKAROUND
+
+ vec3 world_pos = point_object_to_world(pos);
+
#if !defined(FACE)
+ /* TODO override the ViewProjection Matrix for this case. */
mat4 projmat = ProjectionMatrix;
projmat[3][2] -= ofs;
- gl_Position = projmat * (ModelViewMatrix * vec4(pos, 1.0));
+ gl_Position = projmat * (ViewMatrix * vec4(world_pos, 1.0));
#else
- gl_Position = ModelViewProjectionMatrix * vec4(pos, 1.0);
+ gl_Position = point_world_to_ndc(world_pos);
#endif
ivec4 m_data = data & dataMask;
@@ -76,17 +76,16 @@ void main()
#if !defined(FACE)
/* Facing based color blend */
- vec4 vpos = ModelViewMatrix * vec4(pos, 1.0);
- vec3 view_normal = normalize(NormalMatrix * vnor + 1e-4);
- vec3 view_vec = (ProjectionMatrix[3][3] == 0.0) ? normalize(vpos.xyz) : vec3(0.0, 0.0, 1.0);
+ vec3 vpos = point_world_to_view(world_pos);
+ vec3 view_normal = normalize(normal_object_to_view(vnor) + 1e-4);
+ vec3 view_vec = (ProjectionMatrix[3][3] == 0.0) ? normalize(vpos) : vec3(0.0, 0.0, 1.0);
float facing = dot(view_vec, view_normal);
facing = 1.0 - abs(facing) * 0.2;
finalColor.rgb = mix(colorEditMeshMiddle.rgb, finalColor.rgb, facing);
-
#endif
#ifdef USE_WORLD_CLIP_PLANES
- world_clip_planes_calc_clip_distance((ModelMatrix * vec4(pos, 1.0)).xyz);
+ world_clip_planes_calc_clip_distance(world_pos);
#endif
}
diff --git a/source/blender/draw/modes/shaders/edit_normals_vert.glsl b/source/blender/draw/modes/shaders/edit_normals_vert.glsl
index 2e34a132cb0..384d13923f6 100644
--- a/source/blender/draw/modes/shaders/edit_normals_vert.glsl
+++ b/source/blender/draw/modes/shaders/edit_normals_vert.glsl
@@ -1,8 +1,4 @@
-uniform mat4 ModelViewProjectionMatrix;
-uniform mat3 NormalMatrix;
-uniform mat4 ProjectionMatrix;
-uniform mat4 ModelMatrix;
uniform float normalSize;
in vec3 pos;
@@ -25,10 +21,16 @@ flat out vec4 v2;
void main()
{
- v1 = ModelViewProjectionMatrix * vec4(pos, 1.0);
- vec3 n = normalize(NormalMatrix * nor); /* viewspace */
- v2 = v1 + ProjectionMatrix * vec4(n * normalSize, 0.0);
+ GPU_INTEL_VERTEX_SHADER_WORKAROUND
+
+ vec3 n = normalize(normal_object_to_world(nor));
+
+ vec3 world_pos = point_object_to_world(pos);
+
+ v1 = point_world_to_ndc(world_pos);
+ v2 = point_world_to_ndc(world_pos + n * normalSize);
+
#ifdef USE_WORLD_CLIP_PLANES
- world_clip_planes_calc_clip_distance((ModelMatrix * vec4(pos, 1.0)).xyz);
+ world_clip_planes_calc_clip_distance(world_pos);
#endif
}
diff --git a/source/blender/draw/modes/shaders/object_empty_axes_vert.glsl b/source/blender/draw/modes/shaders/object_empty_axes_vert.glsl
index 7fd955343fc..43c8e313fc3 100644
--- a/source/blender/draw/modes/shaders/object_empty_axes_vert.glsl
+++ b/source/blender/draw/modes/shaders/object_empty_axes_vert.glsl
@@ -1,8 +1,5 @@
uniform mat4 ViewProjectionMatrix;
-#ifdef USE_WORLD_CLIP_PLANES
-uniform mat4 ModelMatrix;
-#endif
uniform vec3 screenVecs[3];
@@ -33,6 +30,6 @@ void main()
finalColor = vec4(color, 1.0);
#ifdef USE_WORLD_CLIP_PLANES
- world_clip_planes_calc_clip_distance((ModelMatrix * pos_4d).xyz);
+ world_clip_planes_calc_clip_distance(pos_4d.xyz);
#endif
}
diff --git a/source/blender/draw/modes/shaders/object_empty_image_frag.glsl b/source/blender/draw/modes/shaders/object_empty_image_frag.glsl
index 386d05636f9..deb82a8904e 100644
--- a/source/blender/draw/modes/shaders/object_empty_image_frag.glsl
+++ b/source/blender/draw/modes/shaders/object_empty_image_frag.glsl
@@ -14,12 +14,33 @@ uniform sampler2D image;
uniform int depthMode;
uniform bool useAlphaTest;
+float linearrgb_to_srgb(float c)
+{
+ if (c < 0.0031308) {
+ return (c < 0.0) ? 0.0 : c * 12.92;
+ }
+ else {
+ return 1.055 * pow(c, 1.0 / 2.4) - 0.055;
+ }
+}
+
+vec4 texture_read_as_srgb(sampler2D tex, vec2 co)
+{
+ /* By convention image textures return scene linear colors, but
+ * overlays still assume srgb. */
+ vec4 color = texture(tex, co);
+ color.r = linearrgb_to_srgb(color.r);
+ color.g = linearrgb_to_srgb(color.g);
+ color.b = linearrgb_to_srgb(color.b);
+ return color;
+}
+
void main()
{
#ifdef USE_WIRE
fragColor = finalColor;
#else
- vec4 tex_col = texture(image, texCoord_interp);
+ vec4 tex_col = texture_read_as_srgb(image, texCoord_interp);
fragColor = finalColor * tex_col;
if (useAlphaTest) {
diff --git a/source/blender/draw/modes/shaders/object_empty_image_vert.glsl b/source/blender/draw/modes/shaders/object_empty_image_vert.glsl
index 9694c63fef1..36e86290be7 100644
--- a/source/blender/draw/modes/shaders/object_empty_image_vert.glsl
+++ b/source/blender/draw/modes/shaders/object_empty_image_vert.glsl
@@ -1,7 +1,5 @@
-uniform mat4 ModelViewProjectionMatrix;
-uniform mat4 ModelMatrix;
-uniform float aspectX;
-uniform float aspectY;
+
+uniform vec2 aspect;
uniform float size;
uniform vec2 offset;
#ifdef USE_WIRE
@@ -21,8 +19,9 @@ out vec2 texCoord_interp;
void main()
{
- vec4 pos_4d = vec4((pos + offset) * (size * vec2(aspectX, aspectY)), 0.0, 1.0);
- gl_Position = ModelViewProjectionMatrix * pos_4d;
+ vec3 pos = vec3((pos + offset) * (size * aspect), 0.0);
+ vec3 world_pos = point_object_to_world(pos);
+ gl_Position = point_world_to_ndc(world_pos);
#ifdef USE_WIRE
gl_Position.z -= 1e-5;
finalColor = vec4(color, 1.0);
@@ -32,6 +31,6 @@ void main()
#endif
#ifdef USE_WORLD_CLIP_PLANES
- world_clip_planes_calc_clip_distance((ModelMatrix * pos_4d).xyz);
+ world_clip_planes_calc_clip_distance(world_pos);
#endif
}
diff --git a/source/blender/draw/modes/shaders/object_grid_frag.glsl b/source/blender/draw/modes/shaders/object_grid_frag.glsl
index df2cfe7be82..a20f12efd93 100644
--- a/source/blender/draw/modes/shaders/object_grid_frag.glsl
+++ b/source/blender/draw/modes/shaders/object_grid_frag.glsl
@@ -8,10 +8,7 @@ in vec3 local_pos;
out vec4 FragColor;
-uniform mat4 ProjectionMatrix;
-uniform vec3 cameraPos;
uniform vec3 planeAxes;
-uniform vec3 eye;
uniform vec4 gridSettings;
uniform float meshSize;
uniform float lineKernel = 0.0;
@@ -23,6 +20,8 @@ uniform sampler2D depthBuffer;
#define gridScale gridSettings.z
#define gridSubdiv gridSettings.w
+#define cameraPos (ViewMatrixInverse[3].xyz)
+
uniform int gridFlag;
#define AXIS_X (1 << 0)
@@ -109,7 +108,7 @@ void main()
dist = 1.0; /* avoid branch after */
if ((gridFlag & PLANE_XY) != 0) {
- float angle = 1.0 - abs(eye.z);
+ float angle = 1.0 - abs(ViewMatrixInverse[2].z);
dist = 1.0 + angle * 2.0;
angle *= angle;
fade *= 1.0 - angle * angle;
diff --git a/source/blender/draw/modes/shaders/object_grid_vert.glsl b/source/blender/draw/modes/shaders/object_grid_vert.glsl
index e8f4b089b47..d247967b03a 100644
--- a/source/blender/draw/modes/shaders/object_grid_vert.glsl
+++ b/source/blender/draw/modes/shaders/object_grid_vert.glsl
@@ -2,9 +2,6 @@
/* Infinite grid
* Clément Foucault */
-uniform mat4 ViewProjectionMatrix;
-uniform mat4 ProjectionMatrix;
-uniform vec3 cameraPos;
uniform vec3 planeAxes;
uniform vec4 gridSettings;
uniform float meshSize;
@@ -16,6 +13,8 @@ uniform float meshSize;
uniform int gridFlag;
+#define cameraPos (ViewMatrixInverse[3].xyz)
+
#define PLANE_XY (1 << 4)
#define PLANE_XZ (1 << 5)
#define PLANE_YZ (1 << 6)
diff --git a/source/blender/draw/modes/shaders/object_mball_handles_vert.glsl b/source/blender/draw/modes/shaders/object_mball_handles_vert.glsl
index c395ed01bca..9414309570b 100644
--- a/source/blender/draw/modes/shaders/object_mball_handles_vert.glsl
+++ b/source/blender/draw/modes/shaders/object_mball_handles_vert.glsl
@@ -4,7 +4,6 @@
* Note that if the stiffness is zero, it assumes the scale is directly multiplied by the radius */
uniform mat4 ViewProjectionMatrix;
-uniform mat4 ModelMatrix;
uniform vec3 screen_vecs[2];
/* ---- Instantiated Attrs ---- */
@@ -32,6 +31,6 @@ void main()
finalColor = vec4(color, 1.0);
#ifdef USE_WORLD_CLIP_PLANES
- world_clip_planes_calc_clip_distance((ModelMatrix * world_pos).xyz);
+ world_clip_planes_calc_clip_distance(world_pos.xyz);
#endif
}
diff --git a/source/blender/draw/modes/shaders/object_outline_prepass_geom.glsl b/source/blender/draw/modes/shaders/object_outline_prepass_geom.glsl
index 97d4bdacf07..5a3eb38fb6b 100644
--- a/source/blender/draw/modes/shaders/object_outline_prepass_geom.glsl
+++ b/source/blender/draw/modes/shaders/object_outline_prepass_geom.glsl
@@ -2,8 +2,6 @@
layout(lines_adjacency) in;
layout(line_strip, max_vertices = 2) out;
-uniform mat4 ProjectionMatrix;
-
in vec4 pPos[];
in vec3 vPos[];
diff --git a/source/blender/draw/modes/shaders/object_outline_prepass_vert.glsl b/source/blender/draw/modes/shaders/object_outline_prepass_vert.glsl
index 0b5f4733ebc..e34afe95b5e 100644
--- a/source/blender/draw/modes/shaders/object_outline_prepass_vert.glsl
+++ b/source/blender/draw/modes/shaders/object_outline_prepass_vert.glsl
@@ -1,8 +1,4 @@
-uniform mat4 ModelViewMatrix;
-uniform mat4 ModelViewProjectionMatrix;
-uniform mat4 ModelMatrix;
-
in vec3 pos;
out vec4 pPos;
@@ -10,12 +6,13 @@ out vec3 vPos;
void main()
{
- vPos = (ModelViewMatrix * vec4(pos, 1.0)).xyz;
- pPos = ModelViewProjectionMatrix * vec4(pos, 1.0);
+ vec3 world_pos = point_object_to_world(pos);
+ vPos = point_world_to_view(world_pos);
+ pPos = point_world_to_ndc(world_pos);
/* Small bias to always be on top of the geom. */
pPos.z -= 1e-3;
#ifdef USE_WORLD_CLIP_PLANES
- world_clip_planes_calc_clip_distance((ModelMatrix * vec4(pos, 1.0)).xyz);
+ world_clip_planes_calc_clip_distance(world_pos);
#endif
}
diff --git a/source/blender/draw/modes/shaders/object_particle_dot_vert.glsl b/source/blender/draw/modes/shaders/object_particle_dot_vert.glsl
index e51b829adb5..f98ae9a9515 100644
--- a/source/blender/draw/modes/shaders/object_particle_dot_vert.glsl
+++ b/source/blender/draw/modes/shaders/object_particle_dot_vert.glsl
@@ -1,6 +1,4 @@
-uniform mat4 ModelViewMatrix;
-uniform mat4 ProjectionMatrix;
uniform float pixel_size;
uniform float size;
@@ -12,10 +10,13 @@ flat out float finalVal;
void main()
{
- gl_Position = ModelViewMatrix * vec4(pos, 1.0);
+ vec3 world_pos = point_object_to_world(pos);
- float psize = (ProjectionMatrix[3][3] == 0.0) ? (size / (-gl_Position.z * pixel_size)) :
- (size / pixel_size);
+ float view_z = dot(ViewMatrixInverse[2].xyz, world_pos - ViewMatrixInverse[3].xyz);
+
+ bool is_persp = (ProjectionMatrix[3][3] == 0.0);
+ float psize = (is_persp) ? (size / (-view_z * pixel_size)) : (size / pixel_size);
+ gl_Position = point_world_to_ndc(world_pos);
gl_PointSize = psize;
@@ -31,7 +32,5 @@ void main()
// convert to PointCoord units
radii /= psize;
- gl_Position = ProjectionMatrix * gl_Position;
-
finalVal = val;
}
diff --git a/source/blender/draw/modes/shaders/object_particle_prim_vert.glsl b/source/blender/draw/modes/shaders/object_particle_prim_vert.glsl
index 0f626626498..46aceb245f4 100644
--- a/source/blender/draw/modes/shaders/object_particle_prim_vert.glsl
+++ b/source/blender/draw/modes/shaders/object_particle_prim_vert.glsl
@@ -1,18 +1,17 @@
-uniform mat4 ModelViewProjectionMatrix;
-uniform mat4 ViewProjectionMatrix;
-uniform mat4 ModelViewMatrix;
-uniform mat4 ProjectionMatrix;
-uniform int screen_space;
+uniform bool screen_space;
uniform float draw_size;
uniform vec3 color;
uniform sampler1D ramp;
+/* ---- Instantiated Attrs ---- */
+in vec3 inst_pos;
+in int axis;
+
+/* ---- Per instance Attrs ---- */
in vec3 pos;
in vec4 rot;
in float val;
-in vec3 inst_pos;
-in int axis;
flat out vec4 finalColor;
@@ -24,8 +23,9 @@ vec3 rotate(vec3 vec, vec4 quat)
void main()
{
- if (screen_space == 1) {
- gl_Position = ModelViewMatrix * vec4(pos, 1.0) + vec4(inst_pos * draw_size, 0.0);
+ if (screen_space) {
+ gl_Position = ViewMatrix * (ModelMatrix * vec4(pos, 1.0));
+ gl_Position.xyz += inst_pos * draw_size;
gl_Position = ProjectionMatrix * gl_Position;
}
else {
@@ -35,7 +35,8 @@ void main()
size *= 2;
}
- gl_Position = ModelViewProjectionMatrix * vec4(pos + rotate(inst_pos * size, rot), 1.0);
+ vec3 pos_rot = pos + rotate(inst_pos * size, rot);
+ gl_Position = point_object_to_ndc(pos_rot);
}
#ifdef USE_AXIS
diff --git a/source/blender/draw/modes/shaders/overlay_face_orientation_vert.glsl b/source/blender/draw/modes/shaders/overlay_face_orientation_vert.glsl
index 659e3cbd5f5..2dd84c0a060 100644
--- a/source/blender/draw/modes/shaders/overlay_face_orientation_vert.glsl
+++ b/source/blender/draw/modes/shaders/overlay_face_orientation_vert.glsl
@@ -1,13 +1,12 @@
-uniform mat4 ModelViewProjectionMatrix;
-uniform mat4 ModelMatrix;
in vec3 pos;
void main()
{
- gl_Position = ModelViewProjectionMatrix * vec4(pos, 1.0);
+ vec3 world_pos = point_object_to_world(pos);
+ gl_Position = point_world_to_ndc(world_pos);
#ifdef USE_WORLD_CLIP_PLANES
- world_clip_planes_calc_clip_distance((ModelMatrix * vec4(pos, 1.0)).xyz);
+ world_clip_planes_calc_clip_distance(world_pos);
#endif
}
diff --git a/source/blender/draw/modes/shaders/overlay_face_wireframe_vert.glsl b/source/blender/draw/modes/shaders/overlay_face_wireframe_vert.glsl
index 96acba71233..23f64e6e49c 100644
--- a/source/blender/draw/modes/shaders/overlay_face_wireframe_vert.glsl
+++ b/source/blender/draw/modes/shaders/overlay_face_wireframe_vert.glsl
@@ -1,9 +1,4 @@
-uniform mat4 ProjectionMatrix;
-uniform mat4 ModelViewMatrix;
-uniform mat4 ModelMatrix;
-uniform mat3 NormalMatrix;
-
uniform float wireStepParam;
uniform float ofs;
@@ -11,57 +6,41 @@ in vec3 pos;
in vec3 nor;
in float wd; /* wiredata */
-#ifndef USE_SCULPT
float get_edge_sharpness(float wd)
{
+#ifndef USE_SCULPT
return ((wd == 0.0) ? -1.5 : wd) + wireStepParam;
-}
#else
-float get_edge_sharpness(float wd)
-{
return 1.0;
-}
#endif
+}
/* Geometry shader version */
#if defined(SELECT_EDGES) || defined(USE_GEOM)
out float facing_g;
out float edgeSharpness_g;
-void main()
-{
- edgeSharpness_g = get_edge_sharpness(wd);
-
- mat4 projmat = ProjectionMatrix;
- projmat[3][2] -= ofs;
-
- gl_Position = projmat * (ModelViewMatrix * vec4(pos, 1.0));
-
- facing_g = normalize(NormalMatrix * nor).z;
-
-# ifdef USE_WORLD_CLIP_PLANES
- world_clip_planes_calc_clip_distance((ModelMatrix * vec4(pos, 1.0)).xyz);
-# endif
-}
-
#else /* USE_GEOM */
out float facing;
flat out float edgeSharpness;
+# define facing_g facing
+# define edgeSharpness_g edgeSharpness
+
+#endif /* SELECT_EDGES */
void main()
{
- edgeSharpness = get_edge_sharpness(wd);
-
mat4 projmat = ProjectionMatrix;
projmat[3][2] -= ofs;
- gl_Position = projmat * (ModelViewMatrix * vec4(pos, 1.0));
+ vec4 wpos = ModelMatrix * vec4(pos, 1.0);
+ gl_Position = projmat * (ViewMatrix * wpos);
- facing = normalize(NormalMatrix * nor).z;
+ vec3 wnor = normalize(normal_object_to_world(nor));
+ facing_g = dot(wnor, ViewMatrixInverse[2].xyz);
+ edgeSharpness_g = get_edge_sharpness(wd);
-# ifdef USE_WORLD_CLIP_PLANES
- world_clip_planes_calc_clip_distance((ModelMatrix * vec4(pos, 1.0)).xyz);
-# endif
+#ifdef USE_WORLD_CLIP_PLANES
+ world_clip_planes_calc_clip_distance(wpos.xyz);
+#endif
}
-
-#endif /* SELECT_EDGES */
diff --git a/source/blender/draw/modes/shaders/paint_face_vert.glsl b/source/blender/draw/modes/shaders/paint_face_vert.glsl
index 59b88d8d3a7..4b5191ead07 100644
--- a/source/blender/draw/modes/shaders/paint_face_vert.glsl
+++ b/source/blender/draw/modes/shaders/paint_face_vert.glsl
@@ -1,20 +1,19 @@
-uniform mat4 ModelViewProjectionMatrix;
-uniform mat4 ModelMatrix;
-
in vec3 pos;
in vec4 nor; /* select flag on the 4th component */
void main()
{
- gl_Position = ModelViewProjectionMatrix * vec4(pos, 1.0);
+ vec3 world_pos = point_object_to_world(pos);
+ gl_Position = point_world_to_ndc(world_pos);
+
/* Don't draw faces that are selected. */
if (nor.w > 0.0) {
gl_Position = vec4(0.0, 0.0, 0.0, 1.0);
}
else {
#ifdef USE_WORLD_CLIP_PLANES
- world_clip_planes_calc_clip_distance((ModelMatrix * vec4(pos, 1.0)).xyz);
+ world_clip_planes_calc_clip_distance(world_pos);
#endif
}
}
diff --git a/source/blender/draw/modes/shaders/paint_texture_frag.glsl b/source/blender/draw/modes/shaders/paint_texture_frag.glsl
index c7e110122c5..4a3c5cb430c 100644
--- a/source/blender/draw/modes/shaders/paint_texture_frag.glsl
+++ b/source/blender/draw/modes/shaders/paint_texture_frag.glsl
@@ -16,6 +16,27 @@ uniform vec3 maskingColor;
uniform bool maskingInvertStencil;
#endif
+float linearrgb_to_srgb(float c)
+{
+ if (c < 0.0031308) {
+ return (c < 0.0) ? 0.0 : c * 12.92;
+ }
+ else {
+ return 1.055 * pow(c, 1.0 / 2.4) - 0.055;
+ }
+}
+
+vec4 texture_read_as_srgb(sampler2D tex, vec2 co)
+{
+ /* By convention image textures return scene linear colors, but
+ * overlays still assume srgb. */
+ vec4 color = texture(tex, co);
+ color.r = linearrgb_to_srgb(color.r);
+ color.g = linearrgb_to_srgb(color.g);
+ color.b = linearrgb_to_srgb(color.b);
+ return color;
+}
+
void main()
{
vec2 uv = uv_interp;
@@ -24,7 +45,7 @@ void main()
uv = (floor(uv_interp * tex_size) + 0.5) / tex_size;
}
- vec4 color = texture(image, uv);
+ vec4 color = texture_read_as_srgb(image, uv);
color.a *= alpha;
#ifdef TEXTURE_PAINT_MASK
diff --git a/source/blender/draw/modes/shaders/paint_texture_vert.glsl b/source/blender/draw/modes/shaders/paint_texture_vert.glsl
index 03d933b9196..564f988348e 100644
--- a/source/blender/draw/modes/shaders/paint_texture_vert.glsl
+++ b/source/blender/draw/modes/shaders/paint_texture_vert.glsl
@@ -1,7 +1,4 @@
-uniform mat4 ModelViewProjectionMatrix;
-uniform mat4 ModelMatrix;
-
in vec2 u; /* active uv map */
in vec3 pos;
@@ -17,7 +14,8 @@ out vec2 masking_uv_interp;
void main()
{
- gl_Position = ModelViewProjectionMatrix * vec4(pos, 1.0);
+ vec3 world_pos = point_object_to_world(pos);
+ gl_Position = point_world_to_ndc(world_pos);
uv_interp = u;
@@ -26,6 +24,6 @@ void main()
#endif
#ifdef USE_WORLD_CLIP_PLANES
- world_clip_planes_calc_clip_distance((ModelMatrix * vec4(pos, 1.0)).xyz);
+ world_clip_planes_calc_clip_distance(world_pos);
#endif
}
diff --git a/source/blender/draw/modes/shaders/paint_vertex_vert.glsl b/source/blender/draw/modes/shaders/paint_vertex_vert.glsl
index 54f6d1a4aea..53e72cc8a20 100644
--- a/source/blender/draw/modes/shaders/paint_vertex_vert.glsl
+++ b/source/blender/draw/modes/shaders/paint_vertex_vert.glsl
@@ -1,7 +1,4 @@
-uniform mat4 ModelViewProjectionMatrix;
-uniform mat4 ModelMatrix;
-
in vec3 pos;
in vec3 c; /* active color */
@@ -17,11 +14,12 @@ vec3 srgb_to_linear_attr(vec3 c)
void main()
{
- gl_Position = ModelViewProjectionMatrix * vec4(pos, 1.0);
+ vec3 world_pos = point_object_to_world(pos);
+ gl_Position = point_world_to_ndc(world_pos);
finalColor = srgb_to_linear_attr(c);
#ifdef USE_WORLD_CLIP_PLANES
- world_clip_planes_calc_clip_distance((ModelMatrix * vec4(pos, 1.0)).xyz);
+ world_clip_planes_calc_clip_distance(world_pos);
#endif
}
diff --git a/source/blender/draw/modes/shaders/paint_weight_vert.glsl b/source/blender/draw/modes/shaders/paint_weight_vert.glsl
index e95b116df79..330cc7d19f4 100644
--- a/source/blender/draw/modes/shaders/paint_weight_vert.glsl
+++ b/source/blender/draw/modes/shaders/paint_weight_vert.glsl
@@ -1,7 +1,4 @@
-uniform mat4 ModelViewProjectionMatrix;
-uniform mat4 ModelMatrix;
-
in float weight;
in vec3 pos;
@@ -9,12 +6,13 @@ out vec2 weight_interp; /* (weight, alert) */
void main()
{
- gl_Position = ModelViewProjectionMatrix * vec4(pos, 1.0);
+ vec3 world_pos = point_object_to_world(pos);
+ gl_Position = point_world_to_ndc(world_pos);
/* Separate actual weight and alerts for independent interpolation */
weight_interp = max(vec2(weight, -weight), 0.0);
#ifdef USE_WORLD_CLIP_PLANES
- world_clip_planes_calc_clip_distance((ModelMatrix * vec4(pos, 1.0)).xyz);
+ world_clip_planes_calc_clip_distance(world_pos);
#endif
}
diff --git a/source/blender/draw/modes/shaders/paint_wire_vert.glsl b/source/blender/draw/modes/shaders/paint_wire_vert.glsl
index a163fd7e8b3..10bf8729f47 100644
--- a/source/blender/draw/modes/shaders/paint_wire_vert.glsl
+++ b/source/blender/draw/modes/shaders/paint_wire_vert.glsl
@@ -1,7 +1,4 @@
-uniform mat4 ModelViewProjectionMatrix;
-uniform mat4 ModelMatrix;
-
in vec3 pos;
in vec4 nor; /* flag stored in w */
@@ -16,7 +13,8 @@ void main()
bool is_select = false;
bool is_hidden = false;
#endif
- gl_Position = ModelViewProjectionMatrix * vec4(pos, 1.0);
+ vec3 world_pos = point_object_to_world(pos);
+ gl_Position = point_world_to_ndc(world_pos);
/* Add offset in Z to avoid zfighting and render selected wires on top. */
/* TODO scale this bias using znear and zfar range. */
gl_Position.z -= (is_select ? 2e-4 : 1e-4);
@@ -46,6 +44,6 @@ void main()
finalColor.a = nor.w;
#ifdef USE_WORLD_CLIP_PLANES
- world_clip_planes_calc_clip_distance((ModelMatrix * vec4(pos, 1.0)).xyz);
+ world_clip_planes_calc_clip_distance(world_pos);
#endif
}
diff --git a/source/blender/draw/modes/shaders/particle_strand_frag.glsl b/source/blender/draw/modes/shaders/particle_strand_frag.glsl
index 578a4935b37..49d843b7e0e 100644
--- a/source/blender/draw/modes/shaders/particle_strand_frag.glsl
+++ b/source/blender/draw/modes/shaders/particle_strand_frag.glsl
@@ -1,4 +1,3 @@
-uniform mat4 ModelViewProjectionMatrix;
in vec4 finalColor;
#ifdef USE_POINTS
diff --git a/source/blender/draw/modes/shaders/particle_strand_vert.glsl b/source/blender/draw/modes/shaders/particle_strand_vert.glsl
index 6dac6d6b980..c3f8fb89c17 100644
--- a/source/blender/draw/modes/shaders/particle_strand_vert.glsl
+++ b/source/blender/draw/modes/shaders/particle_strand_vert.glsl
@@ -1,6 +1,4 @@
-uniform mat4 ModelViewProjectionMatrix;
-
in vec3 pos;
in float color;
@@ -47,7 +45,8 @@ vec3 weight_to_rgb(float weight)
void main()
{
- gl_Position = ModelViewProjectionMatrix * vec4(pos, 1.0);
+ vec3 world_pos = point_object_to_world(pos);
+ gl_Position = point_world_to_ndc(world_pos);
#ifdef USE_WEIGHT
finalColor = vec4(weight_to_rgb(color), 1.0);
diff --git a/source/blender/draw/modes/shaders/sculpt_mask_vert.glsl b/source/blender/draw/modes/shaders/sculpt_mask_vert.glsl
index e5e34fee57e..7b026836690 100644
--- a/source/blender/draw/modes/shaders/sculpt_mask_vert.glsl
+++ b/source/blender/draw/modes/shaders/sculpt_mask_vert.glsl
@@ -1,5 +1,4 @@
-uniform mat4 ModelViewProjectionMatrix;
uniform float maskOpacity;
in vec3 pos;
@@ -9,7 +8,8 @@ out vec4 finalColor;
void main()
{
- gl_Position = ModelViewProjectionMatrix * vec4(pos, 1.0);
+ vec3 world_pos = point_object_to_world(pos);
+ gl_Position = point_world_to_ndc(world_pos);
float mask = 1.0 - (msk * maskOpacity);
finalColor = vec4(mask, mask, mask, 1.0);
diff --git a/source/blender/draw/modes/shaders/volume_velocity_vert.glsl b/source/blender/draw/modes/shaders/volume_velocity_vert.glsl
index 32207afa0b1..e96a789b8b1 100644
--- a/source/blender/draw/modes/shaders/volume_velocity_vert.glsl
+++ b/source/blender/draw/modes/shaders/volume_velocity_vert.glsl
@@ -1,6 +1,4 @@
-uniform mat4 ModelViewProjectionMatrix;
-
uniform sampler3D velocityX;
uniform sampler3D velocityY;
uniform sampler3D velocityZ;
@@ -109,5 +107,6 @@ void main()
pos += (((gl_VertexID % 2) == 1) ? velocity : vec3(0.0)) * displaySize * voxel_size;
#endif
- gl_Position = ModelViewProjectionMatrix * vec4(pos, 1.0);
+ vec3 world_pos = point_object_to_world(pos);
+ gl_Position = point_world_to_ndc(world_pos);
}
diff --git a/source/blender/editors/animation/CMakeLists.txt b/source/blender/editors/animation/CMakeLists.txt
index 978bd772b6f..ce6778a1ff9 100644
--- a/source/blender/editors/animation/CMakeLists.txt
+++ b/source/blender/editors/animation/CMakeLists.txt
@@ -51,6 +51,7 @@ set(SRC
keyframes_general.c
keyframing.c
keyingsets.c
+ time_scrub_ui.c
anim_intern.h
)
diff --git a/source/blender/editors/animation/anim_channels_defines.c b/source/blender/editors/animation/anim_channels_defines.c
index 6d1ee08d5e9..00025112835 100644
--- a/source/blender/editors/animation/anim_channels_defines.c
+++ b/source/blender/editors/animation/anim_channels_defines.c
@@ -485,16 +485,10 @@ static void acf_summary_backdrop(bAnimContext *ac, bAnimListElem *ale, float ymi
static void acf_summary_name(bAnimListElem *UNUSED(ale), char *name)
{
if (name) {
- BLI_strncpy(name, IFACE_("Dope Sheet Summary"), ANIM_CHAN_NAME_SIZE);
+ BLI_strncpy(name, IFACE_("Summary"), ANIM_CHAN_NAME_SIZE);
}
}
-// FIXME: this is really a temp icon I think
-static int acf_summary_icon(bAnimListElem *UNUSED(ale))
-{
- return ICON_BORDERMOVE;
-}
-
/* check if some setting exists for this channel */
static bool acf_summary_setting_valid(bAnimContext *UNUSED(ac),
bAnimListElem *UNUSED(ale),
@@ -557,7 +551,7 @@ static bAnimChannelType ACF_SUMMARY = {
acf_summary_name, /* name */
NULL, /* name prop */
- acf_summary_icon, /* icon */
+ NULL, /* icon */
acf_summary_setting_valid, /* has setting */
acf_summary_setting_flag, /* flag for setting */
diff --git a/source/blender/editors/animation/anim_channels_edit.c b/source/blender/editors/animation/anim_channels_edit.c
index 6e0277d5fff..9e09fc485a6 100644
--- a/source/blender/editors/animation/anim_channels_edit.c
+++ b/source/blender/editors/animation/anim_channels_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_armature.h"
@@ -2531,17 +2532,6 @@ static void box_select_anim_channels(bAnimContext *ac, rcti *rect, short selectm
SpaceNla *snla = (SpaceNla *)ac->sl;
View2D *v2d = &ac->ar->v2d;
rctf rectf;
- float ymin, ymax;
-
- /* set initial y extents */
- if (ac->datatype == ANIMCONT_NLA) {
- ymin = (float)(-NLACHANNEL_HEIGHT(snla));
- ymax = 0.0f;
- }
- else {
- ymin = 0.0f;
- ymax = (float)(-ACHANNEL_HEIGHT(ac));
- }
/* convert border-region to view coordinates */
UI_view2d_region_to_view(v2d, rect->xmin, rect->ymin + 2, &rectf.xmin, &rectf.ymin);
@@ -2551,8 +2541,17 @@ static void box_select_anim_channels(bAnimContext *ac, rcti *rect, short selectm
filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE | ANIMFILTER_LIST_CHANNELS);
ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype);
+ float ymax;
+ if (ac->datatype == ANIMCONT_NLA) {
+ ymax = NLACHANNEL_FIRST_TOP(ac);
+ }
+ else {
+ ymax = ACHANNEL_FIRST_TOP(ac);
+ }
+
/* loop over data, doing box select */
for (ale = anim_data.first; ale; ale = ale->next) {
+ float ymin;
if (ac->datatype == ANIMCONT_NLA) {
ymin = ymax - NLACHANNEL_STEP(snla);
}
@@ -2729,32 +2728,25 @@ static int animchannels_channel_get(bAnimContext *ac, const int mval[2])
ar = ac->ar;
v2d = &ar->v2d;
- /* Figure out which channel user clicked in.
- *
- * Note: although channels technically start at (y = ACHANNEL_FIRST),
- * we need to adjust by half a channel's height so that the tops of channels get caught ok.
- * Since ACHANNEL_FIRST is really ACHANNEL_HEIGHT, we simply use ACHANNEL_HEIGHT_HALF.
- */
+ /* Figure out which channel user clicked in. */
UI_view2d_region_to_view(v2d, mval[0], mval[1], &x, &y);
if (ac->datatype == ANIMCONT_NLA) {
SpaceNla *snla = (SpaceNla *)ac->sl;
- UI_view2d_listview_view_to_cell(v2d,
- NLACHANNEL_NAMEWIDTH,
+ UI_view2d_listview_view_to_cell(NLACHANNEL_NAMEWIDTH,
NLACHANNEL_STEP(snla),
0,
- (float)NLACHANNEL_HEIGHT_HALF(snla),
+ NLACHANNEL_FIRST_TOP(ac),
x,
y,
NULL,
&channel_index);
}
else {
- UI_view2d_listview_view_to_cell(v2d,
- ACHANNEL_NAMEWIDTH,
+ UI_view2d_listview_view_to_cell(ACHANNEL_NAMEWIDTH,
ACHANNEL_STEP(ac),
0,
- (float)ACHANNEL_HEIGHT_HALF(ac),
+ ACHANNEL_FIRST_TOP(ac),
x,
y,
NULL,
@@ -3206,19 +3198,12 @@ static int animchannels_mouseclick_invoke(bContext *C, wmOperator *op, const wmE
selectmode = SELECT_REPLACE;
}
- /* figure out which channel user clicked in
- *
- * Note:
- * although channels technically start at (y = ACHANNEL_FIRST),
- * we need to adjust by half a channel's height so that the tops of channels get caught ok.
- * Since ACHANNEL_FIRST is really ACHANNEL_HEIGHT, we simply use ACHANNEL_HEIGHT_HALF.
- */
+ /* figure out which channel user clicked in */
UI_view2d_region_to_view(v2d, event->mval[0], event->mval[1], &x, &y);
- UI_view2d_listview_view_to_cell(v2d,
- ACHANNEL_NAMEWIDTH,
+ UI_view2d_listview_view_to_cell(ACHANNEL_NAMEWIDTH,
ACHANNEL_STEP(&ac),
0,
- (float)ACHANNEL_HEIGHT_HALF(&ac),
+ ACHANNEL_FIRST_TOP(&ac),
x,
y,
NULL,
diff --git a/source/blender/editors/animation/anim_filter.c b/source/blender/editors/animation/anim_filter.c
index b94d0e3ada7..a228d819286 100644
--- a/source/blender/editors/animation/anim_filter.c
+++ b/source/blender/editors/animation/anim_filter.c
@@ -1823,7 +1823,7 @@ static size_t animdata_filter_gpencil(bAnimContext *ac,
}
/* outliner restrict-flag */
- if (ob->restrictflag & OB_RESTRICT_VIEW) {
+ if (ob->restrictflag & OB_RESTRICT_VIEWPORT) {
continue;
}
}
@@ -3022,7 +3022,7 @@ static bool animdata_filter_base_is_ok(bDopeSheet *ads, Base *base, int filter_m
}
/* outliner restrict-flag */
- if (ob->restrictflag & OB_RESTRICT_VIEW) {
+ if (ob->restrictflag & OB_RESTRICT_VIEWPORT) {
return false;
}
}
diff --git a/source/blender/editors/animation/anim_markers.c b/source/blender/editors/animation/anim_markers.c
index 66cdae07a36..876bc9ae3e4 100644
--- a/source/blender/editors/animation/anim_markers.c
+++ b/source/blender/editors/animation/anim_markers.c
@@ -481,7 +481,9 @@ static void draw_markers_background(rctf *rect)
uint pos = GPU_vertformat_attr_add(immVertexFormat(), "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
- const unsigned char shade[4] = {0, 0, 0, 16};
+ unsigned char shade[4];
+ UI_GetThemeColor4ubv(TH_SCRUBBING_BACKGROUND, shade);
+
immUniformColor4ubv(shade);
GPU_blend(true);
diff --git a/source/blender/editors/animation/drivers.c b/source/blender/editors/animation/drivers.c
index 2a8702802aa..fe079eb59a0 100644
--- a/source/blender/editors/animation/drivers.c
+++ b/source/blender/editors/animation/drivers.c
@@ -1249,7 +1249,8 @@ static int paste_driver_button_exec(bContext *C, wmOperator *op)
UI_context_update_anim_flag(C);
DEG_relations_tag_update(CTX_data_main(C));
- DEG_id_tag_update(ptr.id.data, ID_RECALC_TRANSFORM | ID_RECALC_GEOMETRY);
+
+ DEG_id_tag_update(ptr.id.data, ID_RECALC_ANIMATION);
WM_event_add_notifier(C, NC_ANIMATION | ND_KEYFRAME_PROP, NULL); // XXX
diff --git a/source/blender/editors/animation/keyframes_general.c b/source/blender/editors/animation/keyframes_general.c
index 5214c5f78fa..be8de66a262 100644
--- a/source/blender/editors/animation/keyframes_general.c
+++ b/source/blender/editors/animation/keyframes_general.c
@@ -315,8 +315,7 @@ void clean_fcurve(struct bAnimContext *ac, bAnimListElem *ale, float thresh, boo
clear_fcurve_keys(fcu);
/* check if curve is really unused and if it is, return signal for deletion */
- if ((list_has_suitable_fmodifier(&fcu->modifiers, 0, FMI_TYPE_GENERATE_CURVE) == 0) &&
- (fcu->driver == NULL)) {
+ if (BKE_fcurve_is_empty(fcu)) {
AnimData *adt = ale->adt;
ANIM_fcurve_delete_from_animdata(ac, adt, fcu);
ale->key_data = NULL;
diff --git a/source/blender/editors/animation/keyframing.c b/source/blender/editors/animation/keyframing.c
index a0433b49b16..2dc17c5c397 100644
--- a/source/blender/editors/animation/keyframing.c
+++ b/source/blender/editors/animation/keyframing.c
@@ -1307,8 +1307,8 @@ static bool insert_keyframe_fcurve_value(Main *bmain,
* - if we're replacing keyframes only, DO NOT create new F-Curves if they do not exist yet
* but still try to get the F-Curve if it exists...
*/
- FCurve *fcu = verify_fcurve(
- bmain, act, group, ptr, rna_path, array_index, (flag & INSERTKEY_REPLACE) == 0);
+ bool can_create_curve = (flag & (INSERTKEY_REPLACE | INSERTKEY_AVAILABLE)) == 0;
+ FCurve *fcu = verify_fcurve(bmain, act, group, ptr, rna_path, array_index, can_create_curve);
/* we may not have a F-Curve when we're replacing only... */
if (fcu) {
@@ -1432,7 +1432,7 @@ short insert_keyframe(Main *bmain,
/* Key the entire array. */
if (array_index == -1 || force_all) {
/* In force mode, if any of the curves succeeds, drop the replace mode and restart. */
- if (force_all && (flag & INSERTKEY_REPLACE) != 0) {
+ if (force_all && (flag & (INSERTKEY_REPLACE | INSERTKEY_AVAILABLE)) != 0) {
int exclude = -1;
for (array_index = 0; array_index < value_count; array_index++) {
@@ -1455,7 +1455,7 @@ short insert_keyframe(Main *bmain,
}
if (exclude != -1) {
- flag &= ~INSERTKEY_REPLACE;
+ flag &= ~(INSERTKEY_REPLACE | INSERTKEY_AVAILABLE);
for (array_index = 0; array_index < value_count; array_index++) {
if (array_index != exclude) {
@@ -1557,8 +1557,7 @@ static bool delete_keyframe_fcurve(AnimData *adt, FCurve *fcu, float cfra)
delete_fcurve_key(fcu, i, 1);
/* Only delete curve too if it won't be doing anything anymore */
- if ((fcu->totvert == 0) &&
- (list_has_suitable_fmodifier(&fcu->modifiers, 0, FMI_TYPE_GENERATE_CURVE) == 0)) {
+ if (BKE_fcurve_is_empty(fcu)) {
ANIM_fcurve_delete_from_animdata(NULL, adt, fcu);
}
diff --git a/source/blender/editors/animation/time_scrub_ui.c b/source/blender/editors/animation/time_scrub_ui.c
new file mode 100644
index 00000000000..37e7eab74d4
--- /dev/null
+++ b/source/blender/editors/animation/time_scrub_ui.c
@@ -0,0 +1,214 @@
+/*
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * The Original Code is Copyright (C) 2019 Blender Foundation.
+ * All rights reserved.
+ */
+
+/** \file
+ * \ingroup edanimation
+ */
+
+#include "BKE_context.h"
+
+#include "GPU_immediate.h"
+#include "GPU_matrix.h"
+#include "GPU_state.h"
+
+#include "ED_time_scrub_ui.h"
+
+#include "WM_api.h"
+#include "WM_types.h"
+
+#include "UI_interface.h"
+#include "UI_interface_icons.h"
+#include "UI_view2d.h"
+#include "UI_resources.h"
+
+#include "DNA_scene_types.h"
+
+#include "BLI_rect.h"
+#include "BLI_math.h"
+#include "BLI_string.h"
+#include "BLI_timecode.h"
+
+#include "RNA_access.h"
+
+static void get_scrubbing_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;
+}
+
+static int get_centered_text_y(const rcti *rect)
+{
+ return BLI_rcti_cent_y(rect) - UI_DPI_FAC * 4;
+}
+
+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);
+
+ GPU_blend(true);
+ GPU_blend_set_func_separate(
+ GPU_SRC_ALPHA, GPU_ONE_MINUS_SRC_ALPHA, GPU_ONE, GPU_ONE_MINUS_SRC_ALPHA);
+
+ immRectf(pos, rect->xmin, rect->ymin, rect->xmax, rect->ymax);
+
+ GPU_blend(false);
+
+ immUnbindProgram();
+}
+
+static void get_current_time_str(
+ const Scene *scene, bool display_seconds, int frame, uint max_len, char *r_str)
+{
+ if (display_seconds) {
+ BLI_timecode_string_from_time(r_str, max_len, 0, FRA2TIME(frame), FPS, U.timecode_style);
+ }
+ else {
+ BLI_snprintf(r_str, max_len, "%d", frame);
+ }
+}
+
+static void draw_current_frame(const Scene *scene,
+ bool display_seconds,
+ const View2D *v2d,
+ const rcti *scrubbing_region_rect,
+ int current_frame)
+{
+ const uiFontStyle *fstyle = UI_FSTYLE_WIDGET;
+ const unsigned char color[] = {255, 255, 255, 255};
+ int frame_x = UI_view2d_view_to_region_x(v2d, current_frame);
+
+ char frame_str[64];
+ get_current_time_str(scene, display_seconds, current_frame, sizeof(frame_str), frame_str);
+ float text_width = UI_fontstyle_string_width(fstyle, frame_str);
+ float box_width = MAX2(text_width + 8 * UI_DPI_FAC, 24 * UI_DPI_FAC);
+ float box_padding = 3 * UI_DPI_FAC;
+
+ float bg_color[4];
+ UI_GetThemeColorShade4fv(TH_CFRAME, -5, bg_color);
+
+ UI_draw_roundbox_corner_set(UI_CNR_ALL);
+
+ UI_draw_roundbox_3fvAlpha(true,
+ frame_x - box_width / 2 + U.pixelsize / 2,
+ scrubbing_region_rect->ymin + box_padding,
+ frame_x + box_width / 2 + U.pixelsize / 2,
+ scrubbing_region_rect->ymax - box_padding,
+ 4 * UI_DPI_FAC,
+ bg_color,
+ 1.0f);
+
+ 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,
+ frame_x + box_width / 2 + U.pixelsize / 2,
+ scrubbing_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),
+ frame_str,
+ color);
+}
+
+void ED_scrubbing_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);
+
+ draw_background(&scrubbing_region_rect);
+
+ rcti numbers_rect = scrubbing_region_rect;
+ numbers_rect.ymin = get_centered_text_y(&scrubbing_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);
+ }
+ else {
+ UI_view2d_draw_scale_x__frames_or_seconds(
+ ar, v2d, &numbers_rect, scene, display_seconds, TH_TEXT);
+ }
+
+ draw_current_frame(scene, display_seconds, v2d, &scrubbing_region_rect, scene->r.cfra);
+
+ GPU_matrix_pop_projection();
+}
+
+bool ED_event_in_scrubbing_region(const ARegion *ar, const wmEvent *event)
+{
+ rcti rect = ar->winrct;
+ rect.ymin = rect.ymax - UI_SCRUBBING_MARGIN_Y;
+ return BLI_rcti_isect_pt(&rect, event->x, event->y);
+}
+
+void ED_channel_search_draw(const bContext *C, ARegion *ar, bDopeSheet *dopesheet)
+{
+ GPU_matrix_push_projection();
+ wmOrtho2_region_pixelspace(ar);
+
+ 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.ymax = ceilf(ar->sizey * UI_DPI_FAC);
+
+ uint pos = GPU_vertformat_attr_add(immVertexFormat(), "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
+ immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
+ immUniformThemeColor(TH_BACK);
+ immRectf(pos, rect.xmin, rect.ymin, rect.xmax, rect.ymax);
+ immUnbindProgram();
+
+ uiBlock *block = UI_block_begin(C, ar, __func__, UI_EMBOSS);
+
+ PointerRNA ptr;
+ RNA_pointer_create(&CTX_wm_screen(C)->id, &RNA_DopeSheet, dopesheet, &ptr);
+ PropertyRNA *prop = RNA_struct_find_property(&ptr, "filter_text");
+
+ int padding = 2 * UI_DPI_FAC;
+ uiDefAutoButR(block,
+ &ptr,
+ prop,
+ -1,
+ "",
+ ICON_NONE,
+ rect.xmin + padding,
+ rect.ymin + padding,
+ BLI_rcti_size_x(&rect) - 2 * padding,
+ BLI_rcti_size_y(&rect) - 2 * padding);
+
+ UI_block_end(C, block);
+ UI_block_draw(C, block);
+
+ GPU_matrix_pop_projection();
+}
diff --git a/source/blender/editors/armature/armature_intern.h b/source/blender/editors/armature/armature_intern.h
index 6c2d9fe8f42..569eb7e2e04 100644
--- a/source/blender/editors/armature/armature_intern.h
+++ b/source/blender/editors/armature/armature_intern.h
@@ -210,6 +210,8 @@ void POSELIB_OT_apply_pose(struct wmOperatorType *ot);
void POSE_OT_push(struct wmOperatorType *ot);
void POSE_OT_relax(struct wmOperatorType *ot);
+void POSE_OT_push_rest(struct wmOperatorType *ot);
+void POSE_OT_relax_rest(struct wmOperatorType *ot);
void POSE_OT_breakdown(struct wmOperatorType *ot);
void POSE_OT_propagate(struct wmOperatorType *ot);
diff --git a/source/blender/editors/armature/armature_naming.c b/source/blender/editors/armature/armature_naming.c
index 083967d5d41..9a1582679a4 100644
--- a/source/blender/editors/armature/armature_naming.c
+++ b/source/blender/editors/armature/armature_naming.c
@@ -180,7 +180,17 @@ void ED_armature_bone_rename(Main *bmain,
if (bone) {
unique_bone_name(arm, newname);
+
+ if (arm->bonehash) {
+ BLI_assert(BLI_ghash_haskey(arm->bonehash, bone->name));
+ BLI_ghash_remove(arm->bonehash, bone->name, NULL, NULL);
+ }
+
BLI_strncpy(bone->name, newname, MAXBONENAME);
+
+ if (arm->bonehash) {
+ BLI_ghash_insert(arm->bonehash, bone->name, bone);
+ }
}
else {
return;
diff --git a/source/blender/editors/armature/armature_ops.c b/source/blender/editors/armature/armature_ops.c
index b53ae813f10..a29d0f5f158 100644
--- a/source/blender/editors/armature/armature_ops.c
+++ b/source/blender/editors/armature/armature_ops.c
@@ -146,6 +146,8 @@ void ED_operatortypes_armature(void)
/* POSE SLIDING */
WM_operatortype_append(POSE_OT_push);
WM_operatortype_append(POSE_OT_relax);
+ WM_operatortype_append(POSE_OT_push_rest);
+ WM_operatortype_append(POSE_OT_relax_rest);
WM_operatortype_append(POSE_OT_breakdown);
}
diff --git a/source/blender/editors/armature/armature_relations.c b/source/blender/editors/armature/armature_relations.c
index b2ca1d84520..2c61818d902 100644
--- a/source/blender/editors/armature/armature_relations.c
+++ b/source/blender/editors/armature/armature_relations.c
@@ -66,10 +66,16 @@
/* *************************************** Join *************************************** */
/* NOTE: no operator define here as this is exported to the Object-level operator */
-static void joined_armature_fix_links_constraints(
- Object *tarArm, Object *srcArm, bPoseChannel *pchan, EditBone *curbone, ListBase *lb)
+static void joined_armature_fix_links_constraints(Main *bmain,
+ Object *ob,
+ Object *tarArm,
+ Object *srcArm,
+ bPoseChannel *pchan,
+ EditBone *curbone,
+ ListBase *lb)
{
bConstraint *con;
+ bool changed = false;
for (con = lb->first; con; con = con->next) {
const bConstraintTypeInfo *cti = BKE_constraint_typeinfo_get(con);
@@ -84,10 +90,12 @@ static void joined_armature_fix_links_constraints(
if (ct->tar == srcArm) {
if (ct->subtarget[0] == '\0') {
ct->tar = tarArm;
+ changed = true;
}
else if (STREQ(ct->subtarget, pchan->name)) {
ct->tar = tarArm;
BLI_strncpy(ct->subtarget, curbone->name, sizeof(ct->subtarget));
+ changed = true;
}
}
}
@@ -104,13 +112,21 @@ static void joined_armature_fix_links_constraints(
if (data->act) {
BKE_action_fix_paths_rename(
&tarArm->id, data->act, "pose.bones[", pchan->name, curbone->name, 0, 0, false);
+
+ DEG_id_tag_update_ex(bmain, &data->act->id, ID_RECALC_COPY_ON_WRITE);
}
}
}
+
+ if (changed) {
+ DEG_id_tag_update_ex(bmain, &ob->id, ID_RECALC_COPY_ON_WRITE);
+ }
}
/* userdata for joined_armature_fix_animdata_cb() */
typedef struct tJoinArmature_AdtFixData {
+ Main *bmain;
+
Object *srcArm;
Object *tarArm;
@@ -129,6 +145,7 @@ static void joined_armature_fix_animdata_cb(ID *id, FCurve *fcu, void *user_data
ID *dst_id = &afd->tarArm->id;
GHashIterator gh_iter;
+ bool changed = false;
/* Fix paths - If this is the target object, it will have some "dirty" paths */
if ((id == src_id) && strstr(fcu->rna_path, "pose.bones[")) {
@@ -142,6 +159,8 @@ static void joined_armature_fix_animdata_cb(ID *id, FCurve *fcu, void *user_data
fcu->rna_path = BKE_animsys_fix_rna_path_rename(
id, fcu->rna_path, "pose.bones", old_name, new_name, 0, 0, false);
+ changed = true;
+
/* we don't want to apply a second remapping on this driver now,
* so stop trying names, but keep fixing drivers
*/
@@ -163,6 +182,8 @@ static void joined_armature_fix_animdata_cb(ID *id, FCurve *fcu, void *user_data
if (dtar->id == src_id) {
dtar->id = dst_id;
+ changed = true;
+
/* also check on the subtarget...
* XXX: We duplicate the logic from drivers_path_rename_fix() here, with our own
* little twists so that we know that it isn't going to clobber the wrong data
@@ -193,6 +214,10 @@ static void joined_armature_fix_animdata_cb(ID *id, FCurve *fcu, void *user_data
DRIVER_TARGETS_LOOPER_END;
}
}
+
+ if (changed) {
+ DEG_id_tag_update_ex(afd->bmain, id, ID_RECALC_COPY_ON_WRITE);
+ }
}
/* Helper function for armature joining - link fixing */
@@ -210,13 +235,14 @@ static void joined_armature_fix_links(
pose = ob->pose;
for (pchant = pose->chanbase.first; pchant; pchant = pchant->next) {
joined_armature_fix_links_constraints(
- tarArm, srcArm, pchan, curbone, &pchant->constraints);
+ bmain, ob, tarArm, srcArm, pchan, curbone, &pchant->constraints);
}
}
/* fix object-level constraints */
if (ob != srcArm) {
- joined_armature_fix_links_constraints(tarArm, srcArm, pchan, curbone, &ob->constraints);
+ joined_armature_fix_links_constraints(
+ bmain, ob, tarArm, srcArm, pchan, curbone, &ob->constraints);
}
/* See if an object is parented to this armature */
@@ -231,6 +257,8 @@ static void joined_armature_fix_links(
/* make tar armature be new parent */
ob->parent = tarArm;
+
+ DEG_id_tag_update_ex(bmain, &ob->id, ID_RECALC_COPY_ON_WRITE);
}
}
}
@@ -286,6 +314,7 @@ int join_armature_exec(bContext *C, wmOperator *op)
BLI_assert(ob_active->data != ob_iter->data);
/* init callback data for fixing up AnimData links later */
+ afd.bmain = bmain;
afd.srcArm = ob_iter;
afd.tarArm = ob_active;
afd.names_map = BLI_ghash_str_new("join_armature_adt_fix");
diff --git a/source/blender/editors/armature/armature_select.c b/source/blender/editors/armature/armature_select.c
index fbbb68d2003..23ddf77e63d 100644
--- a/source/blender/editors/armature/armature_select.c
+++ b/source/blender/editors/armature/armature_select.c
@@ -70,7 +70,7 @@ Base *ED_armature_base_and_ebone_from_select_buffer(Base **bases,
EditBone *ebone = NULL;
/* TODO(campbell): optimize, eg: sort & binary search. */
for (uint base_index = 0; base_index < bases_len; base_index++) {
- if (bases[base_index]->object->select_id == hit_object) {
+ if (bases[base_index]->object->runtime.select_id == hit_object) {
base = bases[base_index];
break;
}
@@ -94,7 +94,7 @@ Object *ED_armature_object_and_ebone_from_select_buffer(Object **objects,
EditBone *ebone = NULL;
/* TODO(campbell): optimize, eg: sort & binary search. */
for (uint ob_index = 0; ob_index < objects_len; ob_index++) {
- if (objects[ob_index]->select_id == hit_object) {
+ if (objects[ob_index]->runtime.select_id == hit_object) {
ob = objects[ob_index];
break;
}
@@ -118,7 +118,7 @@ Base *ED_armature_base_and_bone_from_select_buffer(Base **bases,
Bone *bone = NULL;
/* TODO(campbell): optimize, eg: sort & binary search. */
for (uint base_index = 0; base_index < bases_len; base_index++) {
- if (bases[base_index]->object->select_id == hit_object) {
+ if (bases[base_index]->object->runtime.select_id == hit_object) {
base = bases[base_index];
break;
}
@@ -300,6 +300,7 @@ static int armature_select_linked_invoke(bContext *C, wmOperator *op, const wmEv
const bool sel = !RNA_boolean_get(op->ptr, "deselect");
view3d_operator_needs_opengl(C);
+ BKE_object_update_select_id(CTX_data_main(C));
Base *base = NULL;
bone = get_nearest_bone(C, event->mval, true, &base);
@@ -1817,6 +1818,7 @@ static int armature_shortest_path_pick_invoke(bContext *C, wmOperator *op, const
Base *base_dst = NULL;
view3d_operator_needs_opengl(C);
+ BKE_object_update_select_id(CTX_data_main(C));
ebone_src = arm->act_edbone;
ebone_dst = get_nearest_bone(C, event->mval, false, &base_dst);
diff --git a/source/blender/editors/armature/armature_utils.c b/source/blender/editors/armature/armature_utils.c
index b23081cd6fa..27076f84c7f 100644
--- a/source/blender/editors/armature/armature_utils.c
+++ b/source/blender/editors/armature/armature_utils.c
@@ -127,7 +127,6 @@ void bone_free(bArmature *arm, EditBone *bone)
if (bone->prop) {
IDP_FreeProperty(bone->prop);
- MEM_freeN(bone->prop);
}
/* Clear references from other edit bones. */
@@ -650,6 +649,7 @@ void ED_armature_from_edit(Main *bmain, bArmature *arm)
Object *obt;
/* armature bones */
+ BKE_armature_bone_hash_free(arm);
BKE_armature_bonelist_free(&arm->bonebase);
arm->act_bone = NULL;
@@ -754,6 +754,8 @@ void ED_armature_from_edit(Main *bmain, bArmature *arm)
/* Finalize definition of restpose data (roll, bone_mat, arm_mat, head/tail...). */
armature_finalize_restpose(&arm->bonebase, arm->edbo);
+ BKE_armature_bone_hash_make(arm);
+
/* so all users of this armature should get rebuilt */
for (obt = bmain->objects.first; obt; obt = obt->id.next) {
if (obt->data == arm) {
@@ -774,7 +776,6 @@ void ED_armature_edit_free(struct bArmature *arm)
for (eBone = arm->edbo->first; eBone; eBone = eBone->next) {
if (eBone->prop) {
IDP_FreeProperty(eBone->prop);
- MEM_freeN(eBone->prop);
}
}
@@ -808,7 +809,6 @@ void ED_armature_ebone_listbase_free(ListBase *lb)
if (ebone->prop) {
IDP_FreeProperty(ebone->prop);
- MEM_freeN(ebone->prop);
}
MEM_freeN(ebone);
diff --git a/source/blender/editors/armature/pose_edit.c b/source/blender/editors/armature/pose_edit.c
index cf64210ebdb..954beda7777 100644
--- a/source/blender/editors/armature/pose_edit.c
+++ b/source/blender/editors/armature/pose_edit.c
@@ -65,7 +65,7 @@
#include "armature_intern.h"
-#define DEBUG_TIME
+#undef DEBUG_TIME
#include "PIL_time.h"
#ifdef DEBUG_TIME
@@ -197,38 +197,6 @@ void ED_pose_recalculate_paths(bContext *C, Scene *scene, Object *ob, bool curre
ListBase targets = {NULL, NULL};
bool free_depsgraph = false;
- /* Override depsgraph with a filtered, simpler copy */
- if (!current_frame_only && G.debug_value != -1) {
- DEG_FilterQuery query = {{0}};
-
- DEG_FilterTarget *dft_ob = MEM_callocN(sizeof(DEG_FilterTarget), "DEG_FilterTarget");
- dft_ob->id = &ob->id;
- BLI_addtail(&query.targets, dft_ob);
-
-#ifdef DEBUG_TIME
- TIMEIT_START(filter_pose_depsgraph);
-#endif
-
- depsgraph = DEG_graph_filter(depsgraph, bmain, &query);
-
-#ifdef DEBUG_TIME
- TIMEIT_END(filter_pose_depsgraph);
-#endif
-
- free_depsgraph = true;
- MEM_freeN(dft_ob);
-
-#ifdef DEBUG_TIME
- TIMEIT_START(filter_pose_update);
-#endif
-
- BKE_scene_graph_update_tagged(depsgraph, bmain);
-
-#ifdef DEBUG_TIME
- TIMEIT_END(filter_pose_update);
-#endif
- }
-
/* set flag to force recalc, then grab the relevant bones to target */
ob->pose->avs.recalc |= ANIMVIZ_RECALC_PATHS;
animviz_get_object_motionpaths(ob, &targets);
diff --git a/source/blender/editors/armature/pose_lib.c b/source/blender/editors/armature/pose_lib.c
index 7b31897766d..4bcfdc700b3 100644
--- a/source/blender/editors/armature/pose_lib.c
+++ b/source/blender/editors/armature/pose_lib.c
@@ -1018,7 +1018,6 @@ static void poselib_backup_free_data(tPoseLib_PreviewData *pld)
/* free custom data */
if (plb->oldprops) {
IDP_FreeProperty(plb->oldprops);
- MEM_freeN(plb->oldprops);
}
/* free backup element now */
diff --git a/source/blender/editors/armature/pose_slide.c b/source/blender/editors/armature/pose_slide.c
index d683c599f7b..9bc204c9e3b 100644
--- a/source/blender/editors/armature/pose_slide.c
+++ b/source/blender/editors/armature/pose_slide.c
@@ -134,6 +134,8 @@ typedef enum ePoseSlide_Modes {
POSESLIDE_PUSH = 0, /* exaggerate the pose... */
POSESLIDE_RELAX, /* soften the pose... */
POSESLIDE_BREAKDOWN, /* slide between the endpoint poses, finding a 'soft' spot */
+ POSESLIDE_PUSH_REST,
+ POSESLIDE_RELAX_REST,
} ePoseSlide_Modes;
/* Transforms/Channels to Affect */
@@ -627,6 +629,103 @@ static void pose_slide_apply_quat(tPoseSlideOp *pso, tPChanFCurveLink *pfl)
MEM_freeN(path);
}
+static void pose_slide_rest_pose_apply_vec3(tPoseSlideOp *pso, float vec[3], float default_value)
+{
+ /* We only slide to the rest pose. So only use the default rest pose value */
+ const int lock = pso->axislock;
+ for (int idx = 0; idx < 3; idx++) {
+ if ((lock == 0) || ((lock & PS_LOCK_X) && (idx == 0)) || ((lock & PS_LOCK_Y) && (idx == 1)) ||
+ ((lock & PS_LOCK_Z) && (idx == 2))) {
+ float diff_val = default_value - vec[idx];
+ if (pso->mode == POSESLIDE_RELAX_REST) {
+ vec[idx] += pso->percentage * diff_val;
+ }
+ else {
+ /* Push */
+ vec[idx] -= pso->percentage * diff_val;
+ }
+ }
+ }
+}
+
+static void pose_slide_rest_pose_apply_other_rot(tPoseSlideOp *pso, float vec[4], bool quat)
+{
+ /* We only slide to the rest pose. So only use the default rest pose value */
+ float default_values[] = {1.0f, 0.0f, 0.0f, 0.0f};
+ if (!quat) {
+ /* Axis Angle */
+ default_values[0] = 0.0f;
+ default_values[2] = 1.0f;
+ }
+ for (int idx = 0; idx < 4; idx++) {
+ float diff_val = default_values[idx] - vec[idx];
+ if (pso->mode == POSESLIDE_RELAX_REST) {
+ vec[idx] += pso->percentage * diff_val;
+ }
+ else {
+ /* Push */
+ vec[idx] -= pso->percentage * diff_val;
+ }
+ }
+}
+
+/* apply() - perform the pose sliding between the current pose and the rest pose */
+static void pose_slide_rest_pose_apply(bContext *C, tPoseSlideOp *pso)
+{
+ tPChanFCurveLink *pfl;
+
+ /* for each link, handle each set of transforms */
+ for (pfl = pso->pfLinks.first; pfl; pfl = pfl->next) {
+ /* valid transforms for each PoseChannel should have been noted already
+ * - sliding the pose should be a straightforward exercise for location+rotation,
+ * but rotations get more complicated since we may want to use quaternion blending
+ * for quaternions instead...
+ */
+ bPoseChannel *pchan = pfl->pchan;
+
+ if (ELEM(pso->channels, PS_TFM_ALL, PS_TFM_LOC) && (pchan->flag & POSE_LOC)) {
+ /* calculate these for the 'location' vector, and use location curves */
+ pose_slide_rest_pose_apply_vec3(pso, pchan->loc, 0.0f);
+ }
+
+ if (ELEM(pso->channels, PS_TFM_ALL, PS_TFM_SIZE) && (pchan->flag & POSE_SIZE)) {
+ /* calculate these for the 'scale' vector, and use scale curves */
+ pose_slide_rest_pose_apply_vec3(pso, pchan->size, 1.0f);
+ }
+
+ if (ELEM(pso->channels, PS_TFM_ALL, PS_TFM_ROT) && (pchan->flag & POSE_ROT)) {
+ /* everything depends on the rotation mode */
+ if (pchan->rotmode > 0) {
+ /* eulers - so calculate these for the 'eul' vector, and use euler_rotation curves */
+ pose_slide_rest_pose_apply_vec3(pso, pchan->eul, 0.0f);
+ }
+ else if (pchan->rotmode == ROT_MODE_AXISANGLE) {
+ pose_slide_rest_pose_apply_other_rot(pso, pchan->quat, false);
+ }
+ else {
+ /* quaternions - use quaternion blending */
+ pose_slide_rest_pose_apply_other_rot(pso, pchan->quat, true);
+ }
+ }
+
+ if (ELEM(pso->channels, PS_TFM_ALL, PS_TFM_BBONE_SHAPE) && (pchan->flag & POSE_BBONE_SHAPE)) {
+ /* bbone properties - they all start a "bbone_" prefix */
+ // TODO Not implemented
+ // pose_slide_apply_props(pso, pfl, "bbone_");
+ }
+
+ if (ELEM(pso->channels, PS_TFM_ALL, PS_TFM_PROPS) && (pfl->oldprops)) {
+ /* Not strictly a transform, but custom properties contribute
+ * to the pose produced in many rigs (e.g. the facial rigs used in Sintel). */
+ // TODO Not implemented
+ // pose_slide_apply_props(pso, pfl, "[\""); /* dummy " for texteditor bugs */
+ }
+ }
+
+ /* depsgraph updates + redraws */
+ pose_slide_refresh(C, pso);
+}
+
/* apply() - perform the pose sliding based on weighting various poses */
static void pose_slide_apply(bContext *C, tPoseSlideOp *pso)
{
@@ -888,7 +987,12 @@ static int pose_slide_invoke_common(bContext *C, wmOperator *op, tPoseSlideOp *p
/* initial apply for operator... */
/* TODO: need to calculate percentage for initial round too... */
- pose_slide_apply(C, pso);
+ if (pso->mode != POSESLIDE_PUSH_REST && pso->mode != POSESLIDE_RELAX_REST) {
+ pose_slide_apply(C, pso);
+ }
+ else {
+ pose_slide_rest_pose_apply(C, pso);
+ }
/* depsgraph updates + redraws */
pose_slide_refresh(C, pso);
@@ -1122,7 +1226,12 @@ static int pose_slide_modal(bContext *C, wmOperator *op, const wmEvent *event)
pose_slide_reset(pso);
/* apply... */
- pose_slide_apply(C, pso);
+ if (pso->mode != POSESLIDE_PUSH_REST && pso->mode != POSESLIDE_RELAX_REST) {
+ pose_slide_apply(C, pso);
+ }
+ else {
+ pose_slide_rest_pose_apply(C, pso);
+ }
}
/* still running... */
@@ -1140,7 +1249,12 @@ static void pose_slide_cancel(bContext *UNUSED(C), wmOperator *op)
static int pose_slide_exec_common(bContext *C, wmOperator *op, tPoseSlideOp *pso)
{
/* settings should have been set up ok for applying, so just apply! */
- pose_slide_apply(C, pso);
+ if (pso->mode != POSESLIDE_PUSH_REST && pso->mode != POSESLIDE_RELAX_REST) {
+ pose_slide_apply(C, pso);
+ }
+ else {
+ pose_slide_rest_pose_apply(C, pso);
+ }
/* insert keyframes if needed */
pose_slide_autoKeyframe(C, pso);
@@ -1200,7 +1314,7 @@ static void pose_slide_opdef_properties(wmOperatorType *ot)
/* ------------------------------------ */
-/* invoke() - for 'push' mode */
+/* invoke() - for 'push from breakdown' mode */
static int pose_slide_push_invoke(bContext *C, wmOperator *op, const wmEvent *event)
{
tPoseSlideOp *pso;
@@ -1242,9 +1356,9 @@ static int pose_slide_push_exec(bContext *C, wmOperator *op)
void POSE_OT_push(wmOperatorType *ot)
{
/* identifiers */
- ot->name = "Push Pose";
+ ot->name = "Push Pose from Breakdown";
ot->idname = "POSE_OT_push";
- ot->description = "Exaggerate the current pose";
+ ot->description = "Exaggerate the current pose in regards to the breakdown pose";
/* callbacks */
ot->exec = pose_slide_push_exec;
@@ -1262,7 +1376,7 @@ void POSE_OT_push(wmOperatorType *ot)
/* ........................ */
-/* invoke() - for 'relax' mode */
+/* invoke() - for 'relax to breakdown' mode */
static int pose_slide_relax_invoke(bContext *C, wmOperator *op, const wmEvent *event)
{
tPoseSlideOp *pso;
@@ -1304,9 +1418,9 @@ static int pose_slide_relax_exec(bContext *C, wmOperator *op)
void POSE_OT_relax(wmOperatorType *ot)
{
/* identifiers */
- ot->name = "Relax Pose";
+ ot->name = "Relax Pose to Breakdown";
ot->idname = "POSE_OT_relax";
- ot->description = "Make the current pose more similar to its surrounding ones";
+ ot->description = "Make the current pose more similar to its breakdown pose";
/* callbacks */
ot->exec = pose_slide_relax_exec;
@@ -1323,6 +1437,129 @@ void POSE_OT_relax(wmOperatorType *ot)
}
/* ........................ */
+/* invoke() - for 'push from rest pose' mode */
+static int pose_slide_push_rest_invoke(bContext *C, wmOperator *op, const wmEvent *event)
+{
+ tPoseSlideOp *pso;
+
+ /* initialize data */
+ if (pose_slide_init(C, op, POSESLIDE_PUSH_REST) == 0) {
+ pose_slide_exit(op);
+ return OPERATOR_CANCELLED;
+ }
+ else {
+ pso = op->customdata;
+ }
+
+ /* initialise percentage so that it won't pop on first mouse move */
+ pose_slide_mouse_update_percentage(pso, op, event);
+
+ /* do common setup work */
+ return pose_slide_invoke_common(C, op, pso);
+}
+
+/* exec() - for push */
+static int pose_slide_push_rest_exec(bContext *C, wmOperator *op)
+{
+ tPoseSlideOp *pso;
+
+ /* initialize data (from RNA-props) */
+ if (pose_slide_init(C, op, POSESLIDE_PUSH_REST) == 0) {
+ pose_slide_exit(op);
+ return OPERATOR_CANCELLED;
+ }
+ else {
+ pso = op->customdata;
+ }
+
+ /* do common exec work */
+ return pose_slide_exec_common(C, op, pso);
+}
+
+void POSE_OT_push_rest(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name = "Push Pose from Rest Pose";
+ ot->idname = "POSE_OT_push_rest";
+ ot->description = "Push the current pose further away from the rest pose";
+
+ /* callbacks */
+ ot->exec = pose_slide_push_rest_exec;
+ ot->invoke = pose_slide_push_rest_invoke;
+ ot->modal = pose_slide_modal;
+ ot->cancel = pose_slide_cancel;
+ ot->poll = ED_operator_posemode;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_BLOCKING | OPTYPE_USE_EVAL_DATA;
+
+ /* Properties */
+ pose_slide_opdef_properties(ot);
+}
+
+/* ........................ */
+
+/* invoke() - for 'relax' mode */
+static int pose_slide_relax_rest_invoke(bContext *C, wmOperator *op, const wmEvent *event)
+{
+ tPoseSlideOp *pso;
+
+ /* initialize data */
+ if (pose_slide_init(C, op, POSESLIDE_RELAX_REST) == 0) {
+ pose_slide_exit(op);
+ return OPERATOR_CANCELLED;
+ }
+ else {
+ pso = op->customdata;
+ }
+
+ /* initialise percentage so that it won't pop on first mouse move */
+ pose_slide_mouse_update_percentage(pso, op, event);
+
+ /* do common setup work */
+ return pose_slide_invoke_common(C, op, pso);
+}
+
+/* exec() - for relax */
+static int pose_slide_relax_rest_exec(bContext *C, wmOperator *op)
+{
+ tPoseSlideOp *pso;
+
+ /* initialize data (from RNA-props) */
+ if (pose_slide_init(C, op, POSESLIDE_RELAX_REST) == 0) {
+ pose_slide_exit(op);
+ return OPERATOR_CANCELLED;
+ }
+ else {
+ pso = op->customdata;
+ }
+
+ /* do common exec work */
+ return pose_slide_exec_common(C, op, pso);
+}
+
+void POSE_OT_relax_rest(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name = "Relax Pose to Rest Pose";
+ ot->idname = "POSE_OT_relax_rest";
+ ot->description = "Make the current pose more similar to the rest pose";
+
+ /* callbacks */
+ ot->exec = pose_slide_relax_rest_exec;
+ ot->invoke = pose_slide_relax_rest_invoke;
+ ot->modal = pose_slide_modal;
+ ot->cancel = pose_slide_cancel;
+ ot->poll = ED_operator_posemode;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_BLOCKING | OPTYPE_USE_EVAL_DATA;
+
+ /* Properties */
+ pose_slide_opdef_properties(ot);
+}
+
+/* ........................ */
/* invoke() - for 'breakdown' mode */
static int pose_slide_breakdown_invoke(bContext *C, wmOperator *op, const wmEvent *event)
diff --git a/source/blender/editors/armature/pose_transform.c b/source/blender/editors/armature/pose_transform.c
index 6207d5412cf..ed728714c5b 100644
--- a/source/blender/editors/armature/pose_transform.c
+++ b/source/blender/editors/armature/pose_transform.c
@@ -59,6 +59,9 @@
#include "ED_screen.h"
#include "ED_util.h"
+#include "UI_interface.h"
+#include "UI_resources.h"
+
#include "armature_intern.h"
/* ********************************************** */
@@ -87,6 +90,229 @@ static void applyarmature_fix_boneparents(const bContext *C, Scene *scene, Objec
}
}
+/* Sets the bone head, tail and roll to match the supplied parameters. */
+static void applyarmature_set_edit_position(EditBone *curbone,
+ const float pose_mat[4][4],
+ const float new_tail[3],
+ float r_new_arm_mat[4][4])
+{
+ /* Simply copy the head/tail values from pchan over to curbone. */
+ copy_v3_v3(curbone->head, pose_mat[3]);
+ copy_v3_v3(curbone->tail, new_tail);
+
+ /* Fix roll:
+ * 1. find auto-calculated roll value for this bone now
+ * 2. remove this from the 'visual' y-rotation
+ */
+ {
+ float premat[3][3], pmat[3][3];
+ float delta[3];
+
+ /* Obtain new auto y-rotation. */
+ sub_v3_v3v3(delta, curbone->tail, curbone->head);
+
+ copy_m3_m4(pmat, pose_mat);
+ mat3_vec_to_roll(pmat, delta, &curbone->roll);
+
+ /* Compute new rest pose matrix if requested. */
+ if (r_new_arm_mat) {
+ vec_roll_to_mat3(delta, curbone->roll, premat);
+ copy_m4_m3(r_new_arm_mat, premat);
+ copy_v3_v3(r_new_arm_mat[3], pose_mat[3]);
+ }
+ }
+}
+
+/* Copy properties over from pchan to curbone and reset channels. */
+static void applyarmature_transfer_properties(EditBone *curbone,
+ bPoseChannel *pchan,
+ const bPoseChannel *pchan_eval)
+{
+ /* Combine pose and rest values for bendy bone settings,
+ * then clear the pchan values (so we don't get a double-up).
+ */
+ if (pchan->bone->segments > 1) {
+ /* Combine rest/pose values. */
+ curbone->curve_in_x += pchan_eval->curve_in_x;
+ curbone->curve_in_y += pchan_eval->curve_in_y;
+ curbone->curve_out_x += pchan_eval->curve_out_x;
+ curbone->curve_out_y += pchan_eval->curve_out_y;
+ curbone->roll1 += pchan_eval->roll1;
+ curbone->roll2 += pchan_eval->roll2;
+ curbone->ease1 += pchan_eval->ease1;
+ curbone->ease2 += pchan_eval->ease2;
+
+ curbone->scale_in_x *= pchan_eval->scale_in_x;
+ curbone->scale_in_y *= pchan_eval->scale_in_y;
+ curbone->scale_out_x *= pchan_eval->scale_out_x;
+ curbone->scale_out_y *= pchan_eval->scale_out_y;
+
+ /* Reset pose values. */
+ pchan->curve_in_x = pchan->curve_out_x = 0.0f;
+ pchan->curve_in_y = pchan->curve_out_y = 0.0f;
+ pchan->roll1 = pchan->roll2 = 0.0f;
+ pchan->ease1 = pchan->ease2 = 0.0f;
+ pchan->scale_in_x = pchan->scale_in_y = 1.0f;
+ pchan->scale_out_x = pchan->scale_out_y = 1.0f;
+ }
+
+ /* Clear transform values for pchan. */
+ zero_v3(pchan->loc);
+ zero_v3(pchan->eul);
+ unit_qt(pchan->quat);
+ unit_axis_angle(pchan->rotAxis, &pchan->rotAngle);
+ pchan->size[0] = pchan->size[1] = pchan->size[2] = 1.0f;
+
+ /* Set anim lock. */
+ curbone->flag |= BONE_UNKEYED;
+}
+
+/* Adjust the current edit position of the bone using the pose space matrix. */
+static void applyarmature_adjust_edit_position(bArmature *arm,
+ bPoseChannel *pchan,
+ const float delta_mat[4][4],
+ float r_new_arm_mat[4][4])
+{
+ EditBone *curbone = ED_armature_ebone_find_name(arm->edbo, pchan->name);
+ float delta[3], new_tail[3], premat[3][3], new_pose[4][4];
+
+ /* Current orientation matrix. */
+ sub_v3_v3v3(delta, curbone->tail, curbone->head);
+ vec_roll_to_mat3(delta, curbone->roll, premat);
+
+ /* New location and orientation. */
+ mul_m4_m4m3(new_pose, delta_mat, premat);
+ mul_v3_m4v3(new_pose[3], delta_mat, curbone->head);
+ mul_v3_m4v3(new_tail, delta_mat, curbone->tail);
+
+ applyarmature_set_edit_position(curbone, new_pose, new_tail, r_new_arm_mat);
+}
+
+/* Data about parent position for Apply To Selected mode. */
+typedef struct ApplyArmature_ParentState {
+ Bone *bone;
+
+ /* New rest position of the bone with scale included. */
+ float new_rest_mat[4][4];
+ /* New arm_mat of the bone == new_rest_mat without scale. */
+ float new_arm_mat[4][4];
+} ApplyArmature_ParentState;
+
+/* Recursive walk for Apply To Selected mode; pstate NULL unless child of an applied bone. */
+static void applyarmature_process_selected_rec(bArmature *arm,
+ bPose *pose,
+ bPose *pose_eval,
+ Bone *bone,
+ ListBase *selected,
+ ApplyArmature_ParentState *pstate)
+{
+ bPoseChannel *pchan = BKE_pose_channel_find_name(pose, bone->name);
+ const bPoseChannel *pchan_eval = BKE_pose_channel_find_name(pose_eval, bone->name);
+
+ if (!pchan || !pchan_eval)
+ return;
+
+ ApplyArmature_ParentState new_pstate = {.bone = bone};
+
+ if (BLI_findptr(selected, pchan, offsetof(CollectionPointerLink, ptr.data))) {
+ /* SELECTED BONE: Snap to final pose transform minus unapplied parent effects.
+ *
+ * I.e. bone position with accumulated parent effects but no local
+ * transformation will match the original final pose_mat.
+ *
+ * Pose channels are reset as expected.
+ */
+ EditBone *curbone = ED_armature_ebone_find_name(arm->edbo, pchan->name);
+ BoneParentTransform invparent;
+ float new_tail[3];
+
+ if (pchan->parent) {
+ BoneParentTransform old_bpt, new_bpt;
+ float offs_bone[4][4];
+
+ /* Parent effects on the bone transform that have to be removed. */
+ BKE_bone_offset_matrix_get(bone, offs_bone);
+ BKE_bone_parent_transform_calc_from_matrices(
+ bone->flag, offs_bone, bone->parent->arm_mat, pchan_eval->parent->pose_mat, &old_bpt);
+
+ /* Applied parent effects that have to be kept, if any. */
+ float(*new_parent_pose)[4] = pstate ? pstate->new_rest_mat : bone->parent->arm_mat;
+ BKE_bone_parent_transform_calc_from_matrices(
+ bone->flag, offs_bone, bone->parent->arm_mat, new_parent_pose, &new_bpt);
+
+ BKE_bone_parent_transform_invert(&old_bpt);
+ BKE_bone_parent_transform_combine(&new_bpt, &old_bpt, &invparent);
+ }
+ else {
+ BKE_bone_parent_transform_clear(&invparent);
+ }
+
+ /* Apply change without inherited unapplied parent transformations. */
+ BKE_bone_parent_transform_apply(&invparent, pchan_eval->pose_mat, new_pstate.new_rest_mat);
+
+ copy_v3_fl3(new_tail, 0.0, bone->length, 0.0);
+ mul_m4_v3(new_pstate.new_rest_mat, new_tail);
+
+ applyarmature_set_edit_position(
+ curbone, new_pstate.new_rest_mat, new_tail, new_pstate.new_arm_mat);
+ applyarmature_transfer_properties(curbone, pchan, pchan_eval);
+
+ pstate = &new_pstate;
+ }
+ else if (pstate) {
+ /* UNSELECTED CHILD OF SELECTED: Include applied parent effects.
+ *
+ * The inherited transform of applied (selected) bones is baked
+ * into the rest pose so that the final bone position doesn't
+ * change.
+ *
+ * Pose channels are not changed, with the exception of the inherited
+ * applied parent scale being baked into the location pose channel.
+ */
+ BoneParentTransform bpt;
+ float offs_bone[4][4], delta[4][4], old_chan_loc[3];
+
+ /* Include applied parent effects. */
+ BKE_bone_offset_matrix_get(bone, offs_bone);
+ BKE_bone_parent_transform_calc_from_matrices(
+ bone->flag, offs_bone, pstate->bone->arm_mat, pstate->new_rest_mat, &bpt);
+
+ unit_m4(new_pstate.new_rest_mat);
+ BKE_bone_parent_transform_apply(&bpt, new_pstate.new_rest_mat, new_pstate.new_rest_mat);
+
+ /* Bone location channel in pose space relative to bone head. */
+ mul_v3_mat3_m4v3(old_chan_loc, bpt.loc_mat, pchan_eval->loc);
+
+ /* Apply the change to the rest bone position. */
+ invert_m4_m4(delta, bone->arm_mat);
+ mul_m4_m4m4(delta, new_pstate.new_rest_mat, delta);
+
+ applyarmature_adjust_edit_position(arm, pchan, delta, new_pstate.new_arm_mat);
+
+ /* Location pose channel has to be updated, because it is affected
+ * by parent scaling, and the rest pose has no scale by definition. */
+ if (!(bone->flag & BONE_CONNECTED) && !is_zero_v3(old_chan_loc)) {
+ float inv_parent_arm[4][4];
+
+ /* Compute the channel coordinate space matrices for the new rest state. */
+ invert_m4_m4(inv_parent_arm, pstate->new_arm_mat);
+ mul_m4_m4m4(offs_bone, inv_parent_arm, new_pstate.new_arm_mat);
+ BKE_bone_parent_transform_calc_from_matrices(
+ bone->flag, offs_bone, pstate->new_arm_mat, pstate->new_arm_mat, &bpt);
+
+ /* Re-apply the location to keep the final effect. */
+ invert_m4(bpt.loc_mat);
+ mul_v3_mat3_m4v3(pchan->loc, bpt.loc_mat, old_chan_loc);
+ }
+
+ pstate = &new_pstate;
+ }
+
+ for (Bone *child = bone->childbase.first; child; child = child->next) {
+ applyarmature_process_selected_rec(arm, pose, pose_eval, child, selected, pstate);
+ }
+}
+
/* set the current pose as the restpose */
static int apply_armature_pose2bones_exec(bContext *C, wmOperator *op)
{
@@ -99,7 +325,9 @@ static int apply_armature_pose2bones_exec(bContext *C, wmOperator *op)
bArmature *arm = BKE_armature_from_object(ob);
bPose *pose;
bPoseChannel *pchan;
- EditBone *curbone;
+ ListBase selected_bones;
+
+ const bool use_selected = RNA_boolean_get(op->ptr, "selected");
/* don't check if editmode (should be done by caller) */
if (ob->type != OB_ARMATURE) {
@@ -119,80 +347,37 @@ static int apply_armature_pose2bones_exec(bContext *C, wmOperator *op)
"transforms stored are relative to the old rest pose");
}
+ /* Find selected bones before switching to edit mode. */
+ if (use_selected) {
+ CTX_data_selected_pose_bones(C, &selected_bones);
+
+ if (!selected_bones.first) {
+ return OPERATOR_CANCELLED;
+ }
+ }
+
/* Get editbones of active armature to alter */
ED_armature_to_edit(arm);
/* get pose of active object and move it out of posemode */
pose = ob->pose;
- for (pchan = pose->chanbase.first; pchan; pchan = pchan->next) {
- const bPoseChannel *pchan_eval = BKE_pose_channel_find_name(ob_eval->pose, pchan->name);
- curbone = ED_armature_ebone_find_name(arm->edbo, pchan->name);
-
- /* simply copy the head/tail values from pchan over to curbone */
- copy_v3_v3(curbone->head, pchan_eval->pose_head);
- copy_v3_v3(curbone->tail, pchan_eval->pose_tail);
-
- /* fix roll:
- * 1. find auto-calculated roll value for this bone now
- * 2. remove this from the 'visual' y-rotation
- */
- {
- float premat[3][3], imat[3][3], pmat[3][3], tmat[3][3];
- float delta[3], eul[3];
-
- /* obtain new auto y-rotation */
- sub_v3_v3v3(delta, curbone->tail, curbone->head);
- vec_roll_to_mat3(delta, 0.0f, premat);
- invert_m3_m3(imat, premat);
-
- /* get pchan 'visual' matrix */
- copy_m3_m4(pmat, pchan_eval->pose_mat);
-
- /* remove auto from visual and get euler rotation */
- mul_m3_m3m3(tmat, imat, pmat);
- mat3_to_eul(eul, tmat);
-
- /* just use this euler-y as new roll value */
- curbone->roll = eul[1];
+ if (use_selected) {
+ /* The selected only mode requires a recursive walk to handle parent-child relations. */
+ for (Bone *bone = arm->bonebase.first; bone; bone = bone->next) {
+ applyarmature_process_selected_rec(arm, pose, ob_eval->pose, bone, &selected_bones, NULL);
}
- /* combine pose and rest values for bendy bone settings,
- * then clear the pchan values (so we don't get a double-up)
- */
- if (pchan->bone->segments > 1) {
- /* combine rest/pose values */
- curbone->curve_in_x += pchan_eval->curve_in_x;
- curbone->curve_in_y += pchan_eval->curve_in_y;
- curbone->curve_out_x += pchan_eval->curve_out_x;
- curbone->curve_out_y += pchan_eval->curve_out_y;
- curbone->roll1 += pchan_eval->roll1;
- curbone->roll2 += pchan_eval->roll2;
- curbone->ease1 += pchan_eval->ease1;
- curbone->ease2 += pchan_eval->ease2;
- curbone->scale_in_x *= pchan_eval->scale_in_x;
- curbone->scale_in_y *= pchan_eval->scale_in_y;
- curbone->scale_out_x *= pchan_eval->scale_out_x;
- curbone->scale_out_y *= pchan_eval->scale_out_y;
-
- /* reset pose values */
- pchan->curve_in_x = pchan->curve_out_x = 0.0f;
- pchan->curve_in_y = pchan->curve_out_y = 0.0f;
- pchan->roll1 = pchan->roll2 = 0.0f;
- pchan->ease1 = pchan->ease2 = 0.0f;
- pchan->scale_in_x = pchan->scale_in_y = 1.0f;
- pchan->scale_out_x = pchan->scale_out_y = 1.0f;
- }
-
- /* clear transform values for pchan */
- zero_v3(pchan->loc);
- zero_v3(pchan->eul);
- unit_qt(pchan->quat);
- unit_axis_angle(pchan->rotAxis, &pchan->rotAngle);
- pchan->size[0] = pchan->size[1] = pchan->size[2] = 1.0f;
+ BLI_freelistN(&selected_bones);
+ }
+ else {
+ for (pchan = pose->chanbase.first; pchan; pchan = pchan->next) {
+ const bPoseChannel *pchan_eval = BKE_pose_channel_find_name(ob_eval->pose, pchan->name);
+ EditBone *curbone = ED_armature_ebone_find_name(arm->edbo, pchan->name);
- /* set anim lock */
- curbone->flag |= BONE_UNKEYED;
+ applyarmature_set_edit_position(curbone, pchan_eval->pose_mat, pchan_eval->pose_tail, NULL);
+ applyarmature_transfer_properties(curbone, pchan, pchan_eval);
+ }
}
/* convert editbones back to bones, and then free the edit-data */
@@ -212,6 +397,17 @@ static int apply_armature_pose2bones_exec(bContext *C, wmOperator *op)
return OPERATOR_FINISHED;
}
+static void apply_armature_pose2bones_ui(bContext *C, wmOperator *op)
+{
+ uiLayout *layout = op->layout;
+ wmWindowManager *wm = CTX_wm_manager(C);
+ PointerRNA ptr;
+
+ RNA_pointer_create(&wm->id, op->type->srna, op->properties, &ptr);
+
+ uiItemR(layout, &ptr, "selected", 0, NULL, ICON_NONE);
+}
+
void POSE_OT_armature_apply(wmOperatorType *ot)
{
/* identifiers */
@@ -222,9 +418,16 @@ void POSE_OT_armature_apply(wmOperatorType *ot)
/* callbacks */
ot->exec = apply_armature_pose2bones_exec;
ot->poll = ED_operator_posemode;
+ ot->ui = apply_armature_pose2bones_ui;
/* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_USE_EVAL_DATA;
+
+ RNA_def_boolean(ot->srna,
+ "selected",
+ false,
+ "Selected Only",
+ "Only apply the selected bones (with propagation to children)");
}
/* set the current pose as the restpose */
@@ -1022,7 +1225,6 @@ static int pose_clear_user_transforms_exec(bContext *C, wmOperator *op)
for (pchan = dummyPose->chanbase.first; pchan; pchan = pchan->next) {
if (pchan->prop) {
IDP_FreeProperty(pchan->prop);
- MEM_freeN(pchan->prop);
}
}
diff --git a/source/blender/editors/armature/pose_utils.c b/source/blender/editors/armature/pose_utils.c
index a1f763ac57d..fbaf2c896d0 100644
--- a/source/blender/editors/armature/pose_utils.c
+++ b/source/blender/editors/armature/pose_utils.c
@@ -203,7 +203,6 @@ void poseAnim_mapping_free(ListBase *pfLinks)
/* free custom properties */
if (pfl->oldprops) {
IDP_FreeProperty(pfl->oldprops);
- MEM_freeN(pfl->oldprops);
}
/* free list of F-Curve reference links */
diff --git a/source/blender/editors/curve/editcurve.c b/source/blender/editors/curve/editcurve.c
index a787b45c13c..1e40ba2f19b 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;
- /* 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;
+ /* 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;
+ }
- bezt_orig_prev = &bezt_orig[mod_i(a - 1, nu->pntsu)];
- bezt_orig_next = &bezt_orig[mod_i(a + 1, nu->pntsu)];
+ /* 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;
- smooth_single_bezt(bezt, bezt_orig_prev, bezt_orig_next, factor);
+ bezt_orig_prev = &bezt_orig[mod_i(a - 1, nu->pntsu)];
+ bezt_orig_next = &bezt_orig[mod_i(a + 1, nu->pntsu)];
- changed = true;
+ smooth_single_bezt(bezt, bezt_orig_prev, bezt_orig_next, factor);
+
+ 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);
+
+ 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, radius), offsetof(BPoint, radius));
- 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);
+ }
- 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);
- curve_smooth_value(editnurb, offsetof(BezTriple, tilt), offsetof(BPoint, tilt));
+ 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));
+
+ 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;
}
@@ -3909,54 +3963,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)
@@ -5551,6 +5614,8 @@ static int add_vertex_exec(bContext *C, wmOperator *op)
}
WM_event_add_notifier(C, NC_GEOM | ND_DATA, obedit->data);
+ WM_event_add_notifier(C, NC_GEOM | ND_SELECT, obedit->data);
+
DEG_id_tag_update(obedit->data, 0);
return OPERATOR_FINISHED;
@@ -6745,31 +6810,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)
@@ -7024,7 +7099,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 d1b1f43d8dd..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(&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(&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_edit.c b/source/blender/editors/gpencil/gpencil_edit.c
index 463c2144276..9ef0657ae83 100644
--- a/source/blender/editors/gpencil/gpencil_edit.c
+++ b/source/blender/editors/gpencil/gpencil_edit.c
@@ -314,7 +314,7 @@ static int gpencil_paintmode_toggle_exec(bContext *C, wmOperator *op)
BKE_paint_ensure(ts, (Paint **)&ts->gp_paint);
Paint *paint = &ts->gp_paint->paint;
/* if not exist, create a new one */
- if (paint->brush == NULL) {
+ if ((paint->brush == NULL) || (paint->brush->gpencil_settings == NULL)) {
BKE_brush_gpencil_presets(C);
}
BKE_paint_toolslots_brush_validate(bmain, &ts->gp_paint->paint);
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/gpencil/gpencil_merge.c b/source/blender/editors/gpencil/gpencil_merge.c
index 9d3c2a6e271..93d8555e014 100644
--- a/source/blender/editors/gpencil/gpencil_merge.c
+++ b/source/blender/editors/gpencil/gpencil_merge.c
@@ -110,7 +110,7 @@ static bGPDstroke *gpencil_prepare_stroke(bContext *C, wmOperator *op, int totpo
Paint *paint = &ts->gp_paint->paint;
/* if not exist, create a new one */
- if (paint->brush == NULL) {
+ if ((paint->brush == NULL) || (paint->brush->gpencil_settings == NULL)) {
/* create new brushes */
BKE_brush_gpencil_presets(C);
}
diff --git a/source/blender/editors/gpencil/gpencil_paint.c b/source/blender/editors/gpencil/gpencil_paint.c
index b1b29356060..cd1ebc91fbb 100644
--- a/source/blender/editors/gpencil/gpencil_paint.c
+++ b/source/blender/editors/gpencil/gpencil_paint.c
@@ -1819,7 +1819,7 @@ static void gp_init_drawing_brush(bContext *C, tGPsdata *p)
Paint *paint = &ts->gp_paint->paint;
bool changed = false;
/* if not exist, create a new one */
- if (paint->brush == NULL) {
+ if ((paint->brush == NULL) || (paint->brush->gpencil_settings == NULL)) {
/* create new brushes */
BKE_brush_gpencil_presets(C);
changed = true;
diff --git a/source/blender/editors/gpencil/gpencil_primitive.c b/source/blender/editors/gpencil/gpencil_primitive.c
index 08fee2bb393..bff17bf5078 100644
--- a/source/blender/editors/gpencil/gpencil_primitive.c
+++ b/source/blender/editors/gpencil/gpencil_primitive.c
@@ -314,7 +314,7 @@ static void gp_primitive_set_initdata(bContext *C, tGPDprimitive *tgpi)
/* if brush doesn't exist, create a new one */
Paint *paint = &ts->gp_paint->paint;
/* if not exist, create a new one */
- if (paint->brush == NULL) {
+ if ((paint->brush == NULL) || (paint->brush->gpencil_settings == NULL)) {
/* create new brushes */
BKE_brush_gpencil_presets(C);
}
diff --git a/source/blender/editors/gpencil/gpencil_utils.c b/source/blender/editors/gpencil/gpencil_utils.c
index 129bd01574c..93a80f0fcf8 100644
--- a/source/blender/editors/gpencil/gpencil_utils.c
+++ b/source/blender/editors/gpencil/gpencil_utils.c
@@ -1387,7 +1387,7 @@ void ED_gpencil_add_defaults(bContext *C, Object *ob)
BKE_paint_ensure(ts, (Paint **)&ts->gp_paint);
Paint *paint = &ts->gp_paint->paint;
/* if not exist, create a new one */
- if (paint->brush == NULL) {
+ if ((paint->brush == NULL) || (paint->brush->gpencil_settings == NULL)) {
/* create new brushes */
BKE_brush_gpencil_presets(C);
}
diff --git a/source/blender/editors/include/ED_anim_api.h b/source/blender/editors/include/ED_anim_api.h
index d947322f708..cd68981dee3 100644
--- a/source/blender/editors/include/ED_anim_api.h
+++ b/source/blender/editors/include/ED_anim_api.h
@@ -403,11 +403,14 @@ typedef enum eAnimFilter_Flags {
/* -------------- Channel Defines -------------- */
/* channel heights */
-#define ACHANNEL_FIRST(ac) (-0.8f * (ac)->yscale_fac * U.widget_unit)
+#define ACHANNEL_FIRST_TOP(ac) \
+ (UI_view2d_scale_get_y(&(ac)->ar->v2d) * -UI_SCRUBBING_MARGIN_Y - ACHANNEL_SKIP)
#define ACHANNEL_HEIGHT(ac) (0.8f * (ac)->yscale_fac * U.widget_unit)
-#define ACHANNEL_HEIGHT_HALF(ac) (0.4f * (ac)->yscale_fac * U.widget_unit)
#define ACHANNEL_SKIP (0.1f * U.widget_unit)
#define ACHANNEL_STEP(ac) (ACHANNEL_HEIGHT(ac) + ACHANNEL_SKIP)
+/* Additional offset to give some room at the end. */
+#define ACHANNEL_TOT_HEIGHT(ac, item_amount) \
+ (-ACHANNEL_FIRST_TOP(ac) + ACHANNEL_STEP(ac) * (item_amount + 1))
/* channel widths */
#define ACHANNEL_NAMEWIDTH (10 * U.widget_unit)
@@ -418,13 +421,15 @@ typedef enum eAnimFilter_Flags {
/* -------------- NLA Channel Defines -------------- */
/* NLA channel heights */
-#define NLACHANNEL_FIRST (-0.8f * U.widget_unit)
+#define NLACHANNEL_FIRST_TOP(ac) \
+ (UI_view2d_scale_get_y(&(ac)->ar->v2d) * -UI_SCRUBBING_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_HEIGHT_HALF(snla) \
- ((snla && (snla->flag & SNLA_NOSTRIPCURVES)) ? (0.4f * U.widget_unit) : (0.6f * U.widget_unit))
#define NLACHANNEL_SKIP (0.1f * U.widget_unit)
#define NLACHANNEL_STEP(snla) (NLACHANNEL_HEIGHT(snla) + NLACHANNEL_SKIP)
+/* Additional offset to give some room at the end. */
+#define NLACHANNEL_TOT_HEIGHT(ac, item_amount) \
+ (-NLACHANNEL_FIRST_TOP(ac) + NLACHANNEL_STEP(((SpaceNla *)(ac)->sl)) * (item_amount + 1))
/* channel widths */
#define NLACHANNEL_NAMEWIDTH (10 * U.widget_unit)
diff --git a/source/blender/editors/include/ED_image.h b/source/blender/editors/include/ED_image.h
index 5bd806b3dbf..a09e1d579fd 100644
--- a/source/blender/editors/include/ED_image.h
+++ b/source/blender/editors/include/ED_image.h
@@ -28,6 +28,7 @@ struct ARegion;
struct ImBuf;
struct Image;
struct ImageUser;
+struct ReportList;
struct Scene;
struct SpaceImage;
struct ToolSettings;
@@ -110,4 +111,8 @@ void ED_image_draw_info(struct Scene *scene,
bool ED_space_image_show_cache(struct SpaceImage *sima);
+bool ED_image_should_save_modified(const struct bContext *C);
+int ED_image_save_all_modified_info(const struct bContext *C, struct ReportList *reports);
+bool ED_image_save_all_modified(const struct bContext *C, struct ReportList *reports);
+
#endif /* __ED_IMAGE_H__ */
diff --git a/source/blender/editors/include/ED_mesh.h b/source/blender/editors/include/ED_mesh.h
index ce8521a1f6a..0a8304f3f8a 100644
--- a/source/blender/editors/include/ED_mesh.h
+++ b/source/blender/editors/include/ED_mesh.h
@@ -142,44 +142,55 @@ bool BMBVH_EdgeVisible(struct BMBVHTree *tree,
void ED_mesh_undosys_type(struct UndoType *ut);
/* editmesh_select.c */
+struct EDBMSelectID_Context;
+struct EDBMSelectID_Context *EDBM_select_id_context_create(struct ViewContext *vc,
+ struct Base **bases,
+ const uint bases_len,
+ short select_mode);
+void EDBM_select_id_context_destroy(struct EDBMSelectID_Context *sel_id_ctx);
+struct BMElem *EDBM_select_id_bm_elem_get(struct EDBMSelectID_Context *sel_id_ctx,
+ 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,
- bool use_cycle);
+ bool use_cycle,
+ struct Base **bases,
+ uint bases_len,
+ uint *r_base_index);
struct BMVert *EDBM_vert_find_nearest(struct ViewContext *vc, float *r_dist);
struct BMEdge *EDBM_edge_find_nearest_ex(struct ViewContext *vc,
float *r_dist,
float *r_dist_center,
const bool use_select_bias,
- const bool use_cycle,
- struct BMEdge **r_eed_zbuf);
+ bool use_cycle,
+ struct BMEdge **r_eed_zbuf,
+ struct Base **bases,
+ uint bases_len,
+ uint *r_base_index);
struct BMEdge *EDBM_edge_find_nearest(struct ViewContext *vc, float *r_dist);
struct BMFace *EDBM_face_find_nearest_ex(struct ViewContext *vc,
float *r_dist,
float *r_dist_center,
const bool use_select_bias,
- const bool use_cycle,
- struct BMFace **r_efa_zbuf);
+ bool use_cycle,
+ struct BMFace **r_efa_zbuf,
+ struct Base **bases,
+ uint bases_len,
+ uint *r_base_index);
struct BMFace *EDBM_face_find_nearest(struct ViewContext *vc, float *r_dist);
bool EDBM_unified_findnearest(struct ViewContext *vc,
@@ -230,8 +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);
-extern unsigned int bm_vertoffs, bm_solidoffs, bm_wireoffs;
-
/* editmesh_preselect_edgering.c */
struct EditMesh_PreSelEdgeRing;
struct EditMesh_PreSelEdgeRing *EDBM_preselect_edgering_create(void);
@@ -271,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_screen.h b/source/blender/editors/include/ED_screen.h
index 543b2a5781f..a7a95a4a659 100644
--- a/source/blender/editors/include/ED_screen.h
+++ b/source/blender/editors/include/ED_screen.h
@@ -87,9 +87,12 @@ void ED_region_panels_ex(const struct bContext *C,
void ED_region_panels(const struct bContext *C, struct ARegion *ar);
void ED_region_panels_layout_ex(const struct bContext *C,
struct ARegion *ar,
+ struct ListBase *paneltypes,
const char *contexts[],
int contextnr,
- const bool vertical);
+ const bool vertical,
+ const char *category_override);
+
void ED_region_panels_layout(const struct bContext *C, struct ARegion *ar);
void ED_region_panels_draw(const struct bContext *C, struct ARegion *ar);
@@ -142,6 +145,13 @@ void ED_area_do_mgs_subscribe_for_tool_header(const struct bContext *C,
struct ScrArea *sa,
struct ARegion *ar,
struct wmMsgBus *mbus);
+void ED_area_do_mgs_subscribe_for_tool_ui(const struct bContext *C,
+ struct WorkSpace *workspace,
+ struct Scene *scene,
+ struct bScreen *screen,
+ struct ScrArea *sa,
+ struct ARegion *ar,
+ struct wmMsgBus *mbus);
/* message bus */
void ED_region_message_subscribe(struct bContext *C,
@@ -433,8 +443,9 @@ enum {
ED_KEYMAP_ANIMATION = (1 << 6),
ED_KEYMAP_FRAMES = (1 << 7),
ED_KEYMAP_HEADER = (1 << 8),
- ED_KEYMAP_GPENCIL = (1 << 9),
- ED_KEYMAP_FOOTER = (1 << 10),
+ ED_KEYMAP_FOOTER = (1 << 9),
+ ED_KEYMAP_GPENCIL = (1 << 10),
+ ED_KEYMAP_NAVBAR = (1 << 11),
};
/* SCREEN_OT_space_context_cycle direction */
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
new file mode 100644
index 00000000000..a2e3098e949
--- /dev/null
+++ b/source/blender/editors/include/ED_time_scrub_ui.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.
+ *
+ * The Original Code is Copyright (C) 2019 Blender Foundation.
+ * All rights reserved.
+ */
+
+/** \file
+ * \ingroup editors
+ */
+
+#ifndef __ED_SCRUBBING_H__
+#define __ED_SCRUBBING_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);
+
+bool ED_event_in_scrubbing_region(const struct ARegion *ar, const struct wmEvent *event);
+
+void ED_channel_search_draw(const struct bContext *C,
+ struct ARegion *ar,
+ struct bDopeSheet *dopesheet);
+
+#endif /* __ED_SCRUBBING_H__ */
diff --git a/source/blender/editors/include/ED_view3d.h b/source/blender/editors/include/ED_view3d.h
index fd51419a3ee..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;
@@ -108,8 +109,6 @@ enum eV3DCursorOrient {
void ED_view3d_background_color_get(const struct Scene *scene,
const struct View3D *v3d,
float r_color[3]);
-void ED_view3d_cursor3d_calc_mat3(const struct Scene *scene, float mat[3][3]);
-void ED_view3d_cursor3d_calc_mat4(const struct Scene *scene, float mat[4][4]);
void ED_view3d_cursor3d_position(struct bContext *C,
const int mval[2],
const bool use_depth,
@@ -451,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,
@@ -572,7 +564,6 @@ void ED_view3d_draw_offscreen(struct Depsgraph *depsgraph,
bool do_sky,
bool is_persp,
const char *viewname,
- struct GPUFXSettings *fx_settings,
const bool do_color_managment,
struct GPUOffScreen *ofs,
struct GPUViewport *viewport);
@@ -593,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,
@@ -624,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);
@@ -730,4 +721,9 @@ void ED_view3d_gizmo_mesh_preselect_get_active(struct bContext *C,
struct Base **r_base,
struct BMElem **r_ele);
+/* space_view3d.c */
+void ED_view3d_buttons_region_layout_ex(const struct bContext *C,
+ struct ARegion *ar,
+ const char *category_override);
+
#endif /* __ED_VIEW3D_H__ */
diff --git a/source/blender/editors/include/UI_icons.h b/source/blender/editors/include/UI_icons.h
index 2f624007c98..048f30bdf26 100644
--- a/source/blender/editors/include/UI_icons.h
+++ b/source/blender/editors/include/UI_icons.h
@@ -24,6 +24,9 @@
/* Note: this is included multiple times with different #defines for DEF_ICON. */
/* Auto define more specific types for places that do not need the distinction. */
+#ifndef DEF_ICON_SCENE
+# define DEF_ICON_SCENE DEF_ICON
+#endif
#ifndef DEF_ICON_COLLECTION
# define DEF_ICON_COLLECTION DEF_ICON
#endif
@@ -66,7 +69,7 @@ DEF_ICON(COLLAPSEMENU)
DEF_ICON(X)
DEF_ICON(DUPLICATE)
DEF_ICON(TRASH)
-DEF_ICON_BLANK(76)
+DEF_ICON(COLLECTION_NEW)
DEF_ICON_BLANK(77)
DEF_ICON(NODE)
DEF_ICON(NODE_SEL)
@@ -93,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)
@@ -133,18 +136,18 @@ DEF_ICON_SHADING(MATERIAL)
DEF_ICON_SHADING(TEXTURE)
DEF_ICON(ANIM)
DEF_ICON_SHADING(WORLD)
-DEF_ICON(SCENE)
-DEF_ICON(OUTPUT)
+DEF_ICON_SCENE(SCENE)
+DEF_ICON_SCENE(OUTPUT)
DEF_ICON_BLANK(145)
DEF_ICON_BLANK(146)
DEF_ICON(SCRIPT)
DEF_ICON_MODIFIER(PARTICLES)
-DEF_ICON(PHYSICS)
-DEF_ICON(SPEAKER)
+DEF_ICON_MODIFIER(PHYSICS)
+DEF_ICON_OBJECT_DATA(SPEAKER)
DEF_ICON_BLANK(151)
-DEF_ICON(TOOL_SETTINGS)
-DEF_ICON(SHADERFX)
-DEF_ICON(MODIFIER)
+DEF_ICON_SCENE(TOOL_SETTINGS)
+DEF_ICON_MODIFIER(SHADERFX)
+DEF_ICON_MODIFIER(MODIFIER)
DEF_ICON_BLANK(155)
DEF_ICON_BLANK(156)
DEF_ICON_BLANK(157)
@@ -163,7 +166,7 @@ DEF_ICON(FILEBROWSER)
DEF_ICON(IMAGE)
DEF_ICON(INFO)
DEF_ICON(SEQUENCE)
-DEF_ICON(TEXT)
+DEF_ICON_OBJECT_DATA(TEXT)
DEF_ICON_BLANK(174)
DEF_ICON(SOUND)
DEF_ICON(ACTION)
@@ -211,27 +214,27 @@ DEF_ICON(TRACKING_REFINE_FORWARDS)
DEF_ICON_BLANK(77b)
/* DATA */
-DEF_ICON(SCENE_DATA)
-DEF_ICON(RENDERLAYERS)
+DEF_ICON_SCENE(SCENE_DATA)
+DEF_ICON_SCENE(RENDERLAYERS)
DEF_ICON_SHADING(WORLD_DATA)
-DEF_ICON(OBJECT_DATA)
-DEF_ICON(MESH_DATA)
-DEF_ICON(CURVE_DATA)
-DEF_ICON(META_DATA)
-DEF_ICON(LATTICE_DATA)
-DEF_ICON_SHADING(LIGHT_DATA)
+DEF_ICON_OBJECT(OBJECT_DATA)
+DEF_ICON_OBJECT_DATA(MESH_DATA)
+DEF_ICON_OBJECT_DATA(CURVE_DATA)
+DEF_ICON_OBJECT_DATA(META_DATA)
+DEF_ICON_OBJECT_DATA(LATTICE_DATA)
+DEF_ICON_OBJECT_DATA(LIGHT_DATA)
DEF_ICON_SHADING(MATERIAL_DATA)
DEF_ICON_SHADING(TEXTURE_DATA)
DEF_ICON(ANIM_DATA)
-DEF_ICON(CAMERA_DATA)
-DEF_ICON(PARTICLE_DATA)
+DEF_ICON_OBJECT_DATA(CAMERA_DATA)
+DEF_ICON_OBJECT_DATA(PARTICLE_DATA)
DEF_ICON(LIBRARY_DATA_DIRECT)
DEF_ICON_COLLECTION(GROUP)
-DEF_ICON(ARMATURE_DATA)
+DEF_ICON_OBJECT_DATA(ARMATURE_DATA)
DEF_ICON(COMMUNITY)
-DEF_ICON(BONE_DATA)
+DEF_ICON_OBJECT_DATA(BONE_DATA)
DEF_ICON_MODIFIER(CONSTRAINT)
-DEF_ICON(SHAPEKEY_DATA)
+DEF_ICON_OBJECT_DATA(SHAPEKEY_DATA)
DEF_ICON_MODIFIER(CONSTRAINT_BONE)
DEF_ICON(CAMERA_STEREO)
DEF_ICON(PACKAGE)
@@ -243,10 +246,10 @@ DEF_ICON_SHADING(BRUSH_DATA)
DEF_ICON_SHADING(IMAGE_DATA)
DEF_ICON(FILE)
DEF_ICON(FCURVE)
-DEF_ICON(FONT_DATA)
-DEF_ICON(RENDER_RESULT)
-DEF_ICON(SURFACE_DATA)
-DEF_ICON(EMPTY_DATA)
+DEF_ICON_OBJECT_DATA(FONT_DATA)
+DEF_ICON_SCENE(RENDER_RESULT)
+DEF_ICON_OBJECT_DATA(SURFACE_DATA)
+DEF_ICON_OBJECT_DATA(EMPTY_DATA)
DEF_ICON(PRESET)
DEF_ICON(RENDER_ANIMATION)
DEF_ICON(RENDER_STILL)
@@ -254,7 +257,7 @@ DEF_ICON(LIBRARY_DATA_BROKEN)
DEF_ICON(BOIDS)
DEF_ICON(STRANDS)
DEF_ICON(LIBRARY_DATA_INDIRECT)
-DEF_ICON(GREASEPENCIL)
+DEF_ICON_OBJECT_DATA(GREASEPENCIL)
DEF_ICON_SHADING(LINE_DATA)
DEF_ICON(LIBRARY_DATA_OVERRIDE)
DEF_ICON(GROUP_BONE)
@@ -320,7 +323,7 @@ DEF_ICON(RESTRICT_SELECT_ON)
DEF_ICON(RESTRICT_SELECT_OFF)
DEF_ICON(RESTRICT_RENDER_ON)
DEF_ICON(RESTRICT_RENDER_OFF)
-DEF_ICON_BLANK(330)
+DEF_ICON(RESTRICT_INSTANCED_OFF)
/* OUTLINER */
DEF_ICON_OBJECT_DATA(OUTLINER_DATA_EMPTY)
@@ -334,7 +337,7 @@ DEF_ICON_OBJECT_DATA(OUTLINER_DATA_ARMATURE)
DEF_ICON_OBJECT_DATA(OUTLINER_DATA_FONT)
DEF_ICON_OBJECT_DATA(OUTLINER_DATA_SURFACE)
DEF_ICON_OBJECT_DATA(OUTLINER_DATA_SPEAKER)
-DEF_ICON_BLANK(344)
+DEF_ICON_OBJECT_DATA(OUTLINER_DATA_LIGHTPROBE)
DEF_ICON_BLANK(345)
DEF_ICON_OBJECT_DATA(OUTLINER_DATA_GREASEPENCIL)
DEF_ICON(GP_SELECT_POINTS)
@@ -348,7 +351,7 @@ DEF_ICON(ONIONSKIN_OFF)
DEF_ICON(ONIONSKIN_ON)
DEF_ICON(RESTRICT_VIEW_ON)
DEF_ICON(RESTRICT_VIEW_OFF)
-DEF_ICON_BLANK(353)
+DEF_ICON(RESTRICT_INSTANCED_ON)
/* PRIMITIVES */
DEF_ICON(MESH_PLANE)
@@ -363,11 +366,11 @@ DEF_ICON(MESH_TORUS)
DEF_ICON(MESH_CONE)
DEF_ICON(MESH_CAPSULE)
DEF_ICON(EMPTY_SINGLE_ARROW)
-DEF_ICON_SHADING(LIGHT_POINT)
-DEF_ICON_SHADING(LIGHT_SUN)
-DEF_ICON_SHADING(LIGHT_SPOT)
-DEF_ICON_SHADING(LIGHT_HEMI)
-DEF_ICON_SHADING(LIGHT_AREA)
+DEF_ICON_OBJECT_DATA(LIGHT_POINT)
+DEF_ICON_OBJECT_DATA(LIGHT_SUN)
+DEF_ICON_OBJECT_DATA(LIGHT_SPOT)
+DEF_ICON_OBJECT_DATA(LIGHT_HEMI)
+DEF_ICON_OBJECT_DATA(LIGHT_AREA)
DEF_ICON(CUBE)
DEF_ICON(SPHERE)
DEF_ICON(CONE)
@@ -393,9 +396,9 @@ DEF_ICON(CURVE_BEZCIRCLE)
DEF_ICON(CURVE_NCURVE)
DEF_ICON(CURVE_NCIRCLE)
DEF_ICON(CURVE_PATH)
-DEF_ICON_SHADING(LIGHTPROBE_CUBEMAP)
-DEF_ICON_SHADING(LIGHTPROBE_PLANAR)
-DEF_ICON_SHADING(LIGHTPROBE_GRID)
+DEF_ICON_OBJECT_DATA(LIGHTPROBE_CUBEMAP)
+DEF_ICON_OBJECT_DATA(LIGHTPROBE_PLANAR)
+DEF_ICON_OBJECT_DATA(LIGHTPROBE_GRID)
DEF_ICON_BLANK(406)
DEF_ICON_BLANK(407)
DEF_ICON(COLOR_RED)
@@ -422,8 +425,8 @@ DEF_ICON(FORCE_DRAG)
DEF_ICON(FORCE_SMOKEFLOW)
DEF_ICON_BLANK(673)
DEF_ICON_BLANK(674)
-DEF_ICON_BLANK(675)
-DEF_ICON_BLANK(676)
+DEF_ICON(RIGID_BODY)
+DEF_ICON(RIGID_BODY_CONSTRAINT)
DEF_ICON_BLANK(677)
DEF_ICON_BLANK(678)
DEF_ICON_BLANK(679)
@@ -456,11 +459,11 @@ DEF_ICON_BLANK(707)
DEF_ICON_BLANK(708)
DEF_ICON_BLANK(709)
DEF_ICON_BLANK(710)
-DEF_ICON_BLANK(711)
-DEF_ICON_BLANK(712)
-DEF_ICON_BLANK(713)
-DEF_ICON_BLANK(714)
-DEF_ICON_BLANK(715)
+DEF_ICON(SELECT_SET)
+DEF_ICON(SELECT_EXTEND)
+DEF_ICON(SELECT_SUBTRACT)
+DEF_ICON(SELECT_INTERSECT)
+DEF_ICON(SELECT_DIFFERENCE)
/* EMPTY */
DEF_ICON(ALIGN_LEFT)
@@ -485,10 +488,10 @@ DEF_ICON_BLANK(748)
DEF_ICON_BLANK(749)
DEF_ICON_BLANK(750)
DEF_ICON_BLANK(751)
-DEF_ICON_BLANK(752)
-DEF_ICON_BLANK(753)
-DEF_ICON_BLANK(754)
-DEF_ICON_BLANK(755)
+DEF_ICON(HOLDOUT_OFF)
+DEF_ICON(HOLDOUT_ON)
+DEF_ICON(INDIRECT_ONLY_OFF)
+DEF_ICON(INDIRECT_ONLY_ON)
/* EMPTY */
DEF_ICON_BLANK(501)
@@ -635,7 +638,7 @@ DEF_ICON(VERTEXSEL)
DEF_ICON(EDGESEL)
DEF_ICON(FACESEL)
DEF_ICON_BLANK(209)
-DEF_ICON_BLANK(210)
+DEF_ICON(CURSOR)
DEF_ICON(PIVOT_BOUNDBOX)
DEF_ICON(PIVOT_CURSOR)
DEF_ICON(PIVOT_INDIVIDUAL)
@@ -696,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)
@@ -708,7 +711,7 @@ DEF_ICON_BLANK(240)
DEF_ICON_BLANK(241)
DEF_ICON_BLANK(242)
DEF_ICON_BLANK(243)
-DEF_ICON_BLANK(244)
+DEF_ICON(GIZMO)
DEF_ICON(ORIENTATION_CURSOR)
DEF_ICON(NORMALS_VERTEX)
DEF_ICON(NORMALS_FACE)
@@ -818,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)
@@ -1022,6 +1025,7 @@ DEF_ICON_COLOR(EVENT_RETURN)
#undef DEF_ICON
#undef DEF_ICON_ERROR
+#undef DEF_ICON_SCENE
#undef DEF_ICON_COLLECTION
#undef DEF_ICON_OBJECT
#undef DEF_ICON_OBJECT_DATA
diff --git a/source/blender/editors/include/UI_interface.h b/source/blender/editors/include/UI_interface.h
index 18960853011..fddd8f09b87 100644
--- a/source/blender/editors/include/UI_interface.h
+++ b/source/blender/editors/include/UI_interface.h
@@ -228,6 +228,7 @@ enum {
#define UI_PANEL_WIDTH 340
#define UI_COMPACT_PANEL_WIDTH 160
+#define UI_SIDEBAR_PANEL_WIDTH 220
#define UI_NAVIGATION_REGION_WIDTH UI_COMPACT_PANEL_WIDTH
#define UI_NARROW_NAVIGATION_REGION_WIDTH 100
@@ -280,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 */
@@ -594,9 +598,16 @@ struct uiLayout *UI_pie_menu_layout(struct uiPieMenu *pie);
typedef uiBlock *(*uiBlockCreateFunc)(struct bContext *C, struct ARegion *ar, void *arg1);
typedef void (*uiBlockCancelFunc)(struct bContext *C, void *arg1);
-void UI_popup_block_invoke(struct bContext *C, uiBlockCreateFunc func, void *arg);
-void UI_popup_block_invoke_ex(
- struct bContext *C, uiBlockCreateFunc func, void *arg, const char *opname, int opcontext);
+void UI_popup_block_invoke(struct bContext *C,
+ uiBlockCreateFunc func,
+ void *arg,
+ void (*arg_free)(void *arg));
+void UI_popup_block_invoke_ex(struct bContext *C,
+ uiBlockCreateFunc func,
+ void *arg,
+ void (*arg_free)(void *arg),
+ const char *opname,
+ int opcontext);
void UI_popup_block_ex(struct bContext *C,
uiBlockCreateFunc func,
uiBlockHandleFunc popup_func,
@@ -641,6 +652,7 @@ enum {
UI_BLOCK_THEME_STYLE_POPUP = 1,
};
void UI_block_theme_style_set(uiBlock *block, char theme_style);
+char UI_block_emboss_get(uiBlock *block);
void UI_block_emboss_set(uiBlock *block, char dt);
void UI_block_free(const struct bContext *C, uiBlock *block);
@@ -1618,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);
@@ -1629,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);
@@ -1702,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)
diff --git a/source/blender/editors/include/UI_interface_icons.h b/source/blender/editors/include/UI_interface_icons.h
index 5666421c27f..1f15fa3bd4d 100644
--- a/source/blender/editors/include/UI_interface_icons.h
+++ b/source/blender/editors/include/UI_interface_icons.h
@@ -52,8 +52,11 @@ typedef struct IconFile {
* Resizable Icons for Blender
*/
void UI_icons_init(void);
+void UI_icons_reload_internal_textures(void);
+
int UI_icon_get_width(int icon_id);
int UI_icon_get_height(int icon_id);
+bool UI_icon_get_theme_color(int icon_id, unsigned char color[4]);
void UI_id_icon_render(const struct bContext *C,
struct Scene *scene,
@@ -64,16 +67,17 @@ int UI_preview_render_size(enum eIconSizes size);
void UI_icon_draw(float x, float y, int icon_id);
void UI_icon_draw_alpha(float x, float y, int icon_id, float alpha);
-void UI_icon_draw_preview(float x, float y, int icon_id);
-void UI_icon_draw_preview_aspect(float x, float y, int icon_id, float aspect);
-void UI_icon_draw_preview_aspect_size(
- float x, float y, int icon_id, float aspect, float alpha, int size);
-
-void UI_icon_draw_aspect(
- float x, float y, int icon_id, float aspect, float alpha, const char mono_color[4]);
-void UI_icon_draw_aspect_color(
- float x, float y, int icon_id, float aspect, const float rgb[3], const char mono_color[4]);
-void UI_icon_draw_size(float x, float y, int size, int icon_id, float alpha);
+void UI_icon_draw_preview(float x, float y, int icon_id, float aspect, float alpha, int size);
+
+void UI_icon_draw_ex(float x,
+ float y,
+ int icon_id,
+ float aspect,
+ float alpha,
+ float desaturate,
+ const char mono_color[4],
+ const bool mono_border);
+
void UI_icon_draw_desaturate(float x,
float y,
int icon_id,
@@ -81,6 +85,7 @@ void UI_icon_draw_desaturate(float x,
float alpha,
float desaturate,
const char mono_color[4]);
+
void UI_icons_free(void);
void UI_icons_free_drawinfo(void *drawinfo);
diff --git a/source/blender/editors/include/UI_resources.h b/source/blender/editors/include/UI_resources.h
index af94889a1bb..6dc632921ad 100644
--- a/source/blender/editors/include/UI_resources.h
+++ b/source/blender/editors/include/UI_resources.h
@@ -105,6 +105,7 @@ typedef enum ThemeColorID {
TH_FACE_DOT,
TH_FACEDOT_SIZE,
TH_CFRAME,
+ TH_SCRUBBING_BACKGROUND,
TH_TIME_KEYFRAME,
TH_TIME_GP_KEYFRAME,
TH_NURB_ULINE,
@@ -254,6 +255,10 @@ typedef enum ThemeColorID {
TH_MATCH, /* highlight color for search matches */
TH_SELECT_HIGHLIGHT, /* highlight color for selected outliner item */
+ TH_SELECTED_OBJECT, /* selected object color for outliner */
+ TH_ACTIVE_OBJECT, /* active object color for outliner */
+ TH_EDITED_OBJECT, /* edited object color for outliner */
+ TH_ROW_ALTERNATE, /* overlay on every other row */
TH_SKIN_ROOT,
@@ -261,12 +266,15 @@ typedef enum ThemeColorID {
TH_ANIM_INACTIVE, /* no active action */
TH_ANIM_PREVIEW_RANGE, /* preview range overlay */
+ TH_ICON_SCENE,
TH_ICON_COLLECTION,
TH_ICON_OBJECT,
TH_ICON_OBJECT_DATA,
TH_ICON_MODIFIER,
TH_ICON_SHADING,
+ TH_SCROLL_TEXT,
+
TH_NLA_TWEAK, /* 'tweaking' track in NLA */
TH_NLA_TWEAK_DUPLI, /* error/warning flag for other strips referencing dupli strip */
@@ -380,7 +388,7 @@ void UI_GetThemeColorType3ubv(int colorid, int spacetype, unsigned char col[3]);
void UI_GetThemeColorType4ubv(int colorid, int spacetype, unsigned char col[4]);
// get theme color for coloring monochrome icons
-bool UI_GetIconThemeColor4fv(int colorid, float col[4]);
+bool UI_GetIconThemeColor4ubv(int colorid, unsigned char col[4]);
// shade a 3 byte color (same as UI_GetColorPtrBlendShade3ubv with 0.0 factor)
void UI_GetColorPtrShade3ubv(const unsigned char cp1[3], unsigned char col[3], int offset);
diff --git a/source/blender/editors/include/UI_view2d.h b/source/blender/editors/include/UI_view2d.h
index 07dbb49ac07..d03d4b1b4f5 100644
--- a/source/blender/editors/include/UI_view2d.h
+++ b/source/blender/editors/include/UI_view2d.h
@@ -63,9 +63,9 @@ enum eView2D_CommonViewTypes {
/* scroller area */
#define V2D_SCROLL_HEIGHT (0.45f * U.widget_unit)
#define V2D_SCROLL_WIDTH (0.45f * U.widget_unit)
-/* For scrollers with scale markings (text written onto them) */
-#define V2D_SCROLL_HEIGHT_TEXT (0.79f * U.widget_unit)
-#define V2D_SCROLL_WIDTH_TEXT (0.79f * U.widget_unit)
+/* For scrollers with scale handlers */
+#define V2D_SCROLL_HEIGHT_HANDLES (0.6f * U.widget_unit)
+#define V2D_SCROLL_WIDTH_HANDLES (0.6f * U.widget_unit)
/* scroller 'handles' hotspot radius for mouse */
#define V2D_SCROLLER_HANDLE_SIZE (0.6f * U.widget_unit)
@@ -152,30 +152,24 @@ float UI_view2d_grid_resolution_y__values(const struct View2D *v2d);
/* scale indicator text drawing */
void UI_view2d_draw_scale_y__values(const struct ARegion *ar,
const struct View2D *v2d,
- const struct rcti *rect);
+ const struct rcti *rect,
+ int colorid);
void UI_view2d_draw_scale_y__block(const struct ARegion *ar,
const struct View2D *v2d,
- const struct rcti *rect);
-void UI_view2d_draw_scale_x__values(const struct ARegion *ar,
- const struct View2D *v2d,
- const struct rcti *rect);
-void UI_view2d_draw_scale_x__discrete_values(const struct ARegion *ar,
- const struct View2D *v2d,
- const struct rcti *rect);
-void UI_view2d_draw_scale_x__discrete_time(const struct ARegion *ar,
- const struct View2D *v2d,
- const struct rcti *rect,
- const struct Scene *scene);
+ const struct rcti *rect,
+ int colorid);
void UI_view2d_draw_scale_x__discrete_frames_or_seconds(const struct ARegion *ar,
const struct View2D *v2d,
const struct rcti *rect,
const struct Scene *scene,
- bool display_seconds);
+ bool display_seconds,
+ int colorid);
void UI_view2d_draw_scale_x__frames_or_seconds(const struct ARegion *ar,
const struct View2D *v2d,
const struct rcti *rect,
const struct Scene *scene,
- bool display_seconds);
+ bool display_seconds,
+ int colorid);
/* scrollbar drawing */
View2DScrollers *UI_view2d_scrollers_calc(struct View2D *v2d, const struct rcti *mask_custom);
@@ -183,16 +177,7 @@ void UI_view2d_scrollers_draw(struct View2D *v2d, View2DScrollers *scrollers);
void UI_view2d_scrollers_free(View2DScrollers *scrollers);
/* list view tools */
-void UI_view2d_listview_cell_to_view(struct View2D *v2d,
- float columnwidth,
- float rowheight,
- float startx,
- float starty,
- int column,
- int row,
- struct rctf *rect);
-void UI_view2d_listview_view_to_cell(struct View2D *v2d,
- float columnwidth,
+void UI_view2d_listview_view_to_cell(float columnwidth,
float rowheight,
float startx,
float starty,
@@ -200,15 +185,6 @@ void UI_view2d_listview_view_to_cell(struct View2D *v2d,
float viewy,
int *column,
int *row);
-void UI_view2d_listview_visible_cells(struct View2D *v2d,
- float columnwidth,
- float rowheight,
- float startx,
- float starty,
- int *column_min,
- int *column_max,
- int *row_min,
- int *row_max);
/* coordinate conversion */
float UI_view2d_region_to_view_x(const struct View2D *v2d, float x);
@@ -282,6 +258,8 @@ void UI_view2d_smooth_view(struct bContext *C,
struct ARegion *ar,
const struct rctf *cur,
const int smooth_viewtx);
+
#define UI_MARKER_MARGIN_Y (42 * UI_DPI_FAC)
+#define UI_SCRUBBING_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 42f4b4495c3..931a4faa1c0 100644
--- a/source/blender/editors/interface/interface.c
+++ b/source/blender/editors/interface/interface.c
@@ -1086,7 +1086,6 @@ static bool ui_but_event_operator_string_from_menu(const bContext *C,
}
IDP_FreeProperty(prop_menu);
- MEM_freeN(prop_menu);
return found;
}
@@ -1135,7 +1134,6 @@ static bool ui_but_event_operator_string_from_panel(const bContext *C,
}
IDP_FreeProperty(prop_panel);
- MEM_freeN(prop_panel);
return found;
}
@@ -1356,7 +1354,6 @@ static bool ui_but_event_property_operator_string(const bContext *C,
/* cleanup */
IDP_FreeProperty(prop_path);
- MEM_freeN(prop_path);
if (data_path) {
MEM_freeN(data_path);
}
@@ -1687,6 +1684,18 @@ void UI_block_draw(const bContext *C, uiBlock *block)
}
else if (block->panel) {
bool show_background = ar->alignment != RGN_ALIGN_FLOAT;
+ if (show_background) {
+ if (block->panel->type && (block->panel->type->flag & PNL_NO_HEADER)) {
+ if (ar->regiontype == RGN_TYPE_TOOLS) {
+ /* We never want a background around active tools. */
+ show_background = false;
+ }
+ else {
+ /* Without a header there is no background except for region overlap. */
+ show_background = ar->overlap != 0;
+ }
+ }
+ }
ui_draw_aligned_panel(&style, block, &rect, UI_panel_category_is_visible(ar), show_background);
}
@@ -1836,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)
@@ -2763,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(&but->rnapoin, but->rnaprop, PointerRNA_NULL);
+ RNA_property_pointer_set(&but->rnapoin, but->rnaprop, PointerRNA_NULL, NULL);
return true;
}
else {
@@ -2779,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(&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(&but->rnapoin, but->rnaprop, rptr);
+ RNA_property_pointer_set(&but->rnapoin, but->rnaprop, rptr, NULL);
}
return true;
@@ -3235,6 +3247,11 @@ uiBlock *UI_block_begin(const bContext *C, ARegion *region, const char *name, sh
return block;
}
+char UI_block_emboss_get(uiBlock *block)
+{
+ return block->dt;
+}
+
void UI_block_emboss_set(uiBlock *block, char dt)
{
block->dt = dt;
@@ -3721,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_anim.c b/source/blender/editors/interface/interface_anim.c
index b9de504f3b2..4a0a19f57cf 100644
--- a/source/blender/editors/interface/interface_anim.c
+++ b/source/blender/editors/interface/interface_anim.c
@@ -82,6 +82,11 @@ void ui_but_anim_flag(uiBut *but, float cfra)
if (fcu) {
if (!driven) {
+ /* Empty curves are ignored by the animation evaluation system. */
+ if (BKE_fcurve_is_empty(fcu)) {
+ return;
+ }
+
but->flag |= UI_BUT_ANIMATED;
/* T41525 - When the active action is a NLA strip being edited,
diff --git a/source/blender/editors/interface/interface_context_menu.c b/source/blender/editors/interface/interface_context_menu.c
index 748d6e6c183..d1f72519046 100644
--- a/source/blender/editors/interface/interface_context_menu.c
+++ b/source/blender/editors/interface/interface_context_menu.c
@@ -58,30 +58,89 @@
/** \name Button Context Menu
* \{ */
-static void but_shortcut_name_func(bContext *C, void *arg1, int UNUSED(event))
+static IDProperty *shortcut_property_from_rna(bContext *C, uiBut *but)
{
- uiBut *but = (uiBut *)arg1;
+ /* Compute data path from context to property. */
+ const char *member_id = WM_context_member_from_ptr(C, &but->rnapoin);
+ const char *data_path = RNA_path_from_ID_to_struct(&but->rnapoin);
+ const char *member_id_data_path = member_id;
+
+ if (data_path) {
+ member_id_data_path = BLI_sprintfN("%s.%s", member_id, data_path);
+ MEM_freeN((void *)data_path);
+ }
- if (but->optype) {
- char shortcut_str[128];
+ const char *prop_id = RNA_property_identifier(but->rnaprop);
+ const char *final_data_path = BLI_sprintfN("%s.%s", member_id_data_path, prop_id);
- IDProperty *prop = (but->opptr) ? but->opptr->data : NULL;
+ if (member_id != member_id_data_path) {
+ MEM_freeN((void *)member_id_data_path);
+ }
+
+ /* Create ID property of data path, to pass to the operator. */
+ IDProperty *prop;
+ IDPropertyTemplate val = {0};
+ prop = IDP_New(IDP_GROUP, &val, __func__);
+ IDP_AddToGroup(prop, IDP_NewString(final_data_path, "data_path", strlen(final_data_path) + 1));
+
+ MEM_freeN((void *)final_data_path);
+
+ return prop;
+}
- /* complex code to change name of button */
- if (WM_key_event_operator_string(C,
- but->optype->idname,
- but->opcontext,
- prop,
- true,
- shortcut_str,
- sizeof(shortcut_str))) {
- ui_but_add_shortcut(but, shortcut_str, true);
+static const char *shortcut_get_operator_property(bContext *C, uiBut *but, IDProperty **prop)
+{
+ if (but->optype) {
+ /* Operator */
+ *prop = (but->opptr && but->opptr->data) ? IDP_CopyProperty(but->opptr->data) : NULL;
+ return but->optype->idname;
+ }
+ else if (but->rnaprop) {
+ if (RNA_property_type(but->rnaprop) == PROP_BOOLEAN) {
+ /* Boolean */
+ *prop = shortcut_property_from_rna(C, but);
+ return "WM_OT_context_toggle";
}
- else {
- /* simply strip the shortcut */
- ui_but_add_shortcut(but, NULL, true);
+ else if (RNA_property_type(but->rnaprop) == PROP_ENUM) {
+ /* Enum */
+ *prop = shortcut_property_from_rna(C, but);
+ return "WM_OT_context_menu_enum";
}
}
+
+ *prop = NULL;
+ return NULL;
+}
+
+static void shortcut_free_operator_property(IDProperty *prop)
+{
+ if (prop) {
+ IDP_FreeProperty(prop);
+ }
+}
+
+static void but_shortcut_name_func(bContext *C, void *arg1, int UNUSED(event))
+{
+ uiBut *but = (uiBut *)arg1;
+ char shortcut_str[128];
+
+ IDProperty *prop;
+ const char *idname = shortcut_get_operator_property(C, but, &prop);
+ if (idname == NULL) {
+ return;
+ }
+
+ /* complex code to change name of button */
+ if (WM_key_event_operator_string(
+ C, idname, but->opcontext, prop, true, shortcut_str, sizeof(shortcut_str))) {
+ ui_but_add_shortcut(but, shortcut_str, true);
+ }
+ else {
+ /* simply strip the shortcut */
+ ui_but_add_shortcut(but, NULL, true);
+ }
+
+ shortcut_free_operator_property(prop);
}
static uiBlock *menu_change_shortcut(bContext *C, ARegion *ar, void *arg)
@@ -94,15 +153,18 @@ static uiBlock *menu_change_shortcut(bContext *C, ARegion *ar, void *arg)
PointerRNA ptr;
uiLayout *layout;
uiStyle *style = UI_style_get_dpi();
- IDProperty *prop = (but->opptr) ? but->opptr->data : NULL;
+ IDProperty *prop;
+ const char *idname = shortcut_get_operator_property(C, but, &prop);
kmi = WM_key_event_operator(C,
- but->optype->idname,
+ idname,
but->opcontext,
prop,
EVT_TYPE_MASK_HOTKEY_INCLUDE,
EVT_TYPE_MASK_HOTKEY_EXCLUDE,
&km);
+ U.runtime.is_dirty = true;
+
BLI_assert(kmi != NULL);
RNA_pointer_create(&wm->id, &RNA_KeyMapItem, kmi, &ptr);
@@ -118,6 +180,8 @@ static uiBlock *menu_change_shortcut(bContext *C, ARegion *ar, void *arg)
UI_block_bounds_set_popup(block, 6, (const int[2]){-50, 26});
+ shortcut_free_operator_property(prop);
+
return block;
}
@@ -135,25 +199,24 @@ static uiBlock *menu_add_shortcut(bContext *C, ARegion *ar, void *arg)
PointerRNA ptr;
uiLayout *layout;
uiStyle *style = UI_style_get_dpi();
- IDProperty *prop = (but->opptr) ? but->opptr->data : NULL;
int kmi_id;
+ IDProperty *prop;
+ const char *idname = shortcut_get_operator_property(C, but, &prop);
/* XXX this guess_opname can potentially return a different keymap
* than being found on adding later... */
- km = WM_keymap_guess_opname(C, but->optype->idname);
- kmi = WM_keymap_add_item(km, but->optype->idname, AKEY, KM_PRESS, 0, 0);
+ km = WM_keymap_guess_opname(C, idname);
+ kmi = WM_keymap_add_item(km, idname, AKEY, KM_PRESS, 0, 0);
kmi_id = kmi->id;
- /* copy properties, prop can be NULL for reset */
- if (prop) {
- prop = IDP_CopyProperty(prop);
- }
+ /* This takes ownership of prop, or prop can be NULL for reset. */
WM_keymap_item_properties_reset(kmi, prop);
/* update and get pointers again */
WM_keyconfig_update(wm);
+ U.runtime.is_dirty = true;
- km = WM_keymap_guess_opname(C, but->optype->idname);
+ km = WM_keymap_guess_opname(C, idname);
kmi = WM_keymap_item_find_id(km, kmi_id);
RNA_pointer_create(&wm->id, &RNA_KeyMapItem, kmi, &ptr);
@@ -171,6 +234,7 @@ static uiBlock *menu_add_shortcut(bContext *C, ARegion *ar, void *arg)
#ifdef USE_KEYMAP_ADD_HACK
g_kmi_id_hack = kmi_id;
#endif
+
return block;
}
@@ -179,20 +243,21 @@ static void menu_add_shortcut_cancel(struct bContext *C, void *arg1)
uiBut *but = (uiBut *)arg1;
wmKeyMap *km;
wmKeyMapItem *kmi;
-#ifndef USE_KEYMAP_ADD_HACK
- IDProperty *prop;
-#endif
int kmi_id;
+ IDProperty *prop;
+ const char *idname = shortcut_get_operator_property(C, but, &prop);
+
#ifdef USE_KEYMAP_ADD_HACK
- km = WM_keymap_guess_opname(C, but->optype->idname);
+ km = WM_keymap_guess_opname(C, idname);
kmi_id = g_kmi_id_hack;
UNUSED_VARS(but);
#else
- prop = (but->opptr) ? but->opptr->data : NULL;
- kmi_id = WM_key_event_operator_id(C, but->optype->idname, but->opcontext, prop, true, &km);
+ kmi_id = WM_key_event_operator_id(C, idname, but->opcontext, prop, true, &km);
#endif
+ shortcut_free_operator_property(prop);
+
kmi = WM_keymap_item_find_id(km, kmi_id);
WM_keymap_remove_item(km, kmi);
}
@@ -200,7 +265,7 @@ static void menu_add_shortcut_cancel(struct bContext *C, void *arg1)
static void popup_change_shortcut_func(bContext *C, void *arg1, void *UNUSED(arg2))
{
uiBut *but = (uiBut *)arg1;
- UI_popup_block_invoke(C, menu_change_shortcut, but);
+ UI_popup_block_invoke(C, menu_change_shortcut, but, NULL);
}
static void remove_shortcut_func(bContext *C, void *arg1, void *UNUSED(arg2))
@@ -208,10 +273,11 @@ static void remove_shortcut_func(bContext *C, void *arg1, void *UNUSED(arg2))
uiBut *but = (uiBut *)arg1;
wmKeyMap *km;
wmKeyMapItem *kmi;
- IDProperty *prop = (but->opptr) ? but->opptr->data : NULL;
+ IDProperty *prop;
+ const char *idname = shortcut_get_operator_property(C, but, &prop);
kmi = WM_key_event_operator(C,
- but->optype->idname,
+ idname,
but->opcontext,
prop,
EVT_TYPE_MASK_HOTKEY_INCLUDE,
@@ -220,7 +286,9 @@ static void remove_shortcut_func(bContext *C, void *arg1, void *UNUSED(arg2))
BLI_assert(kmi != NULL);
WM_keymap_remove_item(km, kmi);
+ U.runtime.is_dirty = true;
+ shortcut_free_operator_property(prop);
but_shortcut_name_func(C, but, 0);
}
@@ -323,6 +391,7 @@ static void popup_user_menu_add_or_replace_func(bContext *C, void *arg1, void *U
{
uiBut *but = arg1;
bUserMenu *um = ED_screen_user_menu_ensure(C);
+ U.runtime.is_dirty = true;
ui_but_user_menu_add(C, but, um);
}
@@ -330,6 +399,7 @@ static void popup_user_menu_remove_func(bContext *UNUSED(C), void *arg1, void *a
{
bUserMenu *um = arg1;
bUserMenuItem *umi = arg2;
+ U.runtime.is_dirty = true;
ED_screen_user_menu_item_remove(&um->items, umi);
}
@@ -890,16 +960,18 @@ bool ui_popup_context_menu_for_button(bContext *C, uiBut *but)
uiItemS(layout);
}
- /* Operator buttons */
- if (but->optype) {
+ /* Shortcut menu */
+ IDProperty *prop;
+ const char *idname = shortcut_get_operator_property(C, but, &prop);
+ if (idname != NULL) {
uiBlock *block = uiLayoutGetBlock(layout);
uiBut *but2;
- IDProperty *prop = (but->opptr) ? but->opptr->data : NULL;
int w = uiLayoutGetWidth(layout);
wmKeyMap *km;
+
/* We want to know if this op has a shortcut, be it hotkey or not. */
wmKeyMapItem *kmi = WM_key_event_operator(
- C, but->optype->idname, but->opcontext, prop, EVT_TYPE_MASK_ALL, 0, &km);
+ C, idname, but->opcontext, prop, EVT_TYPE_MASK_ALL, 0, &km);
/* We do have a shortcut, but only keyboard ones are editable that way... */
if (kmi) {
@@ -971,7 +1043,7 @@ bool ui_popup_context_menu_for_button(bContext *C, uiBut *but)
}
}
/* only show 'assign' if there's a suitable key map for it to go in */
- else if (WM_keymap_guess_opname(C, but->optype->idname)) {
+ else if (WM_keymap_guess_opname(C, idname)) {
but2 = uiDefIconTextBut(block,
UI_BTYPE_BUT,
0,
@@ -990,6 +1062,8 @@ bool ui_popup_context_menu_for_button(bContext *C, uiBut *but)
UI_but_func_set(but2, popup_add_shortcut_func, but, NULL);
}
+ shortcut_free_operator_property(prop);
+
/* Set the operator pointer for python access */
uiLayoutSetContextFromBut(layout, but);
@@ -1108,6 +1182,9 @@ void ui_popup_context_menu_for_panel(bContext *C, ARegion *ar, Panel *pa)
if (!any_item_visible) {
return;
}
+ if (pa->type->parent != NULL) {
+ return;
+ }
RNA_pointer_create(&sc->id, &RNA_Panel, pa, &ptr);
diff --git a/source/blender/editors/interface/interface_eyedropper_datablock.c b/source/blender/editors/interface/interface_eyedropper_datablock.c
index 1d90139eade..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(&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 8f19f40d1c0..b9c77b13401 100644
--- a/source/blender/editors/interface/interface_handlers.c
+++ b/source/blender/editors/interface/interface_handlers.c
@@ -551,6 +551,23 @@ static bool ui_but_dragedit_update_mval(uiHandleButtonData *data, int mx)
return true;
}
+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) {
+ StructRNA *base = RNA_struct_base(but->rnapoin.type);
+ if (ELEM(base, &RNA_AddonPreferences, &RNA_KeyConfigPreferences, &RNA_KeyMapItem)) {
+ tag = true;
+ }
+ }
+
+ if (tag) {
+ U.runtime.is_dirty = true;
+ WM_main_add_notifier(NC_WINDOW, NULL);
+ }
+}
+
/** \} */
/* -------------------------------------------------------------------- */
@@ -1334,6 +1351,9 @@ static bool ui_drag_toggle_set_xy_xy(
if (do_check) {
ui_but_update_edited(but);
}
+ if (U.runtime.is_dirty == false) {
+ ui_but_update_preferences_dirty(but);
+ }
changed = true;
}
}
@@ -1715,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(&lptr, lprop, other_value);
+ RNA_property_pointer_set(&lptr, lprop, other_value, NULL);
}
RNA_property_update(C, &lptr, prop);
@@ -3769,7 +3789,7 @@ static void ui_block_open_begin(bContext *C, uiBut *but, uiHandleButtonData *dat
}
if (func || handlefunc) {
- data->menu = ui_popup_block_create(C, data->region, but, func, handlefunc, arg);
+ data->menu = ui_popup_block_create(C, data->region, but, func, handlefunc, arg, NULL);
if (but->block->handle) {
data->menu->popup = but->block->handle->popup;
}
@@ -3949,6 +3969,9 @@ static int ui_do_but_HOTKEYEVT(bContext *C,
if (ELEM(event->type, MOUSEMOVE, INBETWEEN_MOUSEMOVE)) {
return WM_UI_HANDLER_CONTINUE;
}
+ else if (event->type == UNKNOWNKEY) {
+ return WM_UI_HANDLER_CONTINUE;
+ }
if (event->type == LEFTMOUSE && event->val == KM_PRESS) {
/* only cancel if click outside the button */
@@ -5619,6 +5642,13 @@ static int ui_do_but_UNITVEC(
}
}
}
+ else if (event->type == ESCKEY || event->type == RIGHTMOUSE) {
+ if (event->val == KM_PRESS) {
+ data->cancel = true;
+ data->escapecancel = true;
+ button_activate_state(C, but, BUTTON_STATE_EXIT);
+ }
+ }
else if (event->type == LEFTMOUSE && event->val == KM_RELEASE) {
button_activate_state(C, but, BUTTON_STATE_EXIT);
}
@@ -6491,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) {
@@ -6526,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++) {
@@ -7563,6 +7593,10 @@ static void button_activate_exit(
if (block->flag & UI_BLOCK_POPUP_MEMORY) {
ui_popup_menu_memory_set(block, but);
}
+
+ if (U.runtime.is_dirty == false) {
+ ui_but_update_preferences_dirty(but);
+ }
}
/* disable tooltips until mousemove + last active flag */
diff --git a/source/blender/editors/interface/interface_icons.c b/source/blender/editors/interface/interface_icons.c
index 7e295f83390..fa3605269ff 100644
--- a/source/blender/editors/interface/interface_icons.c
+++ b/source/blender/editors/interface/interface_icons.c
@@ -37,6 +37,7 @@
#include "BLI_utildefines.h"
#include "BLI_fileops_types.h"
#include "BLI_math_vector.h"
+#include "BLI_math_color_blend.h"
#include "DNA_brush_types.h"
#include "DNA_curve_types.h"
@@ -83,6 +84,7 @@
# define ICON_GRID_COLS 26
# define ICON_GRID_ROWS 30
+# define ICON_MONO_BORDER_OUTSET 2
# define ICON_GRID_MARGIN 10
# define ICON_GRID_W 32
# define ICON_GRID_H 32
@@ -138,7 +140,8 @@ typedef struct DrawInfo {
} DrawInfo;
typedef struct IconTexture {
- GLuint id;
+ GLuint id[2];
+ int num_textures;
int w;
int h;
float invw;
@@ -154,12 +157,13 @@ typedef struct IconType {
/* static here to cache results of icon directory scan, so it's not
* scanning the filesystem each time the menu is drawn */
static struct ListBase iconfilelist = {NULL, NULL};
-static IconTexture icongltex = {0, 0, 0, 0.0f, 0.0f};
+static IconTexture icongltex = {{0, 0}, 0, 0, 0, 0.0f, 0.0f};
#ifndef WITH_HEADLESS
static const IconType icontypes[] = {
# define DEF_ICON(name) {ICON_TYPE_MONO_TEXTURE, 0},
+# define DEF_ICON_SCENE(name) {ICON_TYPE_MONO_TEXTURE, TH_ICON_SCENE},
# define DEF_ICON_COLLECTION(name) {ICON_TYPE_MONO_TEXTURE, TH_ICON_COLLECTION},
# define DEF_ICON_OBJECT(name) {ICON_TYPE_MONO_TEXTURE, TH_ICON_OBJECT},
# define DEF_ICON_OBJECT_DATA(name) {ICON_TYPE_MONO_TEXTURE, TH_ICON_OBJECT_DATA},
@@ -713,38 +717,146 @@ static void icon_verify_datatoc(IconImage *iimg)
}
}
-static void init_internal_icons(void)
+static ImBuf *create_mono_icon_with_border(ImBuf *buf,
+ int resolution_divider,
+ float border_intensity)
{
- // bTheme *btheme = UI_GetTheme();
- ImBuf *b16buf = NULL, *b32buf = NULL;
- int x, y;
+ ImBuf *result = IMB_dupImBuf(buf);
+ const float border_sharpness = 16.0 / (resolution_divider * resolution_divider);
-# if 0 // temp disabled
- if ((btheme != NULL) && btheme->tui.iconfile[0]) {
- char *icondir = BKE_appdir_folder_id(BLENDER_DATAFILES, "icons");
- char iconfilestr[FILE_MAX];
+ float blurred_alpha_buffer[(ICON_GRID_W + 2 * ICON_MONO_BORDER_OUTSET) *
+ (ICON_GRID_H + 2 * ICON_MONO_BORDER_OUTSET)];
+ const int icon_width = (ICON_GRID_W + 2 * ICON_MONO_BORDER_OUTSET) / resolution_divider;
+ const int icon_height = (ICON_GRID_W + 2 * ICON_MONO_BORDER_OUTSET) / resolution_divider;
- if (icondir) {
- BLI_join_dirfile(iconfilestr, sizeof(iconfilestr), icondir, btheme->tui.iconfile);
+ for (int y = 0; y < ICON_GRID_ROWS; y++) {
+ for (int x = 0; x < ICON_GRID_COLS; x++) {
+ IconType icontype = icontypes[y * ICON_GRID_COLS + x];
+ if (icontype.type != ICON_TYPE_MONO_TEXTURE) {
+ continue;
+ }
- /* if the image is missing bbuf will just be NULL */
- bbuf = IMB_loadiffname(iconfilestr, IB_rect, NULL);
+ int sx = x * (ICON_GRID_W + ICON_GRID_MARGIN) + ICON_GRID_MARGIN - ICON_MONO_BORDER_OUTSET;
+ int sy = y * (ICON_GRID_H + ICON_GRID_MARGIN) + ICON_GRID_MARGIN - ICON_MONO_BORDER_OUTSET;
+ sx = sx / resolution_divider;
+ sy = sy / resolution_divider;
+
+ /* blur the alpha channel and store it in blurred_alpha_buffer */
+ int blur_size = 2 / resolution_divider;
+ for (int bx = 0; bx < icon_width; bx++) {
+ const int asx = MAX2(bx - blur_size, 0);
+ const int aex = MIN2(bx + blur_size + 1, icon_width);
+ for (int by = 0; by < icon_height; by++) {
+ const int asy = MAX2(by - blur_size, 0);
+ const int aey = MIN2(by + blur_size + 1, icon_height);
+
+ // blur alpha channel
+ const int write_offset = by * (ICON_GRID_W + 2 * ICON_MONO_BORDER_OUTSET) + bx;
+ float alpha_accum = 0.0;
+ unsigned int alpha_samples = 0;
+ for (int ax = asx; ax < aex; ax++) {
+ for (int ay = asy; ay < aey; ay++) {
+ const int offset_read = (sy + ay) * buf->x + (sx + ax);
+ unsigned int color_read = buf->rect[offset_read];
+ const float alpha_read = ((color_read & 0xff000000) >> 24) / 255.0;
+ alpha_accum += alpha_read;
+ alpha_samples += 1;
+ }
+ }
+ blurred_alpha_buffer[write_offset] = alpha_accum / alpha_samples;
+ }
+ }
- if (bbuf && (bbuf->x < ICON_IMAGE_W || bbuf->y < ICON_IMAGE_H)) {
- printf(
- "\n***WARNING***\n"
- "Icons file '%s' too small.\n"
- "Using built-in Icons instead\n",
- iconfilestr);
- IMB_freeImBuf(bbuf);
- bbuf = NULL;
+ /* apply blurred alpha */
+ for (int bx = 0; bx < icon_width; bx++) {
+ for (int by = 0; by < icon_height; by++) {
+ const int blurred_alpha_offset = by * (ICON_GRID_W + 2 * ICON_MONO_BORDER_OUTSET) + bx;
+ const int offset_write = (sy + by) * buf->x + (sx + bx);
+ const float blurred_alpha = blurred_alpha_buffer[blurred_alpha_offset];
+ float border_srgb[4] = {
+ 0, 0, 0, MIN2(1.0, blurred_alpha * border_sharpness) * border_intensity};
+
+ const unsigned int color_read = buf->rect[offset_write];
+ const unsigned char *orig_color = (unsigned char *)&color_read;
+
+ float border_rgba[4];
+ float orig_rgba[4];
+ float dest_rgba[4];
+ float dest_srgb[4];
+
+ srgb_to_linearrgb_v4(border_rgba, border_srgb);
+ srgb_to_linearrgb_uchar4(orig_rgba, orig_color);
+ blend_color_interpolate_float(dest_rgba, orig_rgba, border_rgba, 1.0 - orig_rgba[3]);
+ linearrgb_to_srgb_v4(dest_srgb, dest_rgba);
+
+ unsigned int alpha_mask = ((unsigned int)(dest_srgb[3] * 255)) << 24;
+ unsigned int cpack = rgb_to_cpack(dest_srgb[0], dest_srgb[1], dest_srgb[2]) | alpha_mask;
+ result->rect[offset_write] = cpack;
+ }
}
}
- else {
- printf("%s: 'icons' data path not found, continuing\n", __func__);
+ }
+ return result;
+}
+
+/* Generate the mipmap levels for the icon textures
+ * During creation the source16 ImBuf will be freed to reduce memory overhead
+ * A new ImBuf will be returned that needs is owned by the caller.
+ *
+ * FIXME: Mipmap levels are generated until the width of the image is 1, which
+ * are too many levels than that are needed.*/
+static ImBuf *create_mono_icon_mipmaps(ImBuf *source32, ImBuf *source16, int level)
+{
+ if (level == 0) {
+ glTexImage2D(GL_TEXTURE_2D,
+ level,
+ GL_RGBA8,
+ source32->x,
+ source32->y,
+ 0,
+ GL_RGBA,
+ GL_UNSIGNED_BYTE,
+ source32->rect);
+ return create_mono_icon_mipmaps(source32, source16, level + 1);
+ }
+ else {
+ glTexImage2D(GL_TEXTURE_2D,
+ level,
+ GL_RGBA8,
+ source16->x,
+ source16->y,
+ 0,
+ GL_RGBA,
+ GL_UNSIGNED_BYTE,
+ source16->rect);
+ if (source16->x > 1) {
+ ImBuf *nbuf = IMB_onehalf(source16);
+ IMB_freeImBuf(source16);
+ source16 = create_mono_icon_mipmaps(source32, nbuf, level + 1);
}
+ return source16;
}
-# endif
+}
+
+static void free_icons_textures(void)
+{
+ if (icongltex.num_textures > 0) {
+ glDeleteTextures(icongltex.num_textures, icongltex.id);
+ icongltex.id[0] = 0;
+ icongltex.id[1] = 0;
+ icongltex.num_textures = 0;
+ }
+}
+
+/* Reload the textures for internal icons.
+ * This function will release the previous textures. */
+void UI_icons_reload_internal_textures(void)
+{
+ bTheme *btheme = UI_GetTheme();
+ ImBuf *b16buf = NULL, *b32buf = NULL, *b16buf_border = NULL, *b32buf_border = NULL;
+ const float icon_border_intensity = btheme->tui.icon_border_intensity;
+ bool need_icons_with_border = icon_border_intensity > 0.0f;
+
if (b16buf == NULL) {
b16buf = IMB_ibImageFromMemory((const uchar *)datatoc_blender_icons16_png,
datatoc_blender_icons16_png_size,
@@ -753,6 +865,10 @@ static void init_internal_icons(void)
"<blender icons>");
}
if (b16buf) {
+ if (need_icons_with_border) {
+ b16buf_border = create_mono_icon_with_border(b16buf, 2, icon_border_intensity);
+ IMB_premultiply_alpha(b16buf_border);
+ }
IMB_premultiply_alpha(b16buf);
}
@@ -764,88 +880,97 @@ static void init_internal_icons(void)
"<blender icons>");
}
if (b32buf) {
+ if (need_icons_with_border) {
+ b32buf_border = create_mono_icon_with_border(b32buf, 1, icon_border_intensity);
+ IMB_premultiply_alpha(b32buf_border);
+ }
IMB_premultiply_alpha(b32buf);
}
if (b16buf && b32buf) {
/* Free existing texture if any. */
- if (icongltex.id) {
- glDeleteTextures(1, &icongltex.id);
- icongltex.id = 0;
- }
+ free_icons_textures();
/* Allocate OpenGL texture. */
- glGenTextures(1, &icongltex.id);
-
- if (icongltex.id) {
- int level = 2;
+ icongltex.num_textures = need_icons_with_border ? 2 : 1;
+ glGenTextures(icongltex.num_textures, icongltex.id);
+ if (icongltex.id[0]) {
icongltex.w = b32buf->x;
icongltex.h = b32buf->y;
icongltex.invw = 1.0f / b32buf->x;
icongltex.invh = 1.0f / b32buf->y;
- glBindTexture(GL_TEXTURE_2D, icongltex.id);
-
- glTexImage2D(GL_TEXTURE_2D,
- 0,
- GL_RGBA8,
- b32buf->x,
- b32buf->y,
- 0,
- GL_RGBA,
- GL_UNSIGNED_BYTE,
- b32buf->rect);
- glTexImage2D(GL_TEXTURE_2D,
- 1,
- GL_RGBA8,
- b16buf->x,
- b16buf->y,
- 0,
- GL_RGBA,
- GL_UNSIGNED_BYTE,
- b16buf->rect);
-
- while (b16buf->x > 1) {
- ImBuf *nbuf = IMB_onehalf(b16buf);
- glTexImage2D(GL_TEXTURE_2D,
- level,
- GL_RGBA8,
- nbuf->x,
- nbuf->y,
- 0,
- GL_RGBA,
- GL_UNSIGNED_BYTE,
- nbuf->rect);
- level++;
- IMB_freeImBuf(b16buf);
- b16buf = nbuf;
- }
-
+ glBindTexture(GL_TEXTURE_2D, icongltex.id[0]);
+ b16buf = create_mono_icon_mipmaps(b32buf, b16buf, 0);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
+ glBindTexture(GL_TEXTURE_2D, 0);
+ }
+ if (need_icons_with_border && icongltex.id[1]) {
+ glBindTexture(GL_TEXTURE_2D, icongltex.id[1]);
+ b16buf_border = create_mono_icon_mipmaps(b32buf_border, b16buf_border, 0);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glBindTexture(GL_TEXTURE_2D, 0);
}
+ }
- /* Define icons. */
- for (y = 0; y < ICON_GRID_ROWS; y++) {
- /* Row W has monochrome icons. */
- for (x = 0; x < ICON_GRID_COLS; x++) {
- IconType icontype = icontypes[y * ICON_GRID_COLS + x];
- if (!ELEM(icontype.type, ICON_TYPE_COLOR_TEXTURE, ICON_TYPE_MONO_TEXTURE)) {
- continue;
- }
+ IMB_freeImBuf(b16buf);
+ IMB_freeImBuf(b32buf);
+ IMB_freeImBuf(b16buf_border);
+ IMB_freeImBuf(b32buf_border);
+}
- def_internal_icon(b32buf,
- BIFICONID_FIRST + y * ICON_GRID_COLS + x,
- x * (ICON_GRID_W + ICON_GRID_MARGIN) + ICON_GRID_MARGIN,
- y * (ICON_GRID_H + ICON_GRID_MARGIN) + ICON_GRID_MARGIN,
- ICON_GRID_W,
- icontype.type,
- icontype.theme_color);
+static void init_internal_icons(void)
+{
+ int x, y;
+
+# if 0 // temp disabled
+ if ((btheme != NULL) && btheme->tui.iconfile[0]) {
+ char *icondir = BKE_appdir_folder_id(BLENDER_DATAFILES, "icons");
+ char iconfilestr[FILE_MAX];
+
+ if (icondir) {
+ BLI_join_dirfile(iconfilestr, sizeof(iconfilestr), icondir, btheme->tui.iconfile);
+
+ /* if the image is missing bbuf will just be NULL */
+ bbuf = IMB_loadiffname(iconfilestr, IB_rect, NULL);
+
+ if (bbuf && (bbuf->x < ICON_IMAGE_W || bbuf->y < ICON_IMAGE_H)) {
+ printf(
+ "\n***WARNING***\n"
+ "Icons file '%s' too small.\n"
+ "Using built-in Icons instead\n",
+ iconfilestr);
+ IMB_freeImBuf(bbuf);
+ bbuf = NULL;
}
}
+ else {
+ printf("%s: 'icons' data path not found, continuing\n", __func__);
+ }
+ }
+# endif
+
+ /* Define icons. */
+ for (y = 0; y < ICON_GRID_ROWS; y++) {
+ /* Row W has monochrome icons. */
+ for (x = 0; x < ICON_GRID_COLS; x++) {
+ IconType icontype = icontypes[y * ICON_GRID_COLS + x];
+ if (!ELEM(icontype.type, ICON_TYPE_COLOR_TEXTURE, ICON_TYPE_MONO_TEXTURE)) {
+ continue;
+ }
+
+ def_internal_icon(NULL,
+ BIFICONID_FIRST + y * ICON_GRID_COLS + x,
+ x * (ICON_GRID_W + ICON_GRID_MARGIN) + ICON_GRID_MARGIN,
+ y * (ICON_GRID_H + ICON_GRID_MARGIN) + ICON_GRID_MARGIN,
+ ICON_GRID_W,
+ icontype.type,
+ icontype.theme_color);
+ }
}
def_internal_vicon(ICON_SMALL_TRI_RIGHT_VEC, vicon_small_tri_right_draw);
@@ -882,9 +1007,6 @@ static void init_internal_icons(void)
def_internal_vicon(ICON_COLORSET_18_VEC, vicon_colorset_draw_18);
def_internal_vicon(ICON_COLORSET_19_VEC, vicon_colorset_draw_19);
def_internal_vicon(ICON_COLORSET_20_VEC, vicon_colorset_draw_20);
-
- IMB_freeImBuf(b16buf);
- IMB_freeImBuf(b32buf);
}
# endif /* WITH_HEADLESS */
@@ -964,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)
@@ -990,11 +1118,7 @@ ListBase *UI_iconfile_list(void)
void UI_icons_free(void)
{
#ifndef WITH_HEADLESS
- if (icongltex.id) {
- glDeleteTextures(1, &icongltex.id);
- icongltex.id = 0;
- }
-
+ free_icons_textures();
free_iconfile_list(&iconfilelist);
BKE_icons_free();
#endif
@@ -1104,10 +1228,22 @@ int UI_icon_get_height(int icon_id)
return 0;
}
+bool UI_icon_get_theme_color(int icon_id, uchar color[4])
+{
+ Icon *icon = BKE_icon_get(icon_id);
+ if (icon == NULL) {
+ return false;
+ }
+
+ DrawInfo *di = icon_ensure_drawinfo(icon);
+ return UI_GetIconThemeColor4ubv(di->data.texture.theme_color, color);
+}
+
void UI_icons_init()
{
#ifndef WITH_HEADLESS
init_iconfile_list(&iconfilelist);
+ UI_icons_reload_internal_textures();
init_internal_icons();
init_brush_icons();
init_event_icons();
@@ -1348,7 +1484,6 @@ static void icon_draw_rect(float x,
int rh,
uint *rect,
float alpha,
- const float rgb[3],
const float desaturate)
{
ImBuf *ima = NULL;
@@ -1366,12 +1501,6 @@ static void icon_draw_rect(float x,
/* modulate color */
float col[4] = {1.0f, 1.0f, 1.0f, alpha};
- if (rgb) {
- col[0] = rgb[0];
- col[1] = rgb[1];
- col[2] = rgb[2];
- }
-
/* rect contains image in 'rendersize', we only scale if needed */
if (rw != w || rh != h) {
/* preserve aspect ratio and center */
@@ -1439,12 +1568,17 @@ typedef struct IconDrawCall {
float color[4];
} IconDrawCall;
-static struct {
+typedef struct IconTextureDrawCall {
IconDrawCall drawcall_cache[ICON_DRAW_CACHE_SIZE];
int calls; /* Number of calls batched together */
+} IconTextureDrawCall;
+
+static struct {
+ IconTextureDrawCall normal;
+ IconTextureDrawCall border;
bool enabled;
float mat[4][4];
-} g_icon_draw_cache = {{{{0}}}};
+} g_icon_draw_cache = {{{{{0}}}}};
void UI_icon_draw_cache_begin(void)
{
@@ -1452,19 +1586,15 @@ void UI_icon_draw_cache_begin(void)
g_icon_draw_cache.enabled = true;
}
-static void icon_draw_cache_flush_ex(void)
+static void icon_draw_cache_texture_flush_ex(GLuint texture,
+ IconTextureDrawCall *texture_draw_calls)
{
- if (g_icon_draw_cache.calls == 0) {
+ if (texture_draw_calls->calls == 0) {
return;
}
- /* We need to flush widget base first to ensure correct ordering. */
- UI_widgetbase_draw_cache_flush();
-
- GPU_blend_set_func(GPU_ONE, GPU_ONE_MINUS_SRC_ALPHA);
-
glActiveTexture(GL_TEXTURE0);
- glBindTexture(GL_TEXTURE_2D, icongltex.id);
+ glBindTexture(GL_TEXTURE_2D, texture);
GPUShader *shader = GPU_shader_get_builtin_shader(GPU_SHADER_2D_IMAGE_MULTI_RECT_COLOR);
GPU_shader_bind(shader);
@@ -1473,16 +1603,43 @@ static void icon_draw_cache_flush_ex(void)
int data_loc = GPU_shader_get_uniform_ensure(shader, "calls_data[0]");
glUniform1i(img_loc, 0);
- glUniform4fv(data_loc, ICON_DRAW_CACHE_SIZE * 3, (float *)g_icon_draw_cache.drawcall_cache);
+ glUniform4fv(data_loc, ICON_DRAW_CACHE_SIZE * 3, (float *)texture_draw_calls->drawcall_cache);
- GPU_draw_primitive(GPU_PRIM_TRIS, 6 * g_icon_draw_cache.calls);
+ GPU_draw_primitive(GPU_PRIM_TRIS, 6 * texture_draw_calls->calls);
glBindTexture(GL_TEXTURE_2D, 0);
- g_icon_draw_cache.calls = 0;
+ texture_draw_calls->calls = 0;
+}
+
+static void icon_draw_cache_flush_ex(bool only_full_caches)
+{
+ bool should_draw = false;
+ if (only_full_caches) {
+ should_draw = g_icon_draw_cache.normal.calls == ICON_DRAW_CACHE_SIZE ||
+ g_icon_draw_cache.border.calls == ICON_DRAW_CACHE_SIZE;
+ }
+ else {
+ should_draw = g_icon_draw_cache.normal.calls || g_icon_draw_cache.border.calls;
+ }
- GPU_blend_set_func_separate(
- GPU_SRC_ALPHA, GPU_ONE_MINUS_SRC_ALPHA, GPU_ONE, GPU_ONE_MINUS_SRC_ALPHA);
+ if (should_draw) {
+ /* We need to flush widget base first to ensure correct ordering. */
+ UI_widgetbase_draw_cache_flush();
+
+ GPU_blend_set_func(GPU_ONE, GPU_ONE_MINUS_SRC_ALPHA);
+
+ if (!only_full_caches || g_icon_draw_cache.normal.calls == ICON_DRAW_CACHE_SIZE) {
+ icon_draw_cache_texture_flush_ex(icongltex.id[0], &g_icon_draw_cache.normal);
+ }
+
+ if (!only_full_caches || g_icon_draw_cache.border.calls == ICON_DRAW_CACHE_SIZE) {
+ icon_draw_cache_texture_flush_ex(icongltex.id[1], &g_icon_draw_cache.border);
+ }
+
+ GPU_blend_set_func_separate(
+ GPU_SRC_ALPHA, GPU_ONE_MINUS_SRC_ALPHA, GPU_ONE, GPU_ONE_MINUS_SRC_ALPHA);
+ }
}
void UI_icon_draw_cache_end(void)
@@ -1491,12 +1648,12 @@ void UI_icon_draw_cache_end(void)
g_icon_draw_cache.enabled = false;
/* Don't change blend state if it's not needed. */
- if (g_icon_draw_cache.calls == 0) {
+ if (g_icon_draw_cache.border.calls == 0 && g_icon_draw_cache.normal.calls == 0) {
return;
}
GPU_blend(true);
- icon_draw_cache_flush_ex();
+ icon_draw_cache_flush_ex(false);
GPU_blend(false);
}
@@ -1509,14 +1666,18 @@ static void icon_draw_texture_cached(float x,
int UNUSED(iw),
int ih,
float alpha,
- const float rgb[3])
+ const float rgb[3],
+ bool with_border)
{
float mvp[4][4];
GPU_matrix_model_view_projection_get(mvp);
- IconDrawCall *call = &g_icon_draw_cache.drawcall_cache[g_icon_draw_cache.calls];
- g_icon_draw_cache.calls++;
+ IconTextureDrawCall *texture_call = with_border ? &g_icon_draw_cache.border :
+ &g_icon_draw_cache.normal;
+
+ IconDrawCall *call = &texture_call->drawcall_cache[texture_call->calls];
+ texture_call->calls++;
/* Manual mat4*vec2 */
call->pos.xmin = x * mvp[0][0] + y * mvp[1][0] + mvp[3][0];
@@ -1536,8 +1697,8 @@ static void icon_draw_texture_cached(float x,
copy_v4_fl(call->color, alpha);
}
- if (g_icon_draw_cache.calls == ICON_DRAW_CACHE_SIZE) {
- icon_draw_cache_flush_ex();
+ if (texture_call->calls == ICON_DRAW_CACHE_SIZE) {
+ icon_draw_cache_flush_ex(true);
}
}
@@ -1550,10 +1711,11 @@ static void icon_draw_texture(float x,
int iw,
int ih,
float alpha,
- const float rgb[3])
+ const float rgb[3],
+ bool with_border)
{
if (g_icon_draw_cache.enabled) {
- icon_draw_texture_cached(x, y, w, h, ix, iy, iw, ih, alpha, rgb);
+ icon_draw_texture_cached(x, y, w, h, ix, iy, iw, ih, alpha, rgb, with_border);
return;
}
@@ -1570,7 +1732,7 @@ static void icon_draw_texture(float x,
y2 = (iy + ih) * icongltex.invh;
glActiveTexture(GL_TEXTURE0);
- glBindTexture(GL_TEXTURE_2D, icongltex.id);
+ glBindTexture(GL_TEXTURE_2D, with_border ? icongltex.id[1] : icongltex.id[0]);
GPUShader *shader = GPU_shader_get_builtin_shader(GPU_SHADER_2D_IMAGE_RECT_COLOR);
GPU_shader_bind(shader);
@@ -1614,11 +1776,11 @@ static void icon_draw_size(float x,
int icon_id,
float aspect,
float alpha,
- const float rgb[3],
enum eIconSizes size,
int draw_size,
const float desaturate,
- const char mono_rgba[4])
+ const char mono_rgba[4],
+ const bool mono_border)
{
bTheme *btheme = UI_GetTheme();
Icon *icon = NULL;
@@ -1675,7 +1837,7 @@ static void icon_draw_size(float x,
GPU_blend_set_func_separate(
GPU_ONE, GPU_ONE_MINUS_SRC_ALPHA, GPU_ONE, GPU_ONE_MINUS_SRC_ALPHA);
- icon_draw_rect(x, y, w, h, aspect, w, h, ibuf->rect, alpha, rgb, desaturate);
+ icon_draw_rect(x, y, w, h, aspect, w, h, ibuf->rect, alpha, desaturate);
GPU_blend_set_func_separate(
GPU_SRC_ALPHA, GPU_ONE_MINUS_SRC_ALPHA, GPU_ONE, GPU_ONE_MINUS_SRC_ALPHA);
}
@@ -1695,36 +1857,42 @@ static void icon_draw_size(float x,
di->data.texture.w,
di->data.texture.h,
alpha,
- rgb);
+ NULL,
+ false);
}
else if (di->type == ICON_TYPE_MONO_TEXTURE) {
- /* icon that matches text color, assumed to be white */
+ /* Monochrome icon that uses text or theme color. */
+ bool with_border = mono_border && (btheme->tui.icon_border_intensity > 0.0f);
float color[4];
- if (!UI_GetIconThemeColor4fv(di->data.texture.theme_color, color)) {
- if (mono_rgba) {
- rgba_uchar_to_float(color, (const uchar *)mono_rgba);
- }
- else {
- UI_GetThemeColor4fv(TH_TEXT, color);
- }
+ if (mono_rgba) {
+ rgba_uchar_to_float(color, (const uchar *)mono_rgba);
}
-
- if (rgb) {
- mul_v3_v3(color, rgb);
+ else {
+ UI_GetThemeColor4fv(TH_TEXT, color);
}
mul_v4_fl(color, alpha);
- icon_draw_texture(x,
- y,
- (float)w,
- (float)h,
- di->data.texture.x,
- di->data.texture.y,
- di->data.texture.w,
- di->data.texture.h,
+ float border_outset = 0.0;
+ unsigned int border_texel = 0;
+#ifndef WITH_HEADLESS
+ if (with_border) {
+ const float scale = (float)ICON_GRID_W / (float)ICON_DEFAULT_WIDTH;
+ border_texel = ICON_MONO_BORDER_OUTSET;
+ border_outset = ICON_MONO_BORDER_OUTSET / (scale * aspect);
+ }
+#endif
+ icon_draw_texture(x - border_outset,
+ y - border_outset,
+ (float)w + 2 * border_outset,
+ (float)h + 2 * border_outset,
+ di->data.texture.x - border_texel,
+ di->data.texture.y - border_texel,
+ di->data.texture.w + 2 * border_texel,
+ di->data.texture.h + 2 * border_texel,
color[3],
- color);
+ color,
+ with_border);
}
else if (di->type == ICON_TYPE_BUFFER) {
@@ -1738,7 +1906,7 @@ static void icon_draw_size(float x,
return;
}
- icon_draw_rect(x, y, w, h, aspect, iimg->w, iimg->h, iimg->rect, alpha, rgb, desaturate);
+ icon_draw_rect(x, y, w, h, aspect, iimg->w, iimg->h, iimg->rect, alpha, desaturate);
}
else if (di->type == ICON_TYPE_PREVIEW) {
PreviewImage *pi = (icon->id_type != 0) ? BKE_previewimg_id_ensure((ID *)icon->obj) :
@@ -1755,7 +1923,7 @@ static void icon_draw_size(float x,
GPU_blend_set_func_separate(
GPU_ONE, GPU_ONE_MINUS_SRC_ALPHA, GPU_ONE, GPU_ONE_MINUS_SRC_ALPHA);
icon_draw_rect(
- x, y, w, h, aspect, pi->w[size], pi->h[size], pi->rect[size], alpha, rgb, desaturate);
+ x, y, w, h, aspect, pi->w[size], pi->h[size], pi->rect[size], alpha, desaturate);
GPU_blend_set_func_separate(
GPU_SRC_ALPHA, GPU_ONE_MINUS_SRC_ALPHA, GPU_ONE, GPU_ONE_MINUS_SRC_ALPHA);
}
@@ -2057,7 +2225,7 @@ int UI_idcode_icon_get(const int idcode)
case ID_PC:
return ICON_CURVE_BEZCURVE; /* TODO! this would need its own icon! */
case ID_LP:
- return ICON_LIGHTPROBE_CUBEMAP;
+ return ICON_OUTLINER_DATA_LIGHTPROBE;
case ID_SCE:
return ICON_SCENE_DATA;
case ID_SPK:
@@ -2077,71 +2245,40 @@ int UI_idcode_icon_get(const int idcode)
}
}
-static void icon_draw_at_size(float x,
- float y,
- int icon_id,
- float aspect,
- float alpha,
- enum eIconSizes size,
- const float desaturate,
- const char mono_color[4])
-{
- int draw_size = get_draw_size(size);
- icon_draw_size(x, y, icon_id, aspect, alpha, NULL, size, draw_size, desaturate, mono_color);
-}
-
-void UI_icon_draw_aspect(
- float x, float y, int icon_id, float aspect, float alpha, const char mono_color[4])
-{
- icon_draw_at_size(x, y, icon_id, aspect, alpha, ICON_SIZE_ICON, 0.0f, mono_color);
-}
-
-void UI_icon_draw_aspect_color(
- float x, float y, int icon_id, float aspect, const float rgb[3], const char mono_color[4])
-{
- int draw_size = get_draw_size(ICON_SIZE_ICON);
- icon_draw_size(x, y, icon_id, aspect, 1.0f, rgb, ICON_SIZE_ICON, draw_size, false, mono_color);
-}
-
-void UI_icon_draw_desaturate(float x,
- float y,
- int icon_id,
- float aspect,
- float alpha,
- float desaturate,
- const char mono_color[4])
-{
- icon_draw_at_size(x, y, icon_id, aspect, alpha, ICON_SIZE_ICON, desaturate, mono_color);
-}
-
/* draws icon with dpi scale factor */
void UI_icon_draw(float x, float y, int icon_id)
{
- UI_icon_draw_aspect(x, y, icon_id, 1.0f / UI_DPI_FAC, 1.0f, NULL);
+ UI_icon_draw_ex(x, y, icon_id, U.inv_dpi_fac, 1.0f, 0.0f, NULL, false);
}
void UI_icon_draw_alpha(float x, float y, int icon_id, float alpha)
{
- UI_icon_draw_aspect(x, y, icon_id, 1.0f / UI_DPI_FAC, alpha, NULL);
+ UI_icon_draw_ex(x, y, icon_id, U.inv_dpi_fac, alpha, 0.0f, NULL, false);
}
-void UI_icon_draw_size(float x, float y, int size, int icon_id, float alpha)
+void UI_icon_draw_preview(float x, float y, int icon_id, float aspect, float alpha, int size)
{
- icon_draw_size(x, y, icon_id, 1.0f, alpha, NULL, ICON_SIZE_ICON, size, false, NULL);
+ icon_draw_size(x, y, icon_id, aspect, alpha, ICON_SIZE_PREVIEW, size, false, NULL, false);
}
-void UI_icon_draw_preview(float x, float y, int icon_id)
+void UI_icon_draw_ex(float x,
+ float y,
+ int icon_id,
+ float aspect,
+ float alpha,
+ float desaturate,
+ const char mono_color[4],
+ const bool mono_border)
{
- icon_draw_at_size(x, y, icon_id, 1.0f, 1.0f, ICON_SIZE_PREVIEW, false, NULL);
-}
-
-void UI_icon_draw_preview_aspect(float x, float y, int icon_id, float aspect)
-{
- icon_draw_at_size(x, y, icon_id, aspect, 1.0f, ICON_SIZE_PREVIEW, false, NULL);
-}
-
-void UI_icon_draw_preview_aspect_size(
- float x, float y, int icon_id, float aspect, float alpha, int size)
-{
- icon_draw_size(x, y, icon_id, aspect, alpha, NULL, ICON_SIZE_PREVIEW, size, false, NULL);
+ int draw_size = get_draw_size(ICON_SIZE_ICON);
+ icon_draw_size(x,
+ y,
+ icon_id,
+ aspect,
+ alpha,
+ ICON_SIZE_ICON,
+ draw_size,
+ desaturate,
+ mono_color,
+ mono_border);
}
diff --git a/source/blender/editors/interface/interface_intern.h b/source/blender/editors/interface/interface_intern.h
index 4af7fdd779f..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);
@@ -539,13 +540,12 @@ struct uiKeyNavLock {
typedef uiBlock *(*uiBlockHandleCreateFunc)(struct bContext *C,
struct uiPopupBlockHandle *handle,
void *arg1);
-typedef void (*uiBlockHandleFreeFunc)(struct uiPopupBlockHandle *handle, void *arg1);
struct uiPopupBlockCreate {
uiBlockCreateFunc create_func;
uiBlockHandleCreateFunc handle_create_func;
- uiBlockHandleFreeFunc free_func;
void *arg;
+ void (*arg_free)(void *arg);
int event_xy[2];
@@ -662,7 +662,8 @@ uiPopupBlockHandle *ui_popup_block_create(struct bContext *C,
uiBut *but,
uiBlockCreateFunc create_func,
uiBlockHandleCreateFunc handle_create_func,
- void *arg);
+ void *arg,
+ void (*arg_free)(void *arg));
uiPopupBlockHandle *ui_popup_menu_create(struct bContext *C,
struct ARegion *butregion,
uiBut *but,
diff --git a/source/blender/editors/interface/interface_layout.c b/source/blender/editors/interface/interface_layout.c
index 41001ff6d14..a3906879fd7 100644
--- a/source/blender/editors/interface/interface_layout.c
+++ b/source/blender/editors/interface/interface_layout.c
@@ -304,10 +304,14 @@ static int ui_text_icon_width(uiLayout *layout, const char *name, int icon, bool
layout->item.flag |= UI_ITEM_MIN;
}
const uiFontStyle *fstyle = UI_FSTYLE_WIDGET;
- /* it may seem odd that the icon only adds (unit_x / 4)
- * but taking margins into account its fine */
- return (UI_fontstyle_string_width(fstyle, name) +
- (unit_x * ((compact ? 1.25f : 1.50f) + (icon ? 0.25f : 0.0f))));
+ float margin = compact ? 1.25 : 1.50;
+ if (icon) {
+ /* It may seem odd that the icon only adds (unit_x / 4)
+ * but taking margins into account its fine, except
+ * in compact mode a bit more margin is required. */
+ margin += compact ? 0.35 : 0.25;
+ }
+ return UI_fontstyle_string_width(fstyle, name) + (unit_x * margin);
}
else {
return unit_x * 10;
@@ -480,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)
@@ -687,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)) {
@@ -760,7 +764,8 @@ static void ui_item_enum_expand_elem_exec(uiLayout *layout,
if (RNA_property_flag(prop) & PROP_ENUM_FLAG) {
/* If this is set, assert since we're clobbering someone elses callback. */
- BLI_assert(but->func == NULL);
+ /* Buttons get their block's func by default, so we cannot assert in that case either. */
+ BLI_assert(ELEM(but->func, NULL, block->func));
UI_but_func_set(but, ui_item_enum_expand_handle, but, POINTER_FROM_INT(value));
}
@@ -1450,7 +1455,6 @@ void uiItemsFullEnumO_items(uiLayout *layout,
if (properties) {
if (tptr.data) {
IDP_FreeProperty(tptr.data);
- MEM_freeN(tptr.data);
}
tptr.data = IDP_CopyProperty(properties);
}
@@ -1854,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.
@@ -1884,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) {
@@ -1900,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) {
@@ -1928,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;
@@ -1985,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) {
@@ -2152,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;
}
@@ -2171,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)) {
diff --git a/source/blender/editors/interface/interface_panel.c b/source/blender/editors/interface/interface_panel.c
index 87e58a4b3b5..9c5ce0c9d2c 100644
--- a/source/blender/editors/interface/interface_panel.c
+++ b/source/blender/editors/interface/interface_panel.c
@@ -258,43 +258,16 @@ static void panels_collapse_all(ScrArea *sa, ARegion *ar, const Panel *from_pa)
}
}
-static void ui_panel_copy_offset(Panel *pa, Panel *papar)
-{
- /* with respect to sizes... papar is parent */
-
- pa->ofsx = papar->ofsx;
- pa->ofsy = papar->ofsy + papar->sizey - pa->sizey;
-}
-
-/**
- * XXX Disabled paneltab handling for now. Old 2.4x feature,
- * *DO NOT* confuse it with new tool tabs in 2.70. ;)
- * See also T41704.
- */
-/* #define UI_USE_PANELTAB */
-
Panel *UI_panel_find_by_type(ListBase *lb, PanelType *pt)
{
Panel *pa;
const char *idname = pt->idname;
-#ifdef UI_USE_PANELTAB
- const char *tabname = pt->idname;
- for (pa = lb->first; pa; pa = pa->next) {
- if (STREQLEN(pa->panelname, idname, sizeof(pa->panelname))) {
- if (STREQLEN(pa->tabname, tabname, sizeof(pa->tabname))) {
- return pa;
- }
- }
- }
-#else
for (pa = lb->first; pa; pa = pa->next) {
if (STREQLEN(pa->panelname, idname, sizeof(pa->panelname))) {
return pa;
}
}
-#endif
-
return NULL;
}
@@ -307,10 +280,6 @@ Panel *UI_panel_begin(
Panel *palast, *panext;
const char *drawname = CTX_IFACE_(pt->translation_context, pt->label);
const char *idname = pt->idname;
-#ifdef UI_USE_PANELTAB
- const char *tabname = pt->idname;
- const char *hookname = NULL;
-#endif
const bool newpanel = (pa == NULL);
int align = panel_aligned(sa, ar);
@@ -341,28 +310,6 @@ Panel *UI_panel_begin(
pa->runtime_flag |= PNL_NEW_ADDED;
BLI_addtail(lb, pa);
-
-#ifdef UI_USE_PANELTAB
- BLI_strncpy(pa->tabname, tabname, sizeof(pa->tabname));
-
- /* make new Panel tabbed? */
- if (hookname) {
- Panel *patab;
- for (patab = lb->first; patab; patab = patab->next) {
- if ((patab->runtime_flag & PNL_ACTIVE) && patab->paneltab == NULL) {
- if (STREQLEN(hookname, patab->panelname, sizeof(patab->panelname))) {
- if (STREQLEN(tabname, patab->tabname, sizeof(patab->tabname))) {
- pa->paneltab = patab;
- ui_panel_copy_offset(pa, patab);
- break;
- }
- }
- }
- }
- }
-#else
- BLI_strncpy(pa->tabname, idname, sizeof(pa->tabname));
-#endif
}
/* Do not allow closed panels without headers! Else user could get "disappeared" UI! */
@@ -411,9 +358,6 @@ Panel *UI_panel_begin(
*r_open = false;
- if (pa->paneltab) {
- return pa;
- }
if (pa->flag & PNL_CLOSED) {
return pa;
}
@@ -423,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;
@@ -446,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;
+ }
}
}
@@ -705,11 +649,17 @@ void ui_draw_aligned_panel(uiStyle *style,
/* FIXME(campbell): currently no background means floating panel which
* can't be dragged. This may be changed in future. */
show_background);
+ const int panel_col = is_subpanel ? TH_PANEL_SUB_BACK : TH_PANEL_BACK;
- if (panel->paneltab) {
- return;
- }
if (panel->type && (panel->type->flag & PNL_NO_HEADER)) {
+ if (show_background) {
+ uint pos = GPU_vertformat_attr_add(
+ immVertexFormat(), "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
+ immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
+ immUniformThemeColor(panel_col);
+ immRectf(pos, rect->xmin, rect->ymin, rect->xmax, rect->ymax);
+ immUnbindProgram();
+ }
return;
}
@@ -765,12 +715,14 @@ void ui_draw_aligned_panel(uiStyle *style,
panel_title_color_get(show_background, col_title);
GPU_blend(true);
- UI_icon_draw_aspect(headrect.xmax - ((PNL_ICON * 2.2f) / block->aspect),
- headrect.ymin + (5.0f / block->aspect),
- (panel->flag & PNL_PIN) ? ICON_PINNED : ICON_UNPINNED,
- (block->aspect / UI_DPI_FAC),
- 1.0f,
- (const char *)col_title);
+ UI_icon_draw_ex(headrect.xmax - ((PNL_ICON * 2.2f) / block->aspect),
+ headrect.ymin + (5.0f / block->aspect),
+ (panel->flag & PNL_PIN) ? ICON_PINNED : ICON_UNPINNED,
+ (block->aspect * U.inv_dpi_fac),
+ 1.0f,
+ 0.0f,
+ (const char *)col_title,
+ false);
GPU_blend(false);
}
@@ -838,8 +790,6 @@ void ui_draw_aligned_panel(uiStyle *style,
if (show_background) {
/* panel backdrop */
- int panel_col = is_subpanel ? TH_PANEL_SUB_BACK : TH_PANEL_BACK;
-
immUniformThemeColor(panel_col);
immRectf(pos, rect->xmin, rect->ymin, rect->xmax, rect->ymax);
}
@@ -934,12 +884,6 @@ static int get_panel_real_ofsy(Panel *pa)
if (pa->flag & PNL_CLOSEDY) {
return pa->ofsy + pa->sizey;
}
- else if (pa->paneltab && (pa->paneltab->flag & PNL_CLOSEDY)) {
- return pa->ofsy + pa->sizey;
- }
- else if (pa->paneltab) {
- return pa->paneltab->ofsy;
- }
else {
return pa->ofsy;
}
@@ -950,9 +894,6 @@ static int get_panel_real_ofsx(Panel *pa)
if (pa->flag & PNL_CLOSEDX) {
return pa->ofsx + get_panel_header(pa);
}
- else if (pa->paneltab && (pa->paneltab->flag & PNL_CLOSEDX)) {
- return pa->ofsx + get_panel_header(pa);
- }
else {
return pa->ofsx + pa->sizex;
}
@@ -1067,7 +1008,7 @@ static bool uiAlignPanelStep(ScrArea *sa, ARegion *ar, const float fac, const bo
/* count active, not tabbed panels */
for (pa = ar->panels.first; pa; pa = pa->next) {
- if ((pa->runtime_flag & PNL_ACTIVE) && pa->paneltab == NULL) {
+ if (pa->runtime_flag & PNL_ACTIVE) {
tot++;
}
}
@@ -1078,7 +1019,7 @@ static bool uiAlignPanelStep(ScrArea *sa, ARegion *ar, const float fac, const bo
/* extra; change close direction? */
for (pa = ar->panels.first; pa; pa = pa->next) {
- if ((pa->runtime_flag & PNL_ACTIVE) && pa->paneltab == NULL) {
+ if (pa->runtime_flag & PNL_ACTIVE) {
if ((pa->flag & PNL_CLOSEDX) && (align == BUT_VERTICAL)) {
pa->flag ^= PNL_CLOSED;
}
@@ -1093,7 +1034,7 @@ static bool uiAlignPanelStep(ScrArea *sa, ARegion *ar, const float fac, const bo
ps = panelsort;
for (pa = ar->panels.first; pa; pa = pa->next) {
- if ((pa->runtime_flag & PNL_ACTIVE) && pa->paneltab == NULL) {
+ if (pa->runtime_flag & PNL_ACTIVE) {
ps->pa = MEM_dupallocN(pa);
ps->orig = pa;
ps++;
@@ -1160,9 +1101,6 @@ static bool uiAlignPanelStep(ScrArea *sa, ARegion *ar, const float fac, const bo
/* set locations for tabbed and sub panels */
for (pa = ar->panels.first; pa; pa = pa->next) {
if (pa->runtime_flag & PNL_ACTIVE) {
- if (pa->paneltab) {
- ui_panel_copy_offset(pa, pa->paneltab);
- }
if (pa->children.first) {
align_sub_panels(pa);
}
@@ -1265,7 +1203,7 @@ void UI_panels_end(const bContext *C, ARegion *ar, int *r_x, int *r_y)
{
ScrArea *sa = CTX_wm_area(C);
uiBlock *block;
- Panel *panot, *panew, *patest, *pa, *firstpa;
+ Panel *pa, *firstpa;
/* offset contents */
for (block = ar->uiblocks.first; block; block = block->next) {
@@ -1274,31 +1212,6 @@ void UI_panels_end(const bContext *C, ARegion *ar, int *r_x, int *r_y)
}
}
- /* consistency; are panels not made, whilst they have tabs */
- for (panot = ar->panels.first; panot; panot = panot->next) {
- if ((panot->runtime_flag & PNL_ACTIVE) == 0) { /* not made */
-
- for (panew = ar->panels.first; panew; panew = panew->next) {
- if ((panew->runtime_flag & PNL_ACTIVE)) {
- if (panew->paneltab == panot) { /* panew is tab in notmade pa */
- break;
- }
- }
- }
- /* now panew can become the new parent, check all other tabs */
- if (panew) {
- for (patest = ar->panels.first; patest; patest = patest->next) {
- if (patest->paneltab == panot) {
- patest->paneltab = panew;
- }
- }
- panot->paneltab = panew;
- panew->paneltab = NULL;
- ED_region_tag_redraw(ar); /* the buttons panew were not made */
- }
- }
- }
-
/* re-align, possibly with animation */
if (panels_need_realign(sa, ar, &pa)) {
if (pa) {
@@ -1380,7 +1293,7 @@ static void check_panel_overlap(ARegion *ar, Panel *panel)
for (pa = ar->panels.first; pa; pa = pa->next) {
pa->flag &= ~PNL_OVERLAP;
if (panel && (pa != panel)) {
- if (pa->paneltab == NULL && (pa->runtime_flag & PNL_ACTIVE)) {
+ if (pa->runtime_flag & PNL_ACTIVE) {
float safex = 0.2, safey = 0.2;
if (pa->flag & PNL_CLOSEDX) {
@@ -1623,11 +1536,11 @@ static void ui_handle_panel_header(
{
ScrArea *sa = CTX_wm_area(C);
ARegion *ar = CTX_wm_region(C);
- Panel *pa;
#ifdef USE_PIN_HIDDEN
- const bool show_pin = UI_panel_category_is_visible(ar) && (block->panel->flag & PNL_PIN);
+ const bool show_pin = UI_panel_category_is_visible(ar) && (block->panel->type->parent == NULL) &&
+ (block->panel->flag & PNL_PIN);
#else
- const bool show_pin = UI_panel_category_is_visible(ar);
+ const bool show_pin = UI_panel_category_is_visible(ar) && (block->panel->type->parent == NULL);
#endif
const bool is_subpanel = (block->panel->type && block->panel->type->parent);
const bool show_drag = !is_subpanel;
@@ -1658,8 +1571,10 @@ static void ui_handle_panel_header(
button = 1;
}
else if (ELEM(event, 0, RETKEY, LEFTMOUSE) && shift) {
- block->panel->flag ^= PNL_PIN;
- button = 2;
+ if (block->panel->type->parent == NULL) {
+ block->panel->flag ^= PNL_PIN;
+ button = 2;
+ }
}
else if (block->panel->flag & PNL_CLOSEDX) {
if (my >= block->rect.ymax) {
@@ -1720,17 +1635,6 @@ static void ui_handle_panel_header(
ui_panel_drag_collapse_handler_add(C, true);
}
}
-
- for (pa = ar->panels.first; pa; pa = pa->next) {
- if (pa->paneltab == block->panel) {
- if (block->panel->flag & PNL_CLOSED) {
- pa->flag |= PNL_CLOSED;
- }
- else {
- pa->flag &= ~PNL_CLOSED;
- }
- }
- }
}
if (align) {
@@ -1772,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);
@@ -1806,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.
@@ -1825,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;
@@ -2067,7 +1989,11 @@ void UI_panel_category_draw_all(ARegion *ar, const char *category_id_active)
ui_fontscale(&fstyle_points, aspect / (U.pixelsize * 1.1f));
BLF_size(fontid, fstyle_points, U.dpi);
- BLI_assert(UI_panel_category_is_visible(ar));
+ /* Check the region type supports categories to avoid an assert
+ * for showing 3D view panels in the properties space. */
+ if ((1 << ar->regiontype) & RGN_TYPE_HAS_CATEGORY_MASK) {
+ BLI_assert(UI_panel_category_is_visible(ar));
+ }
/* calculate tab rect's and check if we need to scale down */
for (pc_dyn = ar->panels_category.first; pc_dyn; pc_dyn = pc_dyn->next) {
@@ -2378,7 +2304,7 @@ int ui_handler_panel_region(bContext *C,
/* checks for mouse position inside */
pa = block->panel;
- if (!pa || pa->paneltab != NULL) {
+ if (!pa) {
continue;
}
/* XXX - accessed freed panels when scripts reload, need to fix. */
diff --git a/source/blender/editors/interface/interface_region_menu_pie.c b/source/blender/editors/interface/interface_region_menu_pie.c
index dcbbde259f2..330a9d48ff4 100644
--- a/source/blender/editors/interface/interface_region_menu_pie.c
+++ b/source/blender/editors/interface/interface_region_menu_pie.c
@@ -208,7 +208,7 @@ void UI_pie_menu_end(bContext *C, uiPieMenu *pie)
wmWindow *window = CTX_wm_window(C);
uiPopupBlockHandle *menu;
- menu = ui_popup_block_create(C, NULL, NULL, NULL, ui_block_func_PIE, pie);
+ menu = ui_popup_block_create(C, NULL, NULL, NULL, ui_block_func_PIE, pie, NULL);
menu->popup = true;
menu->towardstime = PIL_check_seconds_timer();
diff --git a/source/blender/editors/interface/interface_region_menu_popup.c b/source/blender/editors/interface/interface_region_menu_popup.c
index b97cbcdfef5..ab3a86ec9e1 100644
--- a/source/blender/editors/interface/interface_region_menu_popup.c
+++ b/source/blender/editors/interface/interface_region_menu_popup.c
@@ -351,7 +351,7 @@ uiPopupBlockHandle *ui_popup_menu_create(
pup->menu_func = menu_func;
pup->menu_arg = arg;
- handle = ui_popup_block_create(C, butregion, but, NULL, ui_block_func_POPUP, pup);
+ handle = ui_popup_block_create(C, butregion, but, NULL, ui_block_func_POPUP, pup, NULL);
if (!but) {
handle->popup = true;
@@ -463,7 +463,7 @@ void UI_popup_menu_end(bContext *C, uiPopupMenu *pup)
butregion = pup->butregion;
}
- menu = ui_popup_block_create(C, butregion, but, NULL, ui_block_func_POPUP, pup);
+ menu = ui_popup_block_create(C, butregion, but, NULL, ui_block_func_POPUP, pup, NULL);
menu->popup = true;
UI_popup_handlers_add(C, &window->modalhandlers, menu, 0);
@@ -581,13 +581,17 @@ int UI_popup_menu_invoke(bContext *C, const char *idname, ReportList *reports)
/** \name Popup Block API
* \{ */
-void UI_popup_block_invoke_ex(
- bContext *C, uiBlockCreateFunc func, void *arg, const char *opname, int opcontext)
+void UI_popup_block_invoke_ex(bContext *C,
+ uiBlockCreateFunc func,
+ void *arg,
+ void (*arg_free)(void *arg),
+ const char *opname,
+ int opcontext)
{
wmWindow *window = CTX_wm_window(C);
uiPopupBlockHandle *handle;
- handle = ui_popup_block_create(C, NULL, NULL, func, NULL, arg);
+ handle = ui_popup_block_create(C, NULL, NULL, func, NULL, arg, arg_free);
handle->popup = true;
handle->can_refresh = true;
handle->optype = (opname) ? WM_operatortype_find(opname, 0) : NULL;
@@ -598,9 +602,12 @@ void UI_popup_block_invoke_ex(
WM_event_add_mousemove(C);
}
-void UI_popup_block_invoke(bContext *C, uiBlockCreateFunc func, void *arg)
+void UI_popup_block_invoke(bContext *C,
+ uiBlockCreateFunc func,
+ void *arg,
+ void (*arg_free)(void *arg))
{
- UI_popup_block_invoke_ex(C, func, arg, NULL, WM_OP_INVOKE_DEFAULT);
+ UI_popup_block_invoke_ex(C, func, arg, arg_free, NULL, WM_OP_INVOKE_DEFAULT);
}
void UI_popup_block_ex(bContext *C,
@@ -613,7 +620,7 @@ void UI_popup_block_ex(bContext *C,
wmWindow *window = CTX_wm_window(C);
uiPopupBlockHandle *handle;
- handle = ui_popup_block_create(C, NULL, NULL, func, NULL, arg);
+ handle = ui_popup_block_create(C, NULL, NULL, func, NULL, arg, NULL);
handle->popup = true;
handle->retvalue = 1;
handle->can_refresh = true;
@@ -635,7 +642,7 @@ void uiPupBlockOperator(bContext *C, uiBlockCreateFunc func, wmOperator *op, int
wmWindow *window = CTX_wm_window(C);
uiPopupBlockHandle *handle;
- handle = ui_popup_block_create(C, NULL, NULL, func, NULL, op);
+ handle = ui_popup_block_create(C, NULL, NULL, func, NULL, op, NULL);
handle->popup = 1;
handle->retvalue = 1;
handle->can_refresh = true;
diff --git a/source/blender/editors/interface/interface_region_popover.c b/source/blender/editors/interface/interface_region_popover.c
index f149ccd626c..22c62ecd6f7 100644
--- a/source/blender/editors/interface/interface_region_popover.c
+++ b/source/blender/editors/interface/interface_region_popover.c
@@ -244,7 +244,7 @@ static uiBlock *ui_block_func_POPOVER(bContext *C, uiPopupBlockHandle *handle, v
return block;
}
-static void ui_block_free_func_POPOVER(uiPopupBlockHandle *UNUSED(handle), void *arg_pup)
+static void ui_block_free_func_POPOVER(void *arg_pup)
{
uiPopover *pup = arg_pup;
if (pup->keymap != NULL) {
@@ -282,8 +282,8 @@ uiPopupBlockHandle *ui_popover_panel_create(
/* Create popup block. */
uiPopupBlockHandle *handle;
- handle = ui_popup_block_create(C, butregion, but, NULL, ui_block_func_POPOVER, pup);
- handle->popup_create_vars.free_func = ui_block_free_func_POPOVER;
+ handle = ui_popup_block_create(
+ C, butregion, but, NULL, ui_block_func_POPOVER, pup, ui_block_free_func_POPOVER);
handle->can_refresh = true;
/* Add handlers. If attached to a button, the button will already
@@ -386,8 +386,8 @@ void UI_popover_end(bContext *C, uiPopover *pup, wmKeyMap *keymap)
WM_event_set_keymap_handler_post_callback(pup->keymap_handler, popover_keymap_fn, pup);
}
- handle = ui_popup_block_create(C, NULL, NULL, NULL, ui_block_func_POPOVER, pup);
- handle->popup_create_vars.free_func = ui_block_free_func_POPOVER;
+ handle = ui_popup_block_create(
+ C, NULL, NULL, NULL, ui_block_func_POPOVER, pup, ui_block_free_func_POPOVER);
/* Add handlers. */
UI_popup_handlers_add(C, &window->modalhandlers, handle, 0);
diff --git a/source/blender/editors/interface/interface_region_popup.c b/source/blender/editors/interface/interface_region_popup.c
index c4bcd7074d8..bd87439ca9e 100644
--- a/source/blender/editors/interface/interface_region_popup.c
+++ b/source/blender/editors/interface/interface_region_popup.c
@@ -748,7 +748,8 @@ uiPopupBlockHandle *ui_popup_block_create(bContext *C,
uiBut *but,
uiBlockCreateFunc create_func,
uiBlockHandleCreateFunc handle_create_func,
- void *arg)
+ void *arg,
+ void (*arg_free)(void *arg))
{
wmWindow *window = CTX_wm_window(C);
uiBut *activebut = UI_context_active_but_get(C);
@@ -775,6 +776,7 @@ uiPopupBlockHandle *ui_popup_block_create(bContext *C,
handle->popup_create_vars.create_func = create_func;
handle->popup_create_vars.handle_create_func = handle_create_func;
handle->popup_create_vars.arg = arg;
+ handle->popup_create_vars.arg_free = arg_free;
handle->popup_create_vars.but = but;
handle->popup_create_vars.butregion = but ? butregion : NULL;
copy_v2_v2_int(handle->popup_create_vars.event_xy, &window->eventstate->x);
@@ -820,8 +822,8 @@ void ui_popup_block_free(bContext *C, uiPopupBlockHandle *handle)
}
}
- if (handle->popup_create_vars.free_func) {
- handle->popup_create_vars.free_func(handle, handle->popup_create_vars.arg);
+ if (handle->popup_create_vars.arg_free) {
+ handle->popup_create_vars.arg_free(handle->popup_create_vars.arg);
}
ui_popup_block_remove(C, handle);
diff --git a/source/blender/editors/interface/interface_region_tooltip.c b/source/blender/editors/interface/interface_region_tooltip.c
index 4a9c7b689c1..5b205de21b8 100644
--- a/source/blender/editors/interface/interface_region_tooltip.c
+++ b/source/blender/editors/interface/interface_region_tooltip.c
@@ -891,11 +891,11 @@ static uiTooltipData *ui_tooltip_data_from_gizmo(bContext *C, wmGizmo *gz)
} gzop_actions[] = {
{
.part = gz->highlight_part,
- .prefix = use_drag ? TIP_("Click") : NULL,
+ .prefix = use_drag ? CTX_TIP_(BLT_I18NCONTEXT_OPERATOR_DEFAULT, "Click") : NULL,
},
{
.part = use_drag ? gz->drag_part : -1,
- .prefix = use_drag ? TIP_("Drag") : NULL,
+ .prefix = use_drag ? CTX_TIP_(BLT_I18NCONTEXT_OPERATOR_DEFAULT, "Drag") : NULL,
},
};
diff --git a/source/blender/editors/interface/interface_templates.c b/source/blender/editors/interface/interface_templates.c
index e96141eaa05..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(&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(&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(&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(&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(&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);
}
@@ -4042,6 +4042,11 @@ static uiBlock *curvemap_brush_tools_func(bContext *C, ARegion *ar, void *cumap_
return curvemap_tools_func(C, ar, cumap_v, false, UICURVE_FUNC_RESET_NEG);
}
+static uiBlock *curvemap_brush_tools_negslope_func(bContext *C, ARegion *ar, void *cumap_v)
+{
+ return curvemap_tools_func(C, ar, cumap_v, false, UICURVE_FUNC_RESET_POS);
+}
+
static void curvemap_buttons_redraw(bContext *C, void *UNUSED(arg1), void *UNUSED(arg2))
{
ED_region_tag_redraw(CTX_wm_region(C));
@@ -4217,7 +4222,19 @@ static void curvemap_buttons_layout(uiLayout *layout,
TIP_("Zoom out"));
UI_but_func_set(bt, curvemap_buttons_zoom_out, cumap, NULL);
- if (brush) {
+ if (brush && neg_slope) {
+ bt = uiDefIconBlockBut(block,
+ curvemap_brush_tools_negslope_func,
+ cumap,
+ 0,
+ ICON_DOWNARROW_HLT,
+ 0,
+ 0,
+ dx,
+ dx,
+ TIP_("Tools"));
+ }
+ else if (brush) {
bt = uiDefIconBlockBut(block,
curvemap_brush_tools_func,
cumap,
@@ -6744,12 +6761,17 @@ int uiTemplateRecentFiles(uiLayout *layout, int rows)
for (recent = G.recent_files.first, i = 0; (i < rows) && (recent); recent = recent->next, i++) {
const char *filename = BLI_path_basename(recent->filepath);
- uiItemStringO(layout,
- filename,
- BLO_has_bfile_extension(filename) ? ICON_FILE_BLEND : ICON_FILE_BACKUP,
- "WM_OT_open_mainfile",
- "filepath",
- recent->filepath);
+ PointerRNA ptr;
+ uiItemFullO(layout,
+ "WM_OT_open_mainfile",
+ filename,
+ BLO_has_bfile_extension(filename) ? ICON_FILE_BLEND : ICON_FILE_BACKUP,
+ NULL,
+ WM_OP_INVOKE_DEFAULT,
+ 0,
+ &ptr);
+ RNA_string_set(&ptr, "filepath", recent->filepath);
+ RNA_boolean_set(&ptr, "display_file_selector", false);
}
return i;
diff --git a/source/blender/editors/interface/interface_widgets.c b/source/blender/editors/interface/interface_widgets.c
index a9cd2f9cee1..e31646f9fdb 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;
@@ -1421,7 +1423,7 @@ static void widget_draw_preview(BIFIconID icon, float alpha, const rcti *rect)
int x = rect->xmin + w / 2 - size / 2;
int y = rect->ymin + h / 2 - size / 2;
- UI_icon_draw_preview_aspect_size(x, y, icon, 1.0f, alpha, size);
+ UI_icon_draw_preview(x, y, icon, 1.0f, alpha, size);
}
}
@@ -1450,7 +1452,7 @@ static void widget_draw_icon(
return;
}
- aspect = but->block->aspect / UI_DPI_FAC;
+ aspect = but->block->aspect * U.inv_dpi_fac;
height = ICON_DEFAULT_HEIGHT / aspect;
/* calculate blend color */
@@ -1506,18 +1508,27 @@ static void widget_draw_icon(
ys = (int)(ys + 0.1f);
}
+ /* Get theme color. */
+ char color[4] = {mono_color[0], mono_color[1], mono_color[2], mono_color[3]};
+ bool has_theme = UI_icon_get_theme_color(icon, (uchar *)color);
+
/* to indicate draggable */
if (but->dragpoin && (but->flag & UI_ACTIVE)) {
- float rgb[3] = {1.25f, 1.25f, 1.25f};
- UI_icon_draw_aspect_color(xs, ys, icon, aspect, rgb, mono_color);
+ UI_icon_draw_ex(xs, ys, icon, aspect, 1.25f, 0.0f, color, has_theme);
}
- else if ((but->flag & (UI_ACTIVE | UI_SELECT | UI_SELECT_DRAW)) || !UI_but_is_tool(but)) {
- UI_icon_draw_aspect(xs, ys, icon, aspect, alpha, mono_color);
+ else if ((but->flag & (UI_ACTIVE | UI_SELECT | UI_SELECT_DRAW))) {
+ UI_icon_draw_ex(xs, ys, icon, aspect, alpha, 0.0f, color, has_theme);
+ }
+ else if (!UI_but_is_tool(but)) {
+ if (has_theme) {
+ alpha *= 0.8f;
+ }
+ UI_icon_draw_ex(xs, ys, icon, aspect, alpha, 0.0f, color, has_theme);
}
else {
const bTheme *btheme = UI_GetTheme();
- UI_icon_draw_desaturate(
- xs, ys, icon, aspect, alpha, 1.0 - btheme->tui.icon_saturation, mono_color);
+ const float desaturate = 1.0 - btheme->tui.icon_saturation;
+ UI_icon_draw_ex(xs, ys, icon, aspect, alpha, desaturate, color, has_theme);
}
}
@@ -1528,7 +1539,7 @@ static void widget_draw_submenu_tria(const uiBut *but,
const rcti *rect,
const uiWidgetColors *wcol)
{
- const float aspect = but->block->aspect / UI_DPI_FAC;
+ const float aspect = but->block->aspect * U.inv_dpi_fac;
const int tria_height = (int)(ICON_DEFAULT_HEIGHT / aspect);
const int tria_width = (int)(ICON_DEFAULT_WIDTH / aspect) - 2 * U.pixelsize;
const int xs = rect->xmax - tria_width;
@@ -1584,7 +1595,8 @@ static void ui_text_clip_right_ex(const uiFontStyle *fstyle,
BLI_assert(str[0]);
/* If the trailing ellipsis takes more than 20% of all available width, just cut the string
- * (as using the ellipsis would remove even more useful chars, and we cannot show much already!).
+ * (as using the ellipsis would remove even more useful chars, and we cannot show much
+ * already!).
*/
if (sep_strwidth / okwidth > 0.2f) {
l_end = BLF_width_to_strlen(fstyle->uifont_id, str, max_len, okwidth, &tmp);
@@ -1699,7 +1711,8 @@ float UI_text_clip_middle_ex(const uiFontStyle *fstyle,
/* Corner case, the str already takes all available mem,
* and the ellipsis chars would actually add more chars.
* Better to just trim one or two letters to the right in this case...
- * Note: with a single-char ellipsis, this should never happen! But better be safe here...
+ * Note: with a single-char ellipsis, this should never happen! But better be safe
+ * here...
*/
ui_text_clip_right_ex(
fstyle, str, max_len, okwidth, sep, sep_len, sep_strwidth, &final_lpart_len);
@@ -2346,7 +2359,7 @@ static void widget_draw_text_icon(const uiFontStyle *fstyle,
const BIFIconID icon = widget_icon_id(but);
int icon_size_init = is_tool ? ICON_DEFAULT_HEIGHT_TOOLBAR : ICON_DEFAULT_HEIGHT;
- const float icon_size = icon_size_init / (but->block->aspect / UI_DPI_FAC);
+ const float icon_size = icon_size_init / (but->block->aspect * U.inv_dpi_fac);
const float icon_padding = 2 * UI_DPI_FAC;
#ifdef USE_UI_TOOLBAR_HACK
@@ -3494,8 +3507,11 @@ void UI_draw_widget_scroll(uiWidgetColors *wcol, const rcti *rect, const rcti *s
wcol->item[3] = 255;
if (horizontal) {
- shape_preset_init_scroll_circle(&wtb.tria1, slider, 0.6f, 'l');
- shape_preset_init_scroll_circle(&wtb.tria2, slider, 0.6f, 'r');
+ rcti slider_inset = *slider;
+ slider_inset.xmin += 0.05 * U.widget_unit;
+ slider_inset.xmax -= 0.05 * U.widget_unit;
+ shape_preset_init_scroll_circle(&wtb.tria1, &slider_inset, 0.6f, 'l');
+ shape_preset_init_scroll_circle(&wtb.tria2, &slider_inset, 0.6f, 'r');
}
else {
shape_preset_init_scroll_circle(&wtb.tria1, slider, 0.6f, 'b');
@@ -4631,6 +4647,9 @@ void ui_draw_but(const bContext *C, ARegion *ar, uiStyle *style, uiBut *but, rct
break;
case UI_BTYPE_COLORBAND:
+ /* do not draw right to edge of rect */
+ rect->xmin += (0.25f * UI_UNIT_X);
+ rect->xmax -= (0.3f * UI_UNIT_X);
ui_draw_but_COLORBAND(but, &tui->wcol_regular, rect);
break;
@@ -4655,6 +4674,9 @@ void ui_draw_but(const bContext *C, ARegion *ar, uiStyle *style, uiBut *but, rct
break;
case UI_BTYPE_CURVE:
+ /* do not draw right to edge of rect */
+ rect->xmin += (0.2f * UI_UNIT_X);
+ rect->xmax -= (0.2f * UI_UNIT_X);
ui_draw_but_CURVE(ar, but, &tui->wcol_regular, rect);
break;
@@ -5198,7 +5220,7 @@ void ui_draw_menu_item(
GPU_blend(true);
/* XXX scale weak get from fstyle? */
- UI_icon_draw_aspect(xs, ys, iconid, aspect, 1.0f, wt->wcol.text);
+ UI_icon_draw_ex(xs, ys, iconid, aspect, 1.0f, 0.0f, wt->wcol.text, false);
GPU_blend(false);
}
}
diff --git a/source/blender/editors/interface/resources.c b/source/blender/editors/interface/resources.c
index 587cccf516c..06acf59e07c 100644
--- a/source/blender/editors/interface/resources.c
+++ b/source/blender/editors/interface/resources.c
@@ -309,6 +309,9 @@ 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;
+ break;
case TH_VIEW_OVERLAY:
cp = ts->view_overlay;
break;
@@ -792,6 +795,22 @@ const uchar *UI_ThemeGetColorPtr(bTheme *btheme, int spacetype, int colorid)
cp = ts->selected_highlight;
break;
+ case TH_SELECTED_OBJECT:
+ cp = ts->selected_object;
+ break;
+
+ case TH_ACTIVE_OBJECT:
+ cp = ts->active_object;
+ break;
+
+ case TH_EDITED_OBJECT:
+ cp = ts->edited_object;
+ break;
+
+ case TH_ROW_ALTERNATE:
+ cp = ts->row_alternate;
+ break;
+
case TH_SKIN_ROOT:
cp = ts->skin_root;
break;
@@ -865,6 +884,9 @@ const uchar *UI_ThemeGetColorPtr(bTheme *btheme, int spacetype, int colorid)
cp = btheme->tui.gizmo_b;
break;
+ case TH_ICON_SCENE:
+ cp = btheme->tui.icon_scene;
+ break;
case TH_ICON_COLLECTION:
cp = btheme->tui.icon_collection;
break;
@@ -881,6 +903,10 @@ const uchar *UI_ThemeGetColorPtr(bTheme *btheme, int spacetype, int colorid)
cp = btheme->tui.icon_shading;
break;
+ case TH_SCROLL_TEXT:
+ cp = btheme->tui.wcol_scroll.text;
+ break;
+
case TH_INFO_SELECTED:
cp = ts->info_selected;
break;
@@ -1347,7 +1373,7 @@ void UI_GetThemeColorType4ubv(int colorid, int spacetype, uchar col[4])
col[3] = cp[3];
}
-bool UI_GetIconThemeColor4fv(int colorid, float col[4])
+bool UI_GetIconThemeColor4ubv(int colorid, uchar col[4])
{
if (colorid == 0) {
return false;
@@ -1356,16 +1382,16 @@ bool UI_GetIconThemeColor4fv(int colorid, float col[4])
/* Only colored icons in outliner and popups, overall UI is intended
* to stay monochrome and out of the way except a few places where it
* is important to communicate different data types. */
- if (!((theme_spacetype == SPACE_OUTLINER) || (theme_regionid == RGN_TYPE_TEMPORARY))) {
+ if (!((theme_spacetype == SPACE_OUTLINER && theme_regionid == RGN_TYPE_WINDOW) ||
+ (theme_spacetype == SPACE_PROPERTIES && theme_regionid == RGN_TYPE_NAV_BAR))) {
return false;
}
- const uchar *cp;
- cp = UI_ThemeGetColorPtr(theme_active, theme_spacetype, colorid);
- col[0] = ((float)cp[0]) / 255.0f;
- col[1] = ((float)cp[1]) / 255.0f;
- col[2] = ((float)cp[2]) / 255.0f;
- col[3] = ((float)cp[3]) / 255.0f;
+ const uchar *cp = UI_ThemeGetColorPtr(theme_active, theme_spacetype, colorid);
+ col[0] = cp[0];
+ col[1] = cp[1];
+ col[2] = cp[2];
+ col[3] = cp[3];
return true;
}
diff --git a/source/blender/editors/interface/view2d.c b/source/blender/editors/interface/view2d.c
index 58d26c4a840..f2d4faff479 100644
--- a/source/blender/editors/interface/view2d.c
+++ b/source/blender/editors/interface/view2d.c
@@ -138,7 +138,7 @@ static void view2d_masks(View2D *v2d, bool check_scrollers, const rcti *mask_scr
if (check_scrollers) {
/* check size if hiding flag is set: */
if (v2d->scroll & V2D_SCROLL_HORIZONTAL_HIDE) {
- if (!(v2d->scroll & V2D_SCROLL_SCALE_HORIZONTAL)) {
+ if (!(v2d->scroll & V2D_SCROLL_HORIZONTAL_HANDLES)) {
if (BLI_rctf_size_x(&v2d->tot) > BLI_rctf_size_x(&v2d->cur)) {
v2d->scroll &= ~V2D_SCROLL_HORIZONTAL_FULLR;
}
@@ -148,7 +148,7 @@ static void view2d_masks(View2D *v2d, bool check_scrollers, const rcti *mask_scr
}
}
if (v2d->scroll & V2D_SCROLL_VERTICAL_HIDE) {
- if (!(v2d->scroll & V2D_SCROLL_SCALE_VERTICAL)) {
+ if (!(v2d->scroll & V2D_SCROLL_VERTICAL_HANDLES)) {
if (BLI_rctf_size_y(&v2d->tot) + 0.01f > BLI_rctf_size_y(&v2d->cur)) {
v2d->scroll &= ~V2D_SCROLL_VERTICAL_FULLR;
}
@@ -166,10 +166,11 @@ static void view2d_masks(View2D *v2d, bool check_scrollers, const rcti *mask_scr
* - if they overlap, they must not occupy the corners (which are reserved for other widgets)
*/
if (scroll) {
- const int scroll_width = (v2d->scroll & V2D_SCROLL_SCALE_VERTICAL) ? V2D_SCROLL_WIDTH_TEXT :
- V2D_SCROLL_WIDTH;
- const int scroll_height = (v2d->scroll & V2D_SCROLL_SCALE_HORIZONTAL) ?
- V2D_SCROLL_HEIGHT_TEXT :
+ const int scroll_width = (v2d->scroll & V2D_SCROLL_VERTICAL_HANDLES) ?
+ V2D_SCROLL_WIDTH_HANDLES :
+ V2D_SCROLL_WIDTH;
+ const int scroll_height = (v2d->scroll & V2D_SCROLL_HORIZONTAL_HANDLES) ?
+ V2D_SCROLL_HEIGHT_HANDLES :
V2D_SCROLL_HEIGHT;
/* vertical scroller */
@@ -185,6 +186,13 @@ static void view2d_masks(View2D *v2d, bool check_scrollers, const rcti *mask_scr
v2d->vert.xmin = v2d->vert.xmax - scroll_width;
}
+ /* Currently, all regions that have vertical scale handles,
+ * 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;
+ }
+
/* horizontal scroller */
if (scroll & (V2D_SCROLL_BOTTOM)) {
/* on bottom edge of region */
@@ -1589,7 +1597,7 @@ void UI_view2d_scrollers_draw(View2D *v2d, View2DScrollers *vs)
* (workaround to make sure that button windows don't show these,
* and only the time-grids with their zoomability can do so)
*/
- if ((v2d->keepzoom & V2D_LOCKZOOM_X) == 0 && (v2d->scroll & V2D_SCROLL_SCALE_HORIZONTAL) &&
+ if ((v2d->keepzoom & V2D_LOCKZOOM_X) == 0 && (v2d->scroll & V2D_SCROLL_HORIZONTAL_HANDLES) &&
(BLI_rcti_size_x(&slider) > V2D_SCROLLER_HANDLE_SIZE)) {
state |= UI_SCROLL_ARROWS;
}
@@ -1623,7 +1631,7 @@ void UI_view2d_scrollers_draw(View2D *v2d, View2DScrollers *vs)
* (workaround to make sure that button windows don't show these,
* and only the time-grids with their zoomability can do so)
*/
- if ((v2d->keepzoom & V2D_LOCKZOOM_Y) == 0 && (v2d->scroll & V2D_SCROLL_SCALE_VERTICAL) &&
+ if ((v2d->keepzoom & V2D_LOCKZOOM_Y) == 0 && (v2d->scroll & V2D_SCROLL_VERTICAL_HANDLES) &&
(BLI_rcti_size_y(&slider) > V2D_SCROLLER_HANDLE_SIZE)) {
state |= UI_SCROLL_ARROWS;
}
@@ -1644,59 +1652,6 @@ void UI_view2d_scrollers_free(View2DScrollers *scrollers)
/* *********************************************************************** */
/* List View Utilities */
-/** Get the view-coordinates of the nominated cell
- *
- * \param columnwidth, rowheight: size of each 'cell'
- * \param startx, starty: coordinates (in 'tot' rect space) that the list starts from.
- * This should be (0,0) for most views. However, for those where the starting row was offsetted
- * (like for Animation Editor channel lists, to make the first entry more visible), these will be
- * the min-coordinates of the first item.
- * \param column, row: The 2d-coordinates
- * (in 2D-view / 'tot' rect space) the cell exists at
- * \param rect: coordinates of the cell
- * (passed as single var instead of 4 separate, as it's more useful this way)
- */
-void UI_view2d_listview_cell_to_view(View2D *v2d,
- float columnwidth,
- float rowheight,
- float startx,
- float starty,
- int column,
- int row,
- rctf *rect)
-{
- /* sanity checks */
- if (ELEM(NULL, v2d, rect)) {
- return;
- }
-
- if ((columnwidth <= 0) && (rowheight <= 0)) {
- rect->xmin = rect->xmax = 0.0f;
- rect->ymin = rect->ymax = 0.0f;
- return;
- }
-
- /* x-coordinates */
- rect->xmin = startx + (float)(columnwidth * column);
- rect->xmax = startx + (float)(columnwidth * (column + 1));
-
- if ((v2d->align & V2D_ALIGN_NO_POS_X) && !(v2d->align & V2D_ALIGN_NO_NEG_X)) {
- /* simply negate the values for the coordinates if in negative half */
- rect->xmin = -rect->xmin;
- rect->xmax = -rect->xmax;
- }
-
- /* y-coordinates */
- rect->ymin = starty + (float)(rowheight * row);
- rect->ymax = starty + (float)(rowheight * (row + 1));
-
- if ((v2d->align & V2D_ALIGN_NO_POS_Y) && !(v2d->align & V2D_ALIGN_NO_NEG_Y)) {
- /* simply negate the values for the coordinates if in negative half */
- rect->ymin = -rect->ymin;
- rect->ymax = -rect->ymax;
- }
-}
-
/**
* Get the 'cell' (row, column) that the given 2D-view coordinates
* (i.e. in 'tot' rect space) lie in.
@@ -1709,8 +1664,7 @@ void UI_view2d_listview_cell_to_view(View2D *v2d,
* \param viewx, viewy: 2D-coordinates (in 2D-view / 'tot' rect space) to get the cell for
* \param r_column, r_row: the 'coordinates' of the relevant 'cell'
*/
-void UI_view2d_listview_view_to_cell(View2D *v2d,
- float columnwidth,
+void UI_view2d_listview_view_to_cell(float columnwidth,
float rowheight,
float startx,
float starty,
@@ -1719,80 +1673,24 @@ void UI_view2d_listview_view_to_cell(View2D *v2d,
int *r_column,
int *r_row)
{
- /* adjust view coordinates to be all positive ints, corrected for the start offset */
- const int x = (int)(floorf(fabsf(viewx) + 0.5f) - startx);
- const int y = (int)(floorf(fabsf(viewy) + 0.5f) - starty);
-
- /* sizes must not be negative */
- if ((v2d == NULL) || ((columnwidth <= 0) && (rowheight <= 0))) {
- if (r_column) {
- *r_column = 0;
+ if (r_column) {
+ if (columnwidth > 0) {
+ /* Columns go from left to right (x increases). */
+ *r_column = floorf((viewx - startx) / columnwidth);
}
- if (r_row) {
- *r_row = 0;
+ else {
+ *r_column = 0;
}
-
- return;
- }
-
- /* get column */
- if ((r_column) && (columnwidth > 0)) {
- *r_column = x / columnwidth;
- }
- else if (r_column) {
- *r_column = 0;
}
- /* get row */
- if ((r_row) && (rowheight > 0)) {
- *r_row = y / rowheight;
- }
- else if (r_row) {
- *r_row = 0;
- }
-}
-
-/**
- * Get the 'extreme' (min/max) column and row indices which are visible within the 'cur' rect
- *
- * \param columnwidth, rowheight: Size of each 'cell'
- * \param startx, starty: Coordinates that the list starts from,
- * which should be (0,0) for most views.
- * \param column_min, column_max, row_min, row_max: The starting and ending column/row indices
- */
-void UI_view2d_listview_visible_cells(View2D *v2d,
- float columnwidth,
- float rowheight,
- float startx,
- float starty,
- int *column_min,
- int *column_max,
- int *row_min,
- int *row_max)
-{
- /* using 'cur' rect coordinates, call the cell-getting function to get the cells for this */
- if (v2d) {
- /* min */
- UI_view2d_listview_view_to_cell(v2d,
- columnwidth,
- rowheight,
- startx,
- starty,
- v2d->cur.xmin,
- v2d->cur.ymin,
- column_min,
- row_min);
-
- /* max*/
- UI_view2d_listview_view_to_cell(v2d,
- columnwidth,
- rowheight,
- startx,
- starty,
- v2d->cur.xmax,
- v2d->cur.ymax,
- column_max,
- row_max);
+ if (r_row) {
+ if (rowheight > 0) {
+ /* Rows got from top to bottom (y decreases). */
+ *r_row = floorf((starty - viewy) / rowheight);
+ }
+ else {
+ *r_row = 0;
+ }
}
}
diff --git a/source/blender/editors/interface/view2d_draw.c b/source/blender/editors/interface/view2d_draw.c
index 91128e49a60..2009bbecebc 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,
@@ -153,6 +153,12 @@ static void get_parallel_lines_draw_steps(const ParallelLinesSet *lines,
float *r_first,
uint *r_steps)
{
+ if (region_start >= region_end) {
+ *r_first = 0;
+ *r_steps = 0;
+ return;
+ }
+
BLI_assert(lines->distance > 0);
BLI_assert(region_start <= region_end);
@@ -258,7 +264,8 @@ static void draw_horizontal_scale_indicators(const ARegion *ar,
float distance,
const rcti *rect,
PositionToString to_string,
- void *to_string_data)
+ void *to_string_data,
+ int colorid)
{
GPU_matrix_push_projection();
wmOrtho2_region_pixelspace(ar);
@@ -277,7 +284,7 @@ static void draw_horizontal_scale_indicators(const ARegion *ar,
}
const int font_id = BLF_default();
- UI_FontThemeColor(font_id, TH_TEXT);
+ UI_FontThemeColor(font_id, colorid);
BLF_batch_draw_begin();
@@ -308,7 +315,8 @@ static void draw_vertical_scale_indicators(const ARegion *ar,
float display_offset,
const rcti *rect,
PositionToString to_string,
- void *to_string_data)
+ void *to_string_data,
+ int colorid)
{
GPU_matrix_push_projection();
wmOrtho2_region_pixelspace(ar);
@@ -327,7 +335,7 @@ static void draw_vertical_scale_indicators(const ARegion *ar,
}
const int font_id = BLF_default();
- UI_FontThemeColor(font_id, TH_TEXT);
+ UI_FontThemeColor(font_id, colorid);
BLF_enable(font_id, BLF_ROTATION);
BLF_rotation(font_id, M_PI_2);
@@ -463,51 +471,62 @@ void UI_view2d_draw_lines_x__frames_or_seconds(const View2D *v2d,
/* Scale indicator text drawing API
**************************************************/
-void UI_view2d_draw_scale_x__discrete_values(const ARegion *ar,
- const View2D *v2d,
- const rcti *rect)
+static void UI_view2d_draw_scale_x__discrete_values(const ARegion *ar,
+ const View2D *v2d,
+ const rcti *rect,
+ int colorid)
{
float number_step = view2d_major_step_x__discrete(v2d);
- draw_horizontal_scale_indicators(ar, v2d, number_step, rect, view_to_string__frame_number, NULL);
+ draw_horizontal_scale_indicators(
+ ar, v2d, number_step, rect, view_to_string__frame_number, NULL, colorid);
}
-void UI_view2d_draw_scale_x__discrete_time(const ARegion *ar,
- const View2D *v2d,
- const rcti *rect,
- const Scene *scene)
+static void UI_view2d_draw_scale_x__discrete_time(
+ const ARegion *ar, const View2D *v2d, const rcti *rect, const Scene *scene, int colorid)
{
float step = view2d_major_step_x__time(v2d, scene);
- draw_horizontal_scale_indicators(ar, v2d, step, rect, view_to_string__time, (void *)scene);
+ draw_horizontal_scale_indicators(
+ ar, v2d, step, rect, view_to_string__time, (void *)scene, colorid);
}
-void UI_view2d_draw_scale_x__values(const ARegion *ar, const View2D *v2d, const rcti *rect)
+static void UI_view2d_draw_scale_x__values(const ARegion *ar,
+ const View2D *v2d,
+ const rcti *rect,
+ int colorid)
{
float step = view2d_major_step_x__continuous(v2d);
- draw_horizontal_scale_indicators(ar, v2d, step, rect, view_to_string__value, NULL);
+ draw_horizontal_scale_indicators(ar, v2d, step, rect, view_to_string__value, NULL, colorid);
}
-void UI_view2d_draw_scale_y__values(const ARegion *ar, const View2D *v2d, const rcti *rect)
+void UI_view2d_draw_scale_y__values(const ARegion *ar,
+ const View2D *v2d,
+ const rcti *rect,
+ int colorid)
{
float step = view2d_major_step_y__continuous(v2d);
- draw_vertical_scale_indicators(ar, v2d, step, 0.0f, rect, view_to_string__value, NULL);
+ draw_vertical_scale_indicators(ar, v2d, step, 0.0f, rect, view_to_string__value, NULL, colorid);
}
-void UI_view2d_draw_scale_y__block(const ARegion *ar, const View2D *v2d, const rcti *rect)
+void UI_view2d_draw_scale_y__block(const ARegion *ar,
+ const View2D *v2d,
+ const rcti *rect,
+ int colorid)
{
- draw_vertical_scale_indicators(ar, v2d, 1.0f, 0.5f, rect, view_to_string__value, NULL);
+ draw_vertical_scale_indicators(ar, v2d, 1.0f, 0.5f, rect, view_to_string__value, NULL, colorid);
}
void UI_view2d_draw_scale_x__discrete_frames_or_seconds(const struct ARegion *ar,
const struct View2D *v2d,
const struct rcti *rect,
const struct Scene *scene,
- bool display_seconds)
+ bool display_seconds,
+ int colorid)
{
if (display_seconds) {
- UI_view2d_draw_scale_x__discrete_time(ar, v2d, rect, scene);
+ UI_view2d_draw_scale_x__discrete_time(ar, v2d, rect, scene, colorid);
}
else {
- UI_view2d_draw_scale_x__discrete_values(ar, v2d, rect);
+ UI_view2d_draw_scale_x__discrete_values(ar, v2d, rect, colorid);
}
}
@@ -515,12 +534,13 @@ void UI_view2d_draw_scale_x__frames_or_seconds(const struct ARegion *ar,
const struct View2D *v2d,
const struct rcti *rect,
const struct Scene *scene,
- bool display_seconds)
+ bool display_seconds,
+ int colorid)
{
if (display_seconds) {
- UI_view2d_draw_scale_x__discrete_time(ar, v2d, rect, scene);
+ UI_view2d_draw_scale_x__discrete_time(ar, v2d, rect, scene, colorid);
}
else {
- UI_view2d_draw_scale_x__values(ar, v2d, rect);
+ UI_view2d_draw_scale_x__values(ar, v2d, rect, colorid);
}
}
diff --git a/source/blender/editors/interface/view2d_ops.c b/source/blender/editors/interface/view2d_ops.c
index ab8d1cf9bf6..68ee38bc99f 100644
--- a/source/blender/editors/interface/view2d_ops.c
+++ b/source/blender/editors/interface/view2d_ops.c
@@ -2032,8 +2032,8 @@ static int scroller_activate_invoke(bContext *C, wmOperator *op, const wmEvent *
* NOTE: see view2d.c for latest conditions, and keep this in sync with that
*/
if (ELEM(vsm->zone, SCROLLHANDLE_MIN, SCROLLHANDLE_MAX)) {
- if (((vsm->scroller == 'h') && (v2d->scroll & V2D_SCROLL_SCALE_HORIZONTAL) == 0) ||
- ((vsm->scroller == 'v') && (v2d->scroll & V2D_SCROLL_SCALE_VERTICAL) == 0)) {
+ if (((vsm->scroller == 'h') && (v2d->scroll & V2D_SCROLL_HORIZONTAL_HANDLES) == 0) ||
+ ((vsm->scroller == 'v') && (v2d->scroll & V2D_SCROLL_VERTICAL_HANDLES) == 0)) {
/* switch to bar (i.e. no scaling gets handled) */
vsm->zone = SCROLLHANDLE_BAR;
}
diff --git a/source/blender/editors/io/io_cache.c b/source/blender/editors/io/io_cache.c
index 3dd3b20bda3..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(&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/mask/mask_ops.c b/source/blender/editors/mask/mask_ops.c
index c0f3b1f8338..1f825c0bb31 100644
--- a/source/blender/editors/mask/mask_ops.c
+++ b/source/blender/editors/mask/mask_ops.c
@@ -1992,9 +1992,9 @@ static int mask_hide_view_clear_exec(bContext *C, wmOperator *op)
for (masklay = mask->masklayers.first; masklay; masklay = masklay->next) {
- if (masklay->restrictflag & OB_RESTRICT_VIEW) {
+ if (masklay->restrictflag & OB_RESTRICT_VIEWPORT) {
ED_mask_layer_select_set(masklay, select);
- masklay->restrictflag &= ~OB_RESTRICT_VIEW;
+ masklay->restrictflag &= ~OB_RESTRICT_VIEWPORT;
changed = true;
}
}
@@ -2045,7 +2045,7 @@ static int mask_hide_view_set_exec(bContext *C, wmOperator *op)
if (ED_mask_layer_select_check(masklay)) {
ED_mask_layer_select_set(masklay, false);
- masklay->restrictflag |= OB_RESTRICT_VIEW;
+ masklay->restrictflag |= OB_RESTRICT_VIEWPORT;
changed = true;
if (masklay == BKE_mask_layer_active(mask)) {
BKE_mask_layer_active_set(mask, NULL);
@@ -2054,7 +2054,7 @@ static int mask_hide_view_set_exec(bContext *C, wmOperator *op)
}
else {
if (!ED_mask_layer_select_check(masklay)) {
- masklay->restrictflag |= OB_RESTRICT_VIEW;
+ masklay->restrictflag |= OB_RESTRICT_VIEWPORT;
changed = true;
if (masklay == BKE_mask_layer_active(mask)) {
BKE_mask_layer_active_set(mask, NULL);
diff --git a/source/blender/editors/mesh/CMakeLists.txt b/source/blender/editors/mesh/CMakeLists.txt
index 57bf67e825e..9a779db4812 100644
--- a/source/blender/editors/mesh/CMakeLists.txt
+++ b/source/blender/editors/mesh/CMakeLists.txt
@@ -23,6 +23,7 @@ set(INC
../../blentranslation
../../bmesh
../../depsgraph
+ ../../draw
../../gpu
../../imbuf
../../makesdna
diff --git a/source/blender/editors/mesh/editface.c b/source/blender/editors/mesh/editface.c
index 990250792a1..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;
- int a, index;
-
- char *selar = MEM_callocN(me->totpoly + 1, "selar");
-
- uint buf_len;
- uint *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_add_gizmo.c b/source/blender/editors/mesh/editmesh_add_gizmo.c
index 839ee186016..f6729fb56e1 100644
--- a/source/blender/editors/mesh/editmesh_add_gizmo.c
+++ b/source/blender/editors/mesh/editmesh_add_gizmo.c
@@ -29,6 +29,7 @@
#include "BKE_context.h"
#include "BKE_editmesh.h"
+#include "BKE_scene.h"
#include "ED_gizmo_library.h"
#include "ED_gizmo_utils.h"
@@ -75,7 +76,7 @@ static void calc_initial_placement_point_from_view(bContext *C,
float cursor_matrix[4][4];
float orient_matrix[3][3];
- ED_view3d_cursor3d_calc_mat4(scene, cursor_matrix);
+ BKE_scene_cursor_to_mat4(&scene->cursor, cursor_matrix);
float dots[3] = {
dot_v3v3(rv3d->viewinv[2], cursor_matrix[0]),
diff --git a/source/blender/editors/mesh/editmesh_bevel.c b/source/blender/editors/mesh/editmesh_bevel.c
index f6940cae953..1cd4e95314b 100644
--- a/source/blender/editors/mesh/editmesh_bevel.c
+++ b/source/blender/editors/mesh/editmesh_bevel.c
@@ -907,7 +907,8 @@ void MESH_OT_bevel(wmOperatorType *ot)
/* identifiers */
ot->name = "Bevel";
- ot->description = "Edge Bevel";
+ ot->description =
+ "Cut into selected items at an angle to create flat or rounded bevel or chamfer";
ot->idname = "MESH_OT_bevel";
/* api callbacks */
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.c b/source/blender/editors/mesh/editmesh_extrude.c
index 82cff8363f8..0da4d20c6b5 100644
--- a/source/blender/editors/mesh/editmesh_extrude.c
+++ b/source/blender/editors/mesh/editmesh_extrude.c
@@ -36,6 +36,7 @@
#include "RNA_access.h"
#include "WM_types.h"
+#include "WM_api.h"
#include "ED_mesh.h"
#include "ED_screen.h"
@@ -860,6 +861,9 @@ static int edbm_dupli_extrude_cursor_invoke(bContext *C, wmOperator *op, const w
EDBM_mesh_normals_update(vc.em);
EDBM_update_generic(vc.em, true, true);
+
+ WM_event_add_notifier(C, NC_GEOM | ND_DATA, obedit->data);
+ WM_event_add_notifier(C, NC_GEOM | ND_SELECT, obedit->data);
}
MEM_freeN(objects);
diff --git a/source/blender/editors/mesh/editmesh_knife.c b/source/blender/editors/mesh/editmesh_knife.c
index cc0c2f5bbe4..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);
@@ -2811,6 +2812,7 @@ wmKeyMap *knifetool_modal_keymap(wmKeyConfig *keyconf)
{KNF_MODAL_CUT_THROUGH_TOGGLE, "CUT_THROUGH_TOGGLE", 0, "Toggle Cut Through", ""},
{KNF_MODAL_NEW_CUT, "NEW_CUT", 0, "End Current Cut", ""},
{KNF_MODAL_ADD_CUT, "ADD_CUT", 0, "Add Cut", ""},
+ {KNF_MODAL_ADD_CUT_CLOSED, "ADD_CUT_CLOSED", 0, "Add Cut Closed", ""},
{KNF_MODAL_PANNING, "PANNING", 0, "Panning", ""},
{0, NULL, 0, NULL, NULL},
};
diff --git a/source/blender/editors/mesh/editmesh_loopcut.c b/source/blender/editors/mesh/editmesh_loopcut.c
index 528235e693a..59355890428 100644
--- a/source/blender/editors/mesh/editmesh_loopcut.c
+++ b/source/blender/editors/mesh/editmesh_loopcut.c
@@ -79,11 +79,11 @@ typedef struct RingSelOpData {
Depsgraph *depsgraph;
- Object **objects;
- uint objects_len;
+ Base **bases;
+ uint bases_len;
/* These values switch objects based on the object under the cursor. */
- uint ob_index;
+ uint base_index;
Object *ob;
BMEditMesh *em;
BMEdge *eed;
@@ -111,8 +111,8 @@ static void edgering_select(RingSelOpData *lcd)
}
if (!lcd->extend) {
- for (uint ob_index = 0; ob_index < lcd->objects_len; ob_index++) {
- Object *ob_iter = lcd->objects[ob_index];
+ for (uint base_index = 0; base_index < lcd->bases_len; base_index++) {
+ Object *ob_iter = lcd->bases[base_index]->object;
BMEditMesh *em = BKE_editmesh_from_object(ob_iter);
EDBM_flag_disable_all(em, BM_ELEM_SELECT);
DEG_id_tag_update(ob_iter->data, ID_RECALC_SELECT);
@@ -252,7 +252,7 @@ static void ringsel_exit(bContext *UNUSED(C), wmOperator *op)
EDBM_preselect_edgering_destroy(lcd->presel_edgering);
- MEM_freeN(lcd->objects);
+ MEM_freeN(lcd->bases);
ED_region_tag_redraw(lcd->ar);
@@ -307,21 +307,21 @@ static void ringcut_cancel(bContext *C, wmOperator *op)
}
static void loopcut_update_edge(RingSelOpData *lcd,
- uint ob_index,
+ uint base_index,
BMEdge *e,
const int previewlines)
{
if (e != lcd->eed) {
lcd->eed = e;
lcd->ob = lcd->vc.obedit;
- lcd->ob_index = ob_index;
+ lcd->base_index = base_index;
lcd->em = lcd->vc.em;
ringsel_find_edge(lcd, previewlines);
}
else if (e == NULL) {
lcd->ob = NULL;
lcd->em = NULL;
- lcd->ob_index = UINT_MAX;
+ lcd->base_index = UINT_MAX;
}
}
@@ -331,27 +331,26 @@ static void loopcut_mouse_move(RingSelOpData *lcd, const int previewlines)
Object *ob;
BMEdge *eed;
float dist;
- int ob_index;
+ int base_index;
} best = {
.dist = ED_view3d_select_dist_px(),
};
- for (uint ob_index = 0; ob_index < lcd->objects_len; ob_index++) {
- Object *ob_iter = lcd->objects[ob_index];
- ED_view3d_viewcontext_init_object(&lcd->vc, ob_iter);
- BMEdge *eed_test = EDBM_edge_find_nearest_ex(&lcd->vc, &best.dist, NULL, false, false, NULL);
- if (eed_test) {
- best.ob = ob_iter;
- best.eed = eed_test;
- best.ob_index = ob_index;
- }
+ uint base_index;
+ BMEdge *eed_test = EDBM_edge_find_nearest_ex(
+ &lcd->vc, &best.dist, NULL, false, false, NULL, lcd->bases, lcd->bases_len, &base_index);
+
+ if (eed_test) {
+ best.ob = lcd->bases[base_index]->object;
+ best.eed = eed_test;
+ best.base_index = base_index;
}
if (best.eed) {
ED_view3d_viewcontext_init_object(&lcd->vc, best.ob);
}
- loopcut_update_edge(lcd, best.ob_index, best.eed, previewlines);
+ loopcut_update_edge(lcd, best.base_index, best.eed, previewlines);
}
/* called by both init() and exec() */
@@ -361,22 +360,22 @@ static int loopcut_init(bContext *C, wmOperator *op, const wmEvent *event)
/* Use for redo - intentionally wrap int to uint. */
const struct {
- uint ob_index;
+ uint base_index;
uint e_index;
} exec_data = {
- .ob_index = (uint)RNA_int_get(op->ptr, "object_index"),
+ .base_index = (uint)RNA_int_get(op->ptr, "object_index"),
.e_index = (uint)RNA_int_get(op->ptr, "edge_index"),
};
ViewLayer *view_layer = CTX_data_view_layer(C);
- uint objects_len;
- Object **objects = BKE_view_layer_array_from_objects_in_edit_mode(
- view_layer, CTX_wm_view3d(C), &objects_len);
+ uint bases_len;
+ Base **bases = BKE_view_layer_array_from_bases_in_edit_mode(
+ view_layer, CTX_wm_view3d(C), &bases_len);
if (is_interactive) {
- for (uint ob_index = 0; ob_index < objects_len; ob_index++) {
- Object *ob_iter = objects[ob_index];
+ for (uint base_index = 0; base_index < bases_len; base_index++) {
+ Object *ob_iter = bases[base_index]->object;
if (modifiers_isDeformedByLattice(ob_iter) || modifiers_isDeformedByArmature(ob_iter)) {
BKE_report(
op->reports, RPT_WARNING, "Loop cut does not work well on deformed edit mesh display");
@@ -390,12 +389,12 @@ static int loopcut_init(bContext *C, wmOperator *op, const wmEvent *event)
/* for re-execution, check edge index is in range before we setup ringsel */
bool ok = true;
if (is_interactive == false) {
- if (exec_data.ob_index >= objects_len) {
+ if (exec_data.base_index >= bases_len) {
return OPERATOR_CANCELLED;
ok = false;
}
else {
- Object *ob_iter = objects[exec_data.ob_index];
+ Object *ob_iter = bases[exec_data.base_index]->object;
BMEditMesh *em = BKE_editmesh_from_object(ob_iter);
if (exec_data.e_index >= em->bm->totedge) {
ok = false;
@@ -404,7 +403,7 @@ static int loopcut_init(bContext *C, wmOperator *op, const wmEvent *event)
}
if (!ok || !ringsel_init(C, op, true)) {
- MEM_freeN(objects);
+ MEM_freeN(bases);
return OPERATOR_CANCELLED;
}
@@ -416,8 +415,8 @@ static int loopcut_init(bContext *C, wmOperator *op, const wmEvent *event)
RingSelOpData *lcd = op->customdata;
- lcd->objects = objects;
- lcd->objects_len = objects_len;
+ lcd->bases = bases;
+ lcd->bases_len = bases_len;
if (is_interactive) {
copy_v2_v2_int(lcd->vc.mval, event->mval);
@@ -425,13 +424,13 @@ static int loopcut_init(bContext *C, wmOperator *op, const wmEvent *event)
}
else {
- Object *ob_iter = objects[exec_data.ob_index];
+ Object *ob_iter = bases[exec_data.base_index]->object;
ED_view3d_viewcontext_init_object(&lcd->vc, ob_iter);
BMEdge *e;
BM_mesh_elem_table_ensure(lcd->vc.em->bm, BM_EDGE);
e = BM_edge_at_index(lcd->vc.em->bm, exec_data.e_index);
- loopcut_update_edge(lcd, exec_data.ob_index, e, 0);
+ loopcut_update_edge(lcd, exec_data.base_index, e, 0);
}
#ifdef USE_LOOPSLIDE_HACK
@@ -503,7 +502,7 @@ static int loopcut_finish(RingSelOpData *lcd, bContext *C, wmOperator *op)
if (lcd->eed) {
/* set for redo */
BM_mesh_elem_index_ensure(lcd->em->bm, BM_EDGE);
- RNA_int_set(op->ptr, "object_index", lcd->ob_index);
+ RNA_int_set(op->ptr, "object_index", lcd->base_index);
RNA_int_set(op->ptr, "edge_index", BM_elem_index_get(lcd->eed));
/* execute */
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 9df03a81762..dc94219cb9a 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"
@@ -67,6 +68,8 @@
#include "DEG_depsgraph.h"
#include "DEG_depsgraph_query.h"
+#include "DRW_engine.h"
+
#include "mesh_intern.h" /* own include */
/* use bmesh operator flags for a few operators */
@@ -196,186 +199,171 @@ void EDBM_automerge(Scene *scene, Object *obedit, bool update, const char hflag)
/** \name Back-Buffer OpenGL Selection
* \{ */
-/* set in drawobject.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;
+struct EDBMBaseOffset {
+ /* For convenience only. */
+ union {
+ uint offset;
+ uint face_start;
+ };
+ union {
+ uint face;
+ uint edge_start;
+ };
+ union {
+ uint edge;
+ uint vert_start;
+ };
+ uint vert;
+};
-static BLI_bitmap *edbm_backbuf_alloc(const int size)
-{
- return BLI_BITMAP_NEW(size, "selbuf");
-}
+struct EDBMSelectID_Context {
+ struct EDBMBaseOffset *base_array_index_offsets;
+ /** 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;
+};
-/* 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)
+static bool check_ob_drawface_dot(short select_mode, const View3D *v3d, char dt)
{
- uint *buf, *dr, buf_len;
-
- if (vc->obedit == NULL || XRAY_FLAG_ENABLED(vc->v3d)) {
- return false;
- }
-
- 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);
+ if (select_mode & SCE_SELECT_FACE) {
+ if (dt < OB_SOLID) {
+ return true;
+ }
+ if (v3d->overlay.edit_flag & V3D_OVERLAY_EDIT_FACE_DOT) {
+ return true;
+ }
+ if (XRAY_FLAG_ENABLED(v3d)) {
+ return true;
}
- dr++;
}
- MEM_freeN(buf);
- return true;
+ return false;
}
-bool EDBM_backbuf_check(unsigned int index)
+static void edbm_select_pick_draw_bases(struct EDBMSelectID_Context *sel_id_ctx,
+ ViewContext *vc,
+ short select_mode)
{
- /* 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;
- }
+ Scene *scene_eval = (Scene *)DEG_get_evaluated_id(vc->depsgraph, &vc->scene->id);
+ DRW_framebuffer_select_id_setup(vc->ar, true);
- if (index > 0 && index <= bm_vertoffs) {
- return BLI_BITMAP_TEST_BOOL(selbuf, index);
- }
+ 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);
- return false;
-}
+ struct EDBMBaseOffset *base_ofs = &sel_id_ctx->base_array_index_offsets[base_index];
+ bool draw_facedot = check_ob_drawface_dot(select_mode, vc->v3d, ob_eval->dt);
-void EDBM_backbuf_free(void)
-{
- if (selbuf) {
- MEM_freeN(selbuf);
+ DRW_draw_select_id_object(scene_eval,
+ vc->rv3d,
+ ob_eval,
+ select_mode,
+ draw_facedot,
+ offset,
+ &base_ofs->vert,
+ &base_ofs->edge,
+ &base_ofs->face);
+
+ base_ofs->offset = offset;
+ offset = base_ofs->vert;
}
- selbuf = NULL;
-}
-struct LassoMaskData {
- unsigned int *px;
- int width;
-};
+ sel_id_ctx->base_array_index_len = offset;
-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);
+ DRW_framebuffer_select_id_release(vc->ar);
}
-/* 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)
+BMElem *EDBM_select_id_bm_elem_get(struct EDBMSelectID_Context *sel_id_ctx,
+ const uint sel_id,
+ uint *r_base_index)
{
- 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;
+ char elem_type;
+ uint elem_id;
+ 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 - base_ofs->face_start;
+ elem_type = BM_FACE;
+ break;
+ }
+ if (base_ofs->edge > sel_id) {
+ 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->vert_start;
+ elem_type = BM_VERT;
+ break;
}
- }
- else if (XRAY_FLAG_ENABLED(vc->v3d)) {
- return false;
}
- buf = ED_view3d_select_id_read(vc, xmin, ymin, xmax, ymax, &buf_len);
- if ((buf == NULL) || (bm_vertoffs == 0)) {
- return false;
+ if (r_base_index) {
+ *r_base_index = base_index;
}
- 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);
+ Object *obedit = sel_id_ctx->bases[base_index]->object;
+ BMEditMesh *em = BKE_editmesh_from_object(obedit);
- while (buf_len--) {
- if (*dr > 0 && *dr <= bm_vertoffs && *dr_mask == true) {
- BLI_BITMAP_ENABLE(selbuf, *dr);
- }
- dr++;
- dr_mask++;
+ switch (elem_type) {
+ case BM_FACE:
+ return (BMElem *)BM_face_at_index_find_or_table(em->bm, elem_id);
+ case BM_EDGE:
+ return (BMElem *)BM_edge_at_index_find_or_table(em->bm, elem_id);
+ case BM_VERT:
+ return (BMElem *)BM_vert_at_index_find_or_table(em->bm, elem_id);
+ default:
+ BLI_assert(0);
+ return NULL;
}
- 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 EDBM_select_id_context_offset_for_object_elem(const struct EDBMSelectID_Context *sel_id_ctx,
+ int base_index,
+ char htype)
{
- 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;
- }
+ struct EDBMBaseOffset *base_ofs = &sel_id_ctx->base_array_index_offsets[base_index];
+ if (htype == BM_VERT) {
+ return base_ofs->vert_start - 1;
}
- else if (XRAY_FLAG_ENABLED(vc->v3d)) {
- return false;
+ if (htype == BM_EDGE) {
+ return base_ofs->edge_start - 1;
}
-
- xmin = xs - rads;
- xmax = xs + rads;
- ymin = ys - rads;
- ymax = ys + rads;
- buf = ED_view3d_select_id_read(vc, xmin, ymin, xmax, ymax, NULL);
- if ((buf == NULL) || (bm_vertoffs == 0)) {
- return false;
+ if (htype == BM_FACE) {
+ return base_ofs->face_start - 1;
}
+ BLI_assert(0);
+ return 0;
+}
- dr = buf;
+uint EDBM_select_id_context_elem_len(const struct EDBMSelectID_Context *sel_id_ctx)
+{
+ return sel_id_ctx->base_array_index_len;
+}
- /* 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);
- }
- }
- }
- }
+struct EDBMSelectID_Context *EDBM_select_id_context_create(ViewContext *vc,
+ Base **bases,
+ uint bases_len,
+ short select_mode)
+{
+ struct EDBMSelectID_Context *sel_id_ctx = MEM_mallocN(sizeof(*sel_id_ctx), __func__);
+ sel_id_ctx->base_array_index_offsets = MEM_mallocN(sizeof(struct EDBMBaseOffset) * bases_len,
+ __func__);
+ sel_id_ctx->bases = bases;
+ sel_id_ctx->bases_len = bases_len;
- MEM_freeN(buf);
- return true;
+ edbm_select_pick_draw_bases(sel_id_ctx, vc, select_mode);
+
+ return sel_id_ctx;
+}
+
+void EDBM_select_id_context_destroy(struct EDBMSelectID_Context *sel_id_ctx)
+{
+ MEM_freeN(sel_id_ctx->base_array_index_offsets);
+ MEM_freeN(sel_id_ctx);
}
/** \} */
@@ -470,29 +458,44 @@ static void findnearestvert__doClosest(void *userData,
BMVert *EDBM_vert_find_nearest_ex(ViewContext *vc,
float *r_dist,
const bool use_select_bias,
- bool use_cycle)
+ bool use_cycle,
+ Base **bases,
+ uint bases_len,
+ uint *r_base_index)
{
- BMesh *bm = vc->em->bm;
+ uint base_index = 0;
if (!XRAY_FLAG_ENABLED(vc->v3d)) {
uint dist_px = (uint)ED_view3d_backbuf_sample_size_clamp(vc->ar, *r_dist);
- unsigned int index;
+ uint index;
BMVert *eve;
/* No afterqueue (yet), so we check it now, otherwise the bm_xxxofs indices are bad. */
{
- FAKE_SELECT_MODE_BEGIN (vc, fake_select_mode, select_mode, SCE_SELECT_VERTEX)
- ;
- ED_view3d_select_id_validate_with_select_mode(vc, select_mode);
+ FAKE_SELECT_MODE_BEGIN(vc, fake_select_mode, select_mode, SCE_SELECT_VERTEX);
+
+ struct EDBMSelectID_Context *sel_id_ctx = EDBM_select_id_context_create(
+ vc, bases, bases_len, select_mode);
+
+ 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);
+ }
+ else {
+ eve = NULL;
+ }
- index = ED_view3d_select_id_read_nearest(vc, vc->mval, bm_wireoffs, 0xFFFFFF, &dist_px);
- eve = index ? BM_vert_at_index_find_or_table(bm, index - 1) : NULL;
+ EDBM_select_id_context_destroy(sel_id_ctx);
FAKE_SELECT_MODE_END(vc, fake_select_mode);
}
if (eve) {
if (dist_px < *r_dist) {
+ if (r_base_index) {
+ *r_base_index = base_index;
+ }
*r_dist = dist_px;
return eve;
}
@@ -503,32 +506,52 @@ BMVert *EDBM_vert_find_nearest_ex(ViewContext *vc,
struct NearestVertUserData data = {{0}};
const struct NearestVertUserData_Hit *hit;
const eV3DProjTest clip_flag = V3D_PROJ_TEST_CLIP_DEFAULT;
+ BMesh *prev_select_bm = NULL;
- static int prev_select_index = 0;
- static const BMVert *prev_select_elem = NULL;
-
- if ((use_cycle == false) ||
- (prev_select_elem &&
- (prev_select_elem != BM_vert_at_index_find_or_table(bm, prev_select_index)))) {
- prev_select_index = 0;
- prev_select_elem = NULL;
- }
+ static struct {
+ int index;
+ const BMVert *elem;
+ const BMesh *bm;
+ } prev_select = {0};
data.mval_fl[0] = vc->mval[0];
data.mval_fl[1] = vc->mval[1];
data.use_select_bias = use_select_bias;
data.use_cycle = use_cycle;
- data.hit.dist = data.hit_cycle.dist = data.hit.dist_bias = data.hit_cycle.dist_bias = *r_dist;
- data.cycle_index_prev = prev_select_index;
- ED_view3d_init_mats_rv3d(vc->obedit, vc->rv3d);
- mesh_foreachScreenVert(vc, findnearestvert__doClosest, &data, clip_flag);
+ for (; base_index < bases_len; base_index++) {
+ Base *base_iter = bases[base_index];
+ ED_view3d_viewcontext_init_object(vc, base_iter->object);
+ if (use_cycle && prev_select.bm == vc->em->bm &&
+ prev_select.elem == BM_vert_at_index_find_or_table(vc->em->bm, prev_select.index)) {
+ data.cycle_index_prev = prev_select.index;
+ /* No need to compare in the rest of the loop. */
+ use_cycle = false;
+ }
+ else {
+ data.cycle_index_prev = 0;
+ }
- hit = (data.use_cycle && data.hit_cycle.vert) ? &data.hit_cycle : &data.hit;
- *r_dist = hit->dist;
+ data.hit.dist = data.hit_cycle.dist = data.hit.dist_bias = data.hit_cycle.dist_bias =
+ *r_dist;
- prev_select_elem = hit->vert;
- prev_select_index = hit->index;
+ ED_view3d_init_mats_rv3d(vc->obedit, vc->rv3d);
+ mesh_foreachScreenVert(vc, findnearestvert__doClosest, &data, clip_flag);
+
+ hit = (data.use_cycle && data.hit_cycle.vert) ? &data.hit_cycle : &data.hit;
+
+ if (hit->dist < *r_dist) {
+ if (r_base_index) {
+ *r_base_index = base_index;
+ }
+ *r_dist = hit->dist;
+ prev_select_bm = vc->em->bm;
+ }
+ }
+
+ prev_select.index = hit->index;
+ prev_select.elem = hit->vert;
+ prev_select.bm = prev_select_bm;
return hit->vert;
}
@@ -536,7 +559,8 @@ BMVert *EDBM_vert_find_nearest_ex(ViewContext *vc,
BMVert *EDBM_vert_find_nearest(ViewContext *vc, float *r_dist)
{
- return EDBM_vert_find_nearest_ex(vc, r_dist, false, false);
+ Base *base = BKE_view_layer_base_find(vc->view_layer, vc->obact);
+ return EDBM_vert_find_nearest_ex(vc, r_dist, false, false, &base, 1, NULL);
}
/* find the distance to the edge we already have */
@@ -658,24 +682,36 @@ BMEdge *EDBM_edge_find_nearest_ex(ViewContext *vc,
float *r_dist,
float *r_dist_center,
const bool use_select_bias,
- const bool use_cycle,
- BMEdge **r_eed_zbuf)
+ bool use_cycle,
+ BMEdge **r_eed_zbuf,
+ Base **bases,
+ uint bases_len,
+ uint *r_base_index)
{
- BMesh *bm = vc->em->bm;
+ uint base_index = 0;
if (!XRAY_FLAG_ENABLED(vc->v3d)) {
uint dist_px = (uint)ED_view3d_backbuf_sample_size_clamp(vc->ar, *r_dist);
- unsigned int index;
+ uint index;
BMEdge *eed;
/* No afterqueue (yet), so we check it now, otherwise the bm_xxxofs indices are bad. */
{
- FAKE_SELECT_MODE_BEGIN (vc, fake_select_mode, select_mode, SCE_SELECT_EDGE)
- ;
- ED_view3d_select_id_validate_with_select_mode(vc, select_mode);
+ FAKE_SELECT_MODE_BEGIN(vc, fake_select_mode, select_mode, SCE_SELECT_EDGE);
+
+ struct EDBMSelectID_Context *sel_id_ctx = EDBM_select_id_context_create(
+ vc, bases, bases_len, select_mode);
+
+ 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);
+ }
+ else {
+ eed = NULL;
+ }
- index = ED_view3d_select_id_read_nearest(vc, vc->mval, bm_solidoffs, bm_wireoffs, &dist_px);
- eed = index ? BM_edge_at_index_find_or_table(bm, index - 1) : NULL;
+ EDBM_select_id_context_destroy(sel_id_ctx);
FAKE_SELECT_MODE_END(vc, fake_select_mode);
}
@@ -704,6 +740,9 @@ BMEdge *EDBM_edge_find_nearest_ex(ViewContext *vc,
if (eed) {
if (dist_px < *r_dist) {
+ if (r_base_index) {
+ *r_base_index = base_index;
+ }
*r_dist = dist_px;
return eed;
}
@@ -715,36 +754,57 @@ BMEdge *EDBM_edge_find_nearest_ex(ViewContext *vc,
const struct NearestEdgeUserData_Hit *hit;
/* 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;
- static int prev_select_index = 0;
- static const BMEdge *prev_select_elem = NULL;
-
- if ((use_cycle == false) ||
- (prev_select_elem &&
- (prev_select_elem != BM_edge_at_index_find_or_table(bm, prev_select_index)))) {
- prev_select_index = 0;
- prev_select_elem = NULL;
- }
+ static struct {
+ int index;
+ const BMEdge *elem;
+ const BMesh *bm;
+ } prev_select = {0};
data.vc = *vc;
data.mval_fl[0] = vc->mval[0];
data.mval_fl[1] = vc->mval[1];
data.use_select_bias = use_select_bias;
data.use_cycle = use_cycle;
- data.hit.dist = data.hit_cycle.dist = data.hit.dist_bias = data.hit_cycle.dist_bias = *r_dist;
- data.cycle_index_prev = prev_select_index;
- ED_view3d_init_mats_rv3d(vc->obedit, vc->rv3d);
- mesh_foreachScreenEdge(vc, find_nearest_edge__doClosest, &data, clip_flag);
+ for (; base_index < bases_len; base_index++) {
+ Base *base_iter = bases[base_index];
+ ED_view3d_viewcontext_init_object(vc, base_iter->object);
+ if (use_cycle && prev_select.bm == vc->em->bm &&
+ prev_select.elem == BM_edge_at_index_find_or_table(vc->em->bm, prev_select.index)) {
+ data.cycle_index_prev = prev_select.index;
+ /* No need to compare in the rest of the loop. */
+ use_cycle = false;
+ }
+ else {
+ data.cycle_index_prev = 0;
+ }
+
+ data.hit.dist = data.hit_cycle.dist = data.hit.dist_bias = data.hit_cycle.dist_bias =
+ *r_dist;
+
+ ED_view3d_init_mats_rv3d(vc->obedit, vc->rv3d);
+ mesh_foreachScreenEdge(vc, find_nearest_edge__doClosest, &data, clip_flag);
+
+ hit = (data.use_cycle && data.hit_cycle.edge) ? &data.hit_cycle : &data.hit;
+
+ if (hit->dist < *r_dist) {
+ if (r_base_index) {
+ *r_base_index = base_index;
+ }
+ *r_dist = hit->dist;
+ prev_select_bm = vc->em->bm;
+ }
+ }
- hit = (data.use_cycle && data.hit_cycle.edge) ? &data.hit_cycle : &data.hit;
- *r_dist = hit->dist;
if (r_dist_center) {
*r_dist_center = hit->dist_center;
}
- prev_select_elem = hit->edge;
- prev_select_index = hit->index;
+ prev_select.index = hit->index;
+ prev_select.elem = hit->edge;
+ prev_select.bm = prev_select_bm;
return hit->edge;
}
@@ -752,7 +812,8 @@ BMEdge *EDBM_edge_find_nearest_ex(ViewContext *vc,
BMEdge *EDBM_edge_find_nearest(ViewContext *vc, float *r_dist)
{
- return EDBM_edge_find_nearest_ex(vc, r_dist, NULL, false, false, NULL);
+ Base *base = BKE_view_layer_base_find(vc->view_layer, vc->obact);
+ return EDBM_edge_find_nearest_ex(vc, r_dist, NULL, false, false, NULL, &base, 1, NULL);
}
/* find the distance to the face we already have */
@@ -831,23 +892,35 @@ BMFace *EDBM_face_find_nearest_ex(ViewContext *vc,
float *r_dist,
float *r_dist_center,
const bool use_select_bias,
- const bool use_cycle,
- BMFace **r_efa_zbuf)
+ bool use_cycle,
+ BMFace **r_efa_zbuf,
+ Base **bases,
+ uint bases_len,
+ uint *r_base_index)
{
- BMesh *bm = vc->em->bm;
+ uint base_index = 0;
if (!XRAY_FLAG_ENABLED(vc->v3d)) {
float dist_test = 0.0f;
- unsigned int index;
+ uint index;
BMFace *efa;
{
- FAKE_SELECT_MODE_BEGIN (vc, fake_select_mode, select_mode, SCE_SELECT_FACE)
- ;
- ED_view3d_select_id_validate_with_select_mode(vc, select_mode);
+ FAKE_SELECT_MODE_BEGIN(vc, fake_select_mode, select_mode, SCE_SELECT_FACE);
+
+ struct EDBMSelectID_Context *sel_id_ctx = EDBM_select_id_context_create(
+ vc, bases, bases_len, select_mode);
+
+ index = ED_select_buffer_sample_point(vc->mval);
+
+ if (index) {
+ efa = (BMFace *)EDBM_select_id_bm_elem_get(sel_id_ctx, index, &base_index);
+ }
+ else {
+ efa = NULL;
+ }
- index = ED_view3d_select_id_sample(vc, vc->mval[0], vc->mval[1]);
- efa = index ? BM_face_at_index_find_or_table(bm, index - 1) : NULL;
+ EDBM_select_id_context_destroy(sel_id_ctx);
FAKE_SELECT_MODE_END(vc, fake_select_mode);
}
@@ -876,6 +949,9 @@ BMFace *EDBM_face_find_nearest_ex(ViewContext *vc,
if (efa) {
if (dist_test < *r_dist) {
+ if (r_base_index) {
+ *r_base_index = base_index;
+ }
*r_dist = dist_test;
return efa;
}
@@ -886,35 +962,56 @@ BMFace *EDBM_face_find_nearest_ex(ViewContext *vc,
struct NearestFaceUserData data = {{0}};
const struct NearestFaceUserData_Hit *hit;
const eV3DProjTest clip_flag = V3D_PROJ_TEST_CLIP_DEFAULT;
+ BMesh *prev_select_bm = NULL;
- static int prev_select_index = 0;
- static const BMFace *prev_select_elem = NULL;
-
- if ((use_cycle == false) ||
- (prev_select_elem &&
- (prev_select_elem != BM_face_at_index_find_or_table(bm, prev_select_index)))) {
- prev_select_index = 0;
- prev_select_elem = NULL;
- }
+ static struct {
+ int index;
+ const BMFace *elem;
+ const BMesh *bm;
+ } prev_select = {0};
data.mval_fl[0] = vc->mval[0];
data.mval_fl[1] = vc->mval[1];
data.use_select_bias = use_select_bias;
data.use_cycle = use_cycle;
- data.hit.dist = data.hit_cycle.dist = data.hit.dist_bias = data.hit_cycle.dist_bias = *r_dist;
- data.cycle_index_prev = prev_select_index;
- ED_view3d_init_mats_rv3d(vc->obedit, vc->rv3d);
- mesh_foreachScreenFace(vc, findnearestface__doClosest, &data, clip_flag);
+ for (; base_index < bases_len; base_index++) {
+ Base *base_iter = bases[base_index];
+ ED_view3d_viewcontext_init_object(vc, base_iter->object);
+ if (use_cycle && prev_select.bm == vc->em->bm &&
+ prev_select.elem == BM_face_at_index_find_or_table(vc->em->bm, prev_select.index)) {
+ data.cycle_index_prev = prev_select.index;
+ /* No need to compare in the rest of the loop. */
+ use_cycle = false;
+ }
+ else {
+ data.cycle_index_prev = 0;
+ }
+
+ data.hit.dist = data.hit_cycle.dist = data.hit.dist_bias = data.hit_cycle.dist_bias =
+ *r_dist;
+
+ ED_view3d_init_mats_rv3d(vc->obedit, vc->rv3d);
+ mesh_foreachScreenFace(vc, findnearestface__doClosest, &data, clip_flag);
+
+ hit = (data.use_cycle && data.hit_cycle.face) ? &data.hit_cycle : &data.hit;
+
+ if (hit->dist < *r_dist) {
+ if (r_base_index) {
+ *r_base_index = base_index;
+ }
+ *r_dist = hit->dist;
+ prev_select_bm = vc->em->bm;
+ }
+ }
- hit = (data.use_cycle && data.hit_cycle.face) ? &data.hit_cycle : &data.hit;
- *r_dist = hit->dist;
if (r_dist_center) {
*r_dist_center = hit->dist;
}
- prev_select_elem = hit->face;
- prev_select_index = hit->index;
+ prev_select.index = hit->index;
+ prev_select.elem = hit->face;
+ prev_select.bm = prev_select_bm;
return hit->face;
}
@@ -922,7 +1019,8 @@ BMFace *EDBM_face_find_nearest_ex(ViewContext *vc,
BMFace *EDBM_face_find_nearest(ViewContext *vc, float *r_dist)
{
- return EDBM_face_find_nearest_ex(vc, r_dist, NULL, false, false, NULL);
+ Base *base = BKE_view_layer_base_find(vc->view_layer, vc->obact);
+ return EDBM_face_find_nearest_ex(vc, r_dist, NULL, false, false, NULL, &base, 1, NULL);
}
#undef FIND_NEAR_SELECT_BIAS
@@ -965,75 +1063,63 @@ static bool unified_findnearest(ViewContext *vc,
} f, f_zbuf;
} hit = {{NULL}};
- /* TODO(campbell): perform selection as one pass
- * instead of many smaller passes (which doesn't work for zbuf occlusion). */
-
/* no afterqueue (yet), so we check it now, otherwise the em_xxxofs indices are bad */
- if ((dist > 0.0f) && em->selectmode & SCE_SELECT_FACE) {
+ if ((dist > 0.0f) && (em->selectmode & SCE_SELECT_FACE)) {
float dist_center = 0.0f;
float *dist_center_p = (em->selectmode & (SCE_SELECT_EDGE | SCE_SELECT_VERTEX)) ?
&dist_center :
NULL;
- for (uint base_index = 0; base_index < bases_len; base_index++) {
- Base *base_iter = bases[base_index];
- Object *obedit = base_iter->object;
- ED_view3d_viewcontext_init_object(vc, obedit);
- BLI_assert(vc->em->selectmode == em->selectmode);
- BMFace *efa_zbuf = NULL;
- BMFace *efa_test = EDBM_face_find_nearest_ex(
- vc, &dist, dist_center_p, true, use_cycle, &efa_zbuf);
- if (efa_test && dist_center_p) {
- dist = min_ff(dist_margin, dist_center);
- }
- if (efa_test) {
- hit.f.base_index = base_index;
- hit.f.ele = efa_test;
- }
- if (efa_zbuf) {
- hit.f_zbuf.base_index = base_index;
- hit.f_zbuf.ele = efa_zbuf;
- }
- } /* bases */
+ uint base_index = 0;
+ BMFace *efa_zbuf = NULL;
+ BMFace *efa_test = EDBM_face_find_nearest_ex(
+ vc, &dist, dist_center_p, true, use_cycle, &efa_zbuf, bases, bases_len, &base_index);
+
+ if (efa_test && dist_center_p) {
+ dist = min_ff(dist_margin, dist_center);
+ }
+ if (efa_test) {
+ hit.f.base_index = base_index;
+ hit.f.ele = efa_test;
+ }
+ if (efa_zbuf) {
+ hit.f_zbuf.base_index = base_index;
+ hit.f_zbuf.ele = efa_zbuf;
+ }
}
if ((dist > 0.0f) && (em->selectmode & SCE_SELECT_EDGE)) {
float dist_center = 0.0f;
float *dist_center_p = (em->selectmode & SCE_SELECT_VERTEX) ? &dist_center : NULL;
- for (uint base_index = 0; base_index < bases_len; base_index++) {
- Base *base_iter = bases[base_index];
- Object *obedit = base_iter->object;
- ED_view3d_viewcontext_init_object(vc, obedit);
- BMEdge *eed_zbuf = NULL;
- BMEdge *eed_test = EDBM_edge_find_nearest_ex(
- vc, &dist, dist_center_p, true, use_cycle, &eed_zbuf);
- if (eed_test && dist_center_p) {
- dist = min_ff(dist_margin, dist_center);
- }
- if (eed_test) {
- hit.e.base_index = base_index;
- hit.e.ele = eed_test;
- }
- if (eed_zbuf) {
- hit.e_zbuf.base_index = base_index;
- hit.e_zbuf.ele = eed_zbuf;
- }
- } /* bases */
+ uint base_index = 0;
+ BMEdge *eed_zbuf = NULL;
+ BMEdge *eed_test = EDBM_edge_find_nearest_ex(
+ vc, &dist, dist_center_p, true, use_cycle, &eed_zbuf, bases, bases_len, &base_index);
+
+ if (eed_test && dist_center_p) {
+ dist = min_ff(dist_margin, dist_center);
+ }
+ if (eed_test) {
+ hit.e.base_index = base_index;
+ hit.e.ele = eed_test;
+ }
+ if (eed_zbuf) {
+ hit.e_zbuf.base_index = base_index;
+ hit.e_zbuf.ele = eed_zbuf;
+ }
}
- if ((dist > 0.0f) && em->selectmode & SCE_SELECT_VERTEX) {
- for (uint base_index = 0; base_index < bases_len; base_index++) {
- Base *base_iter = bases[base_index];
- Object *obedit = base_iter->object;
- ED_view3d_viewcontext_init_object(vc, obedit);
- BMVert *eve_test = EDBM_vert_find_nearest_ex(vc, &dist, true, use_cycle);
- if (eve_test) {
- hit.v.base_index = base_index;
- hit.v.ele = eve_test;
- }
- } /* bases */
+ if ((dist > 0.0f) && (em->selectmode & SCE_SELECT_VERTEX)) {
+ uint base_index = 0;
+ BMVert *eve_test = EDBM_vert_find_nearest_ex(
+ vc, &dist, true, use_cycle, bases, bases_len, &base_index);
+
+ if (eve_test) {
+ hit.v.base_index = base_index;
+ hit.v.ele = eve_test;
+ }
}
/* return only one of 3 pointers, for frontbuffer redraws */
diff --git a/source/blender/editors/mesh/editmesh_tools.c b/source/blender/editors/mesh/editmesh_tools.c
index cd9d046ae04..a1ebcff31aa 100644
--- a/source/blender/editors/mesh/editmesh_tools.c
+++ b/source/blender/editors/mesh/editmesh_tools.c
@@ -336,6 +336,7 @@ void MESH_OT_subdivide_edgering(wmOperatorType *ot)
{
/* identifiers */
ot->name = "Subdivide Edge-Ring";
+ ot->description = "Subdivide perpendicular edges to the selected edge ring";
ot->idname = "MESH_OT_subdivide_edgering";
/* api callbacks */
@@ -1123,7 +1124,7 @@ static int edbm_mark_sharp_exec(bContext *C, wmOperator *op)
BMEditMesh *em = BKE_editmesh_from_object(obedit);
BMesh *bm = em->bm;
- if (bm->totedgesel == 0) {
+ if ((use_verts && bm->totvertsel == 0) || (!use_verts && bm->totedgesel == 0)) {
continue;
}
@@ -6793,7 +6794,7 @@ void MESH_OT_bridge_edge_loops(wmOperatorType *ot)
/* identifiers */
ot->name = "Bridge Edge Loops";
- ot->description = "Make faces between two or more edge loops";
+ ot->description = "Create a bridge of faces between two or more selected edge loops";
ot->idname = "MESH_OT_bridge_edge_loops";
/* api callbacks */
@@ -7686,6 +7687,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);
@@ -8075,7 +8077,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;
@@ -8241,6 +8243,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;
@@ -8286,7 +8289,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;
@@ -8306,7 +8309,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;
@@ -8344,6 +8347,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);
@@ -8504,7 +8508,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 */
@@ -8567,6 +8571,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;
@@ -8723,7 +8728,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 */
@@ -8763,6 +8768,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__);
@@ -8828,6 +8834,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;
}
@@ -8841,7 +8848,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;
@@ -8858,6 +8865,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);
@@ -8933,7 +8941,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;
@@ -8953,7 +8961,6 @@ void MESH_OT_smoothen_normals(struct wmOperatorType *ot)
static int edbm_mod_weighted_strength_exec(bContext *C, wmOperator *op)
{
- Scene *scene = CTX_data_scene(C);
Object *obedit = CTX_data_edit_object(C);
BMEditMesh *em = BKE_editmesh_from_object(obedit);
BMesh *bm = em->bm;
@@ -8972,7 +8979,7 @@ static int edbm_mod_weighted_strength_exec(bContext *C, wmOperator *op)
const int cd_prop_int_offset = CustomData_get_n_offset(
&bm->pdata, CD_PROP_INT, cd_prop_int_index);
- const int face_strength = scene->toolsettings->face_strength;
+ const int face_strength = RNA_enum_get(op->ptr, "face_strength");
const bool set = RNA_boolean_get(op->ptr, "set");
BM_mesh_elem_index_ensure(bm, BM_FACE);
@@ -9001,6 +9008,13 @@ static int edbm_mod_weighted_strength_exec(bContext *C, wmOperator *op)
return OPERATOR_FINISHED;
}
+static const EnumPropertyItem prop_mesh_face_strength_types[] = {
+ {FACE_STRENGTH_WEAK, "WEAK", 0, "Weak", ""},
+ {FACE_STRENGTH_MEDIUM, "MEDIUM", 0, "Medium", ""},
+ {FACE_STRENGTH_STRONG, "STRONG", 0, "Strong", ""},
+ {0, NULL, 0, NULL, NULL},
+};
+
void MESH_OT_mod_weighted_strength(struct wmOperatorType *ot)
{
/* identifiers */
@@ -9010,11 +9024,18 @@ 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;
ot->prop = RNA_def_boolean(ot->srna, "set", 0, "Set value", "Set Value of faces");
- RNA_def_property_flag(ot->prop, PROP_HIDDEN);
+
+ ot->prop = RNA_def_enum(
+ ot->srna,
+ "face_strength",
+ prop_mesh_face_strength_types,
+ FACE_STRENGTH_MEDIUM,
+ "Face Strength",
+ "Strength to use for assigning or selecting face influence for weighted normal modifier");
}
diff --git a/source/blender/editors/mesh/mesh_ops.c b/source/blender/editors/mesh/mesh_ops.c
index ed5e6c39f85..102ce3efc22 100644
--- a/source/blender/editors/mesh/mesh_ops.c
+++ b/source/blender/editors/mesh/mesh_ops.c
@@ -274,7 +274,7 @@ void ED_operatormacros_mesh(void)
ot = WM_operatortype_append_macro("MESH_OT_extrude_context_move",
"Extrude Region and Move",
- "Extrude context and move result",
+ "Extrude region together along the average normal",
OPTYPE_UNDO | OPTYPE_REGISTER);
otmacro = WM_operatortype_macro_define(ot, "MESH_OT_extrude_context");
otmacro = WM_operatortype_macro_define(ot, "TRANSFORM_OT_translate");
@@ -283,7 +283,7 @@ void ED_operatormacros_mesh(void)
ot = WM_operatortype_append_macro("MESH_OT_extrude_region_shrink_fatten",
"Extrude Region and Shrink/Fatten",
- "Extrude along normals and move result",
+ "Extrude region together along local normals",
OPTYPE_UNDO | OPTYPE_REGISTER);
otmacro = WM_operatortype_macro_define(ot, "MESH_OT_extrude_region");
otmacro = WM_operatortype_macro_define(ot, "TRANSFORM_OT_shrink_fatten");
@@ -292,7 +292,7 @@ void ED_operatormacros_mesh(void)
ot = WM_operatortype_append_macro("MESH_OT_extrude_faces_move",
"Extrude Individual Faces and Move",
- "Extrude faces and move result",
+ "Extrude each individual face separately along local normals",
OPTYPE_UNDO | OPTYPE_REGISTER);
otmacro = WM_operatortype_macro_define(ot, "MESH_OT_extrude_faces_indiv");
otmacro = WM_operatortype_macro_define(ot, "TRANSFORM_OT_shrink_fatten");
diff --git a/source/blender/editors/mesh/meshtools.c b/source/blender/editors/mesh/meshtools.c
index c32fef42d27..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"
@@ -1109,18 +1110,16 @@ bool ED_mesh_pick_face(bContext *C, Object *ob, const int mval[2], uint dist_px,
}
ED_view3d_viewcontext_init(C, &vc);
+ ED_view3d_select_id_validate(&vc);
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 */
-
- ED_view3d_select_id_validate(&vc);
-
- *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) {
@@ -1291,19 +1290,17 @@ bool ED_mesh_pick_vert(
}
ED_view3d_viewcontext_init(C, &vc);
+ ED_view3d_select_id_validate(&vc);
if (use_zbuf) {
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 */
-
- ED_view3d_select_id_validate(&vc);
-
- *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/metaball/mball_edit.c b/source/blender/editors/metaball/mball_edit.c
index 54143822b61..18ff7ae1a5e 100644
--- a/source/blender/editors/metaball/mball_edit.c
+++ b/source/blender/editors/metaball/mball_edit.c
@@ -738,7 +738,7 @@ bool ED_mball_select_pick(bContext *C, const int mval[2], bool extend, bool dese
}
const uint hit_object = hitresult & 0xFFFF;
- if (vc.obedit->select_id != hit_object) {
+ if (vc.obedit->runtime.select_id != hit_object) {
continue;
}
diff --git a/source/blender/editors/object/object_add.c b/source/blender/editors/object/object_add.c
index f8a13579732..cb152cb4e49 100644
--- a/source/blender/editors/object/object_add.c
+++ b/source/blender/editors/object/object_add.c
@@ -113,6 +113,10 @@
#include "object_intern.h"
+/* -------------------------------------------------------------------- */
+/** \name Local Enum Declarations
+ * \{ */
+
/* this is an exact copy of the define in rna_light.c
* kept here because of linking order.
* Icons are only defined here */
@@ -161,7 +165,25 @@ static EnumPropertyItem lightprobe_type_items[] = {
{0, NULL, 0, NULL, NULL},
};
-/************************** Exported *****************************/
+enum {
+ ALIGN_WORLD = 0,
+ ALIGN_VIEW,
+ ALIGN_CURSOR,
+};
+
+static const EnumPropertyItem align_options[] = {
+ {ALIGN_WORLD, "WORLD", 0, "World", "Align the new object to the world"},
+ {ALIGN_VIEW, "VIEW", 0, "View", "Align the new object to the view"},
+ {ALIGN_CURSOR, "CURSOR", 0, "3D Cursor", "Use the 3D cursor orientation for the new object"},
+ {0, NULL, 0, NULL, NULL},
+};
+
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Public Add Object API
+ *
+ * \{ */
void ED_object_location_from_view(bContext *C, float loc[3])
{
@@ -266,7 +288,11 @@ float ED_object_new_primitive_matrix(
// return 1.0f;
}
-/********************* Add Object Operator ********************/
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Add Object Operator
+ * \{ */
static void view_align_update(struct Main *UNUSED(main),
struct Scene *UNUSED(scene),
@@ -291,16 +317,15 @@ void ED_object_add_generic_props(wmOperatorType *ot, bool do_editmode)
{
PropertyRNA *prop;
- /* note: this property gets hidden for add-camera operator */
- prop = RNA_def_boolean(
- ot->srna, "view_align", 0, "Align to View", "Align the new object to the view");
- RNA_def_property_update_runtime(prop, view_align_update);
-
if (do_editmode) {
prop = RNA_def_boolean(
ot->srna, "enter_editmode", 0, "Enter Editmode", "Enter editmode when adding this object");
RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE);
}
+ /* note: this property gets hidden for add-camera operator */
+ prop = RNA_def_enum(
+ ot->srna, "align", align_options, ALIGN_WORLD, "Align", "The alignment of the new object");
+ RNA_def_property_update_runtime(prop, view_align_update);
prop = RNA_def_float_vector_xyz(ot->srna,
"location",
@@ -392,23 +417,44 @@ bool ED_object_add_generic_get_opts(bContext *C,
rot = _rot;
}
+ prop = RNA_struct_find_property(op->ptr, "align");
+ int alignment = RNA_property_enum_get(op->ptr, prop);
+ bool alignment_set = RNA_property_is_set(op->ptr, prop);
+
if (RNA_struct_property_is_set(op->ptr, "rotation")) {
*is_view_aligned = false;
}
- else if (RNA_struct_property_is_set(op->ptr, "view_align")) {
- *is_view_aligned = RNA_boolean_get(op->ptr, "view_align");
+ else if (alignment_set) {
+ *is_view_aligned = alignment == ALIGN_VIEW;
}
else {
*is_view_aligned = (U.flag & USER_ADD_VIEWALIGNED) != 0;
- RNA_boolean_set(op->ptr, "view_align", *is_view_aligned);
+ if (*is_view_aligned) {
+ RNA_property_enum_set(op->ptr, prop, ALIGN_VIEW);
+ alignment = ALIGN_VIEW;
+ }
+ else if (U.flag & USER_ADD_CURSORALIGNED) {
+ RNA_property_enum_set(op->ptr, prop, ALIGN_CURSOR);
+ alignment = ALIGN_CURSOR;
+ }
}
- if (*is_view_aligned) {
- ED_object_rotation_from_view(C, rot, view_align_axis);
- RNA_float_set_array(op->ptr, "rotation", rot);
- }
- else {
- RNA_float_get_array(op->ptr, "rotation", rot);
+ switch (alignment) {
+ case ALIGN_WORLD:
+ RNA_float_get_array(op->ptr, "rotation", rot);
+ break;
+ case ALIGN_VIEW:
+ ED_object_rotation_from_view(C, rot, view_align_axis);
+ RNA_float_set_array(op->ptr, "rotation", rot);
+ break;
+ case ALIGN_CURSOR: {
+ const Scene *scene = CTX_data_scene(C);
+ float tmat[3][3];
+ BKE_scene_cursor_rot_to_mat3(&scene->cursor, tmat);
+ mat3_normalized_to_eul(rot, tmat);
+ RNA_float_set_array(op->ptr, "rotation", rot);
+ break;
+ }
}
}
@@ -516,7 +562,11 @@ void OBJECT_OT_add(wmOperatorType *ot)
ED_object_add_generic_props(ot, true);
}
-/********************** Add Probe Operator **********************/
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Add Probe Operator
+ * \{ */
/* for object add operator */
static const char *get_lightprobe_defname(int type)
@@ -604,7 +654,11 @@ void OBJECT_OT_lightprobe_add(wmOperatorType *ot)
ED_object_add_generic_props(ot, true);
}
-/********************* Add Effector Operator ********************/
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Add Effector Operator
+ * \{ */
/* for object add operator */
static int effector_add_exec(bContext *C, wmOperator *op)
@@ -677,7 +731,11 @@ void OBJECT_OT_effector_add(wmOperatorType *ot)
ED_object_add_generic_props(ot, true);
}
-/********************* Add Camera Operator ********************/
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Add Camera Operator
+ * \{ */
static int object_camera_add_exec(bContext *C, wmOperator *op)
{
@@ -690,7 +748,7 @@ static int object_camera_add_exec(bContext *C, wmOperator *op)
float loc[3], rot[3];
/* force view align for cameras */
- RNA_boolean_set(op->ptr, "view_align", true);
+ RNA_enum_set(op->ptr, "align", ALIGN_VIEW);
if (!ED_object_add_generic_get_opts(
C, op, 'Z', loc, rot, &enter_editmode, &local_view_bits, NULL)) {
@@ -732,11 +790,15 @@ void OBJECT_OT_camera_add(wmOperatorType *ot)
ED_object_add_generic_props(ot, true);
/* hide this for cameras, default */
- prop = RNA_struct_type_find_property(ot->srna, "view_align");
+ prop = RNA_struct_type_find_property(ot->srna, "align");
RNA_def_property_flag(prop, PROP_HIDDEN);
}
-/********************* Add Metaball Operator ********************/
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Add Metaball Operator
+ * \{ */
static int object_metaball_add_exec(bContext *C, wmOperator *op)
{
@@ -797,7 +859,11 @@ void OBJECT_OT_metaball_add(wmOperatorType *ot)
ED_object_add_generic_props(ot, true);
}
-/********************* Add Text Operator ********************/
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Add Text Operator
+ * \{ */
static int object_add_text_exec(bContext *C, wmOperator *op)
{
@@ -842,7 +908,11 @@ void OBJECT_OT_text_add(wmOperatorType *ot)
ED_object_add_generic_props(ot, true);
}
-/********************* Add Armature Operator ********************/
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Add Armature Operator
+ * \{ */
static int object_armature_add_exec(bContext *C, wmOperator *op)
{
@@ -905,7 +975,11 @@ void OBJECT_OT_armature_add(wmOperatorType *ot)
ED_object_add_generic_props(ot, true);
}
-/********************* Add Empty Operator ********************/
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Add Empty Operator
+ * \{ */
static int object_empty_add_exec(bContext *C, wmOperator *op)
{
@@ -1025,7 +1099,12 @@ void OBJECT_OT_drop_named_image(wmOperatorType *ot)
ED_object_add_generic_props(ot, false);
}
-/********************* Add Gpencil Operator ********************/
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Add Gpencil Operator
+ * \{ */
+
static bool object_gpencil_add_poll(bContext *C)
{
Scene *scene = CTX_data_scene(C);
@@ -1156,7 +1235,11 @@ void OBJECT_OT_gpencil_add(wmOperatorType *ot)
ot->prop = RNA_def_enum(ot->srna, "type", rna_enum_object_gpencil_type_items, 0, "Type", "");
}
-/********************* Add Light Operator ********************/
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Add Light Operator
+ * \{ */
static const char *get_light_defname(int type)
{
@@ -1176,7 +1259,6 @@ static const char *get_light_defname(int type)
static int object_light_add_exec(bContext *C, wmOperator *op)
{
- Scene *scene = CTX_data_scene(C);
Object *ob;
Light *la;
int type = RNA_enum_get(op->ptr, "type");
@@ -1207,9 +1289,8 @@ static int object_light_add_exec(bContext *C, wmOperator *op)
la = (Light *)ob->data;
la->type = type;
- if (BKE_scene_uses_cycles(scene)) {
- ED_node_shader_default(C, &la->id);
- la->use_nodes = true;
+ if (type == LA_SUN) {
+ la->energy = 1.0f;
}
return OPERATOR_FINISHED;
@@ -1238,7 +1319,11 @@ void OBJECT_OT_light_add(wmOperatorType *ot)
ED_object_add_generic_props(ot, false);
}
-/********************* Add Collection Instance Operator ********************/
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Add Collection Instance Operator
+ * \{ */
static int collection_instance_add_exec(bContext *C, wmOperator *op)
{
@@ -1324,7 +1409,11 @@ void OBJECT_OT_collection_instance_add(wmOperatorType *ot)
ED_object_add_generic_props(ot, false);
}
-/********************* Add Speaker Operator ********************/
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Add Speaker Operator
+ * \{ */
static int object_speaker_add_exec(bContext *C, wmOperator *op)
{
@@ -1379,7 +1468,11 @@ void OBJECT_OT_speaker_add(wmOperatorType *ot)
ED_object_add_generic_props(ot, true);
}
-/**************************** Delete Object *************************/
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Delete Object Operator
+ * \{ */
/* remove base from a specific scene */
/* note: now unlinks constraints as well */
@@ -1537,7 +1630,11 @@ void OBJECT_OT_delete(wmOperatorType *ot)
WM_operator_properties_confirm_or_exec(ot);
}
-/**************************** Copy Utilities ******************************/
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Copy Object Utilities
+ * \{ */
/* after copying objects, copied data should get new pointers */
static void copy_object_set_idnew(bContext *C)
@@ -1552,7 +1649,11 @@ static void copy_object_set_idnew(bContext *C)
BKE_main_id_clear_newpoins(bmain);
}
-/********************* Make Duplicates Real ************************/
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Make Instanced Objects Real Operator
+ * \{ */
/**
* \note regarding hashing dupli-objects when using OB_DUPLICOLLECTION,
@@ -1656,7 +1757,7 @@ static void make_object_duplilist_real(
for (dob = lb_duplis->first; dob; dob = dob->next) {
Object *ob_src = DEG_get_original_object(dob->ob);
- Object *ob_dst = ID_NEW_SET(dob->ob, BKE_object_copy(bmain, ob_src));
+ Object *ob_dst = ID_NEW_SET(ob_src, BKE_object_copy(bmain, ob_src));
Base *base_dst;
/* font duplis can have a totcol without material, we get them from parent
@@ -1838,7 +1939,11 @@ void OBJECT_OT_duplicates_make_real(wmOperatorType *ot)
ot->srna, "use_hierarchy", 0, "Keep Hierarchy", "Maintain parent child relationships");
}
-/**************************** Convert **************************/
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Data Convert Operator
+ * \{ */
static const EnumPropertyItem convert_target_items[] = {
{OB_CURVE, "CURVE", ICON_OUTLINER_OB_CURVE, "Curve from Mesh/Text", ""},
@@ -1857,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);
@@ -1947,7 +2052,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
@@ -2293,7 +2399,11 @@ void OBJECT_OT_convert(wmOperatorType *ot)
"Keep original objects instead of replacing them");
}
-/**************************** Duplicate ************************/
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Duplicate Object Operator
+ * \{ */
/*
* dupflag: a flag made from constants declared in DNA_userdef_types.h
@@ -2449,7 +2559,13 @@ void OBJECT_OT_duplicate(wmOperatorType *ot)
RNA_def_property_flag(prop, PROP_HIDDEN);
}
-/* **************** add named object, for dragdrop ************* */
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Add Named Object Operator
+ *
+ * Use for for drag & drop.
+ * \{ */
static int add_named_exec(bContext *C, wmOperator *op)
{
@@ -2481,7 +2597,7 @@ static int add_named_exec(bContext *C, wmOperator *op)
return OPERATOR_CANCELLED;
}
- basen->object->restrictflag &= ~OB_RESTRICT_VIEW;
+ basen->object->restrictflag &= ~OB_RESTRICT_VIEWPORT;
if (event) {
ARegion *ar = CTX_wm_region(C);
@@ -2527,7 +2643,12 @@ void OBJECT_OT_add_named(wmOperatorType *ot)
RNA_def_string(ot->srna, "name", NULL, MAX_ID_NAME - 2, "Name", "Object name to add");
}
-/**************************** Join *************************/
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Join Object Operator
+ *
+ * \{ */
static bool join_poll(bContext *C)
{
@@ -2596,7 +2717,11 @@ void OBJECT_OT_join(wmOperatorType *ot)
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
-/**************************** Join as Shape Key*************************/
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Join as Shape Key Operator
+ * \{ */
static bool join_shapes_poll(bContext *C)
{
@@ -2649,3 +2774,5 @@ void OBJECT_OT_join_shapes(wmOperatorType *ot)
/* flags */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
+
+/** \} */
diff --git a/source/blender/editors/object/object_bake_api.c b/source/blender/editors/object/object_bake_api.c
index 5ae757cac56..f87342a14ad 100644
--- a/source/blender/editors/object/object_bake_api.c
+++ b/source/blender/editors/object/object_bake_api.c
@@ -277,7 +277,8 @@ static bool write_internal_bake_pixels(Image *image,
RE_bake_margin(ibuf, mask_buffer, margin);
}
- ibuf->userflags |= IB_DISPLAY_BUFFER_INVALID | IB_BITMAPDIRTY;
+ ibuf->userflags |= IB_DISPLAY_BUFFER_INVALID;
+ BKE_image_mark_dirty(image, ibuf);
if (ibuf->rect_float) {
ibuf->userflags |= IB_RECT_INVALID;
@@ -704,10 +705,9 @@ 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(Depsgraph *depsgraph, Main *bmain, Scene *scene, Object *ob)
+static Mesh *bake_mesh_new_from_object(Object *object)
{
- bool apply_modifiers = (ob->type != OB_MESH);
- Mesh *me = BKE_mesh_new_from_object(depsgraph, bmain, scene, ob, apply_modifiers, false);
+ Mesh *me = BKE_object_to_mesh(object);
if (me->flag & ME_AUTOSMOOTH) {
BKE_mesh_split_faces(me, true);
@@ -903,7 +903,7 @@ static int bake(Render *re,
ob_low_eval = DEG_get_evaluated_object(depsgraph, ob_low);
/* get the mesh as it arrives in the renderer */
- me_low = bake_mesh_new_from_object(depsgraph, bmain, scene, ob_low_eval);
+ me_low = bake_mesh_new_from_object(ob_low_eval);
/* populate the pixel array with the face data */
if ((is_selected_to_active && (ob_cage == NULL) && is_cage) == false) {
@@ -917,7 +917,7 @@ static int bake(Render *re,
/* prepare cage mesh */
if (ob_cage) {
- me_cage = bake_mesh_new_from_object(depsgraph, bmain, scene, ob_cage_eval);
+ me_cage = bake_mesh_new_from_object(ob_cage_eval);
if ((me_low->totpoly != me_cage->totpoly) || (me_low->totloop != me_cage->totloop)) {
BKE_report(reports,
RPT_ERROR,
@@ -946,7 +946,7 @@ static int bake(Render *re,
md = md_next;
}
- me_cage = bake_mesh_new_from_object(depsgraph, bmain, scene, ob_low_eval);
+ me_cage = BKE_object_to_mesh(ob_low_eval);
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 = bake_mesh_new_from_object(depsgraph, bmain, scene, highpoly[i].ob_eval);
+ highpoly[i].me = BKE_object_to_mesh(highpoly[i].ob_eval);
/* 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_mesh_new_from_object(depsgraph, bmain, scene, ob_low_eval, true, false);
+ me_nores = BKE_object_to_mesh(ob_low_eval);
RE_bake_pixels_populate(me_nores, pixel_array_low, num_pixels, &bake_images, uv_layer);
RE_bake_normal_world_to_tangent(pixel_array_low,
@@ -1098,7 +1098,7 @@ static int bake(Render *re,
me_nores,
normal_swizzle,
ob_low_eval->obmat);
- BKE_id_free(bmain, me_nores);
+ BKE_object_to_mesh_clear(ob_low_eval);
if (md) {
md->mode = mode;
@@ -1222,7 +1222,7 @@ cleanup:
int i;
for (i = 0; i < tot_highpoly; i++) {
if (highpoly[i].me) {
- BKE_id_free(bmain, highpoly[i].me);
+ BKE_object_to_mesh_clear(highpoly[i].ob_eval);
}
}
MEM_freeN(highpoly);
@@ -1253,11 +1253,11 @@ cleanup:
}
if (me_low) {
- BKE_id_free(bmain, me_low);
+ BKE_object_to_mesh_clear(ob_low_eval);
}
if (me_cage) {
- BKE_id_free(bmain, me_cage);
+ BKE_object_to_mesh_clear(ob_cage_eval);
}
DEG_graph_free(depsgraph);
diff --git a/source/blender/editors/object/object_constraint.c b/source/blender/editors/object/object_constraint.c
index 6a587bd6e2a..abdf64af595 100644
--- a/source/blender/editors/object/object_constraint.c
+++ b/source/blender/editors/object/object_constraint.c
@@ -160,7 +160,7 @@ static void validate_pyconstraint_cb(Main *bmain, void *arg1, void *arg2)
if (index) {
/* innovative use of a for...loop to search */
for (text = bmain->texts.first, i = 1; text && index != i; i++, text = text->id.next) {
- ;
+ /* pass */
}
}
data->text = text;
@@ -1878,14 +1878,6 @@ static int constraint_add_exec(
if (type == CONSTRAINT_TYPE_NULL) {
return OPERATOR_CANCELLED;
}
- if ((type == CONSTRAINT_TYPE_KINEMATIC) && ((!pchan) || (list != &pchan->constraints))) {
- BKE_report(op->reports, RPT_ERROR, "IK constraint can only be added to bones");
- return OPERATOR_CANCELLED;
- }
- if ((type == CONSTRAINT_TYPE_SPLINEIK) && ((!pchan) || (list != &pchan->constraints))) {
- BKE_report(op->reports, RPT_ERROR, "Spline IK constraint can only be added to bones");
- return OPERATOR_CANCELLED;
- }
/* Create a new constraint of the type required,
* and add it to the active/given constraints list. */
@@ -2023,8 +2015,33 @@ static int pose_constraint_add_exec(bContext *C, wmOperator *op)
/* ------------------ */
+/* Filters constraints that are only compatible with bones */
+static const EnumPropertyItem *object_constraint_add_itemf(bContext *UNUSED(C),
+ PointerRNA *UNUSED(ptr),
+ PropertyRNA *UNUSED(prop),
+ bool *r_free)
+{
+ const EnumPropertyItem *item = rna_enum_constraint_type_items;
+ EnumPropertyItem *object_constraint_items = NULL;
+ int totitem = 0;
+
+ while (item->identifier) {
+ if ((item->value != CONSTRAINT_TYPE_KINEMATIC) && (item->value != CONSTRAINT_TYPE_SPLINEIK)) {
+ RNA_enum_item_add(&object_constraint_items, &totitem, item);
+ }
+ item++;
+ }
+
+ RNA_enum_item_end(&object_constraint_items, &totitem);
+ *r_free = true;
+
+ return object_constraint_items;
+}
+
void OBJECT_OT_constraint_add(wmOperatorType *ot)
{
+ PropertyRNA *prop;
+
/* identifiers */
ot->name = "Add Constraint";
ot->description = "Add a constraint to the active object";
@@ -2039,11 +2056,15 @@ void OBJECT_OT_constraint_add(wmOperatorType *ot)
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
/* properties */
- ot->prop = RNA_def_enum(ot->srna, "type", rna_enum_constraint_type_items, 0, "Type", "");
+ prop = RNA_def_enum(ot->srna, "type", DummyRNA_NULL_items, 0, "Type", "");
+ RNA_def_enum_funcs(prop, object_constraint_add_itemf);
+ ot->prop = prop;
}
void OBJECT_OT_constraint_add_with_targets(wmOperatorType *ot)
{
+ PropertyRNA *prop;
+
/* identifiers */
ot->name = "Add Constraint (with Targets)";
ot->description =
@@ -2060,7 +2081,9 @@ void OBJECT_OT_constraint_add_with_targets(wmOperatorType *ot)
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
/* properties */
- ot->prop = RNA_def_enum(ot->srna, "type", rna_enum_constraint_type_items, 0, "Type", "");
+ prop = RNA_def_enum(ot->srna, "type", DummyRNA_NULL_items, 0, "Type", "");
+ RNA_def_enum_funcs(prop, object_constraint_add_itemf);
+ ot->prop = prop;
}
void POSE_OT_constraint_add(wmOperatorType *ot)
diff --git a/source/blender/editors/object/object_edit.c b/source/blender/editors/object/object_edit.c
index 795e1dd66a5..a542911f4d4 100644
--- a/source/blender/editors/object/object_edit.c
+++ b/source/blender/editors/object/object_edit.c
@@ -314,7 +314,7 @@ void ED_collection_hide_menu_draw(const bContext *C, uiLayout *layout)
continue;
}
- if (lc->collection->flag & COLLECTION_RESTRICT_VIEW) {
+ if (lc->collection->flag & COLLECTION_RESTRICT_VIEWPORT) {
continue;
}
@@ -722,7 +722,7 @@ static bool editmode_toggle_poll(bContext *C)
}
/* if hidden but in edit mode, we still display */
- if ((ob->restrictflag & OB_RESTRICT_VIEW) && !(ob->mode & OB_MODE_EDIT)) {
+ if ((ob->restrictflag & OB_RESTRICT_VIEWPORT) && !(ob->mode & OB_MODE_EDIT)) {
return 0;
}
@@ -1779,4 +1779,5 @@ void OBJECT_OT_link_to_collection(wmOperatorType *ot)
"Name",
"Name of the newly added collection");
RNA_def_property_flag(prop, PROP_SKIP_SAVE);
+ ot->prop = prop;
}
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/physics/dynamicpaint_ops.c b/source/blender/editors/physics/dynamicpaint_ops.c
index cb8fe262730..40b7a245f69 100644
--- a/source/blender/editors/physics/dynamicpaint_ops.c
+++ b/source/blender/editors/physics/dynamicpaint_ops.c
@@ -47,6 +47,7 @@
#include "DEG_depsgraph.h"
#include "DEG_depsgraph_build.h"
+#include "DEG_depsgraph_query.h"
#include "ED_mesh.h"
#include "ED_screen.h"
@@ -360,6 +361,7 @@ static void dynamicPaint_bakeImageSequence(DynamicPaintBakeJob *job)
DynamicPaintSurface *surface = job->surface;
Object *cObject = job->ob;
DynamicPaintCanvasSettings *canvas = surface->canvas;
+ Scene *input_scene = DEG_get_input_scene(job->depsgraph);
Scene *scene = job->scene;
int frame = 1, orig_frame;
int frames;
@@ -375,8 +377,8 @@ static void dynamicPaint_bakeImageSequence(DynamicPaintBakeJob *job)
/* Set frame to start point (also inits modifier data) */
frame = surface->start_frame;
- orig_frame = scene->r.cfra;
- scene->r.cfra = (int)frame;
+ orig_frame = input_scene->r.cfra;
+ input_scene->r.cfra = (int)frame;
ED_update_for_newframe(job->bmain, job->depsgraph);
/* Init surface */
@@ -402,7 +404,7 @@ static void dynamicPaint_bakeImageSequence(DynamicPaintBakeJob *job)
*(job->progress) = progress;
/* calculate a frame */
- scene->r.cfra = (int)frame;
+ input_scene->r.cfra = (int)frame;
ED_update_for_newframe(job->bmain, job->depsgraph);
if (!dynamicPaint_calculateFrame(surface, job->depsgraph, scene, cObject, frame)) {
job->success = 0;
@@ -438,7 +440,8 @@ static void dynamicPaint_bakeImageSequence(DynamicPaintBakeJob *job)
}
}
- scene->r.cfra = orig_frame;
+ input_scene->r.cfra = orig_frame;
+ ED_update_for_newframe(job->bmain, job->depsgraph);
}
static void dpaint_bake_startjob(void *customdata, short *stop, short *do_update, float *progress)
@@ -470,25 +473,26 @@ static void dpaint_bake_startjob(void *customdata, short *stop, short *do_update
*/
static int dynamicpaint_bake_exec(struct bContext *C, struct wmOperator *op)
{
- DynamicPaintModifierData *pmd = NULL;
- DynamicPaintCanvasSettings *canvas;
- Object *ob = ED_object_context(C);
- Scene *scene = CTX_data_scene(C);
+ Depsgraph *depsgraph = CTX_data_depsgraph(C);
+ Object *ob_ = ED_object_context(C);
+ Object *object_eval = DEG_get_evaluated_object(depsgraph, ob_);
+ Scene *scene_eval = DEG_get_evaluated_scene(depsgraph);
DynamicPaintSurface *surface;
/*
* Get modifier data
*/
- pmd = (DynamicPaintModifierData *)modifiers_findByType(ob, eModifierType_DynamicPaint);
- if (!pmd) {
+ DynamicPaintModifierData *pmd = (DynamicPaintModifierData *)modifiers_findByType(
+ object_eval, eModifierType_DynamicPaint);
+ if (pmd == NULL) {
BKE_report(op->reports, RPT_ERROR, "Bake failed: no Dynamic Paint modifier found");
return OPERATOR_CANCELLED;
}
/* Make sure we're dealing with a canvas */
- canvas = pmd->canvas;
- if (!canvas) {
+ DynamicPaintCanvasSettings *canvas = pmd->canvas;
+ if (canvas == NULL) {
BKE_report(op->reports, RPT_ERROR, "Bake failed: invalid canvas");
return OPERATOR_CANCELLED;
}
@@ -500,15 +504,15 @@ static int dynamicpaint_bake_exec(struct bContext *C, struct wmOperator *op)
DynamicPaintBakeJob *job = MEM_mallocN(sizeof(DynamicPaintBakeJob), "DynamicPaintBakeJob");
job->bmain = CTX_data_main(C);
- job->scene = scene;
+ job->scene = scene_eval;
job->depsgraph = CTX_data_depsgraph(C);
- job->ob = ob;
+ job->ob = object_eval;
job->canvas = canvas;
job->surface = surface;
wmJob *wm_job = WM_jobs_get(CTX_wm_manager(C),
CTX_wm_window(C),
- scene,
+ CTX_data_scene(C),
"Dynamic Paint Bake",
WM_JOB_PROGRESS,
WM_JOB_TYPE_DPAINT_BAKE);
diff --git a/source/blender/editors/render/render_internal.c b/source/blender/editors/render/render_internal.c
index 09bcc0a3058..1e85c895f71 100644
--- a/source/blender/editors/render/render_internal.c
+++ b/source/blender/editors/render/render_internal.c
@@ -356,7 +356,7 @@ static int screen_render_exec(bContext *C, wmOperator *op)
/* cleanup sequencer caches before starting user triggered render.
* otherwise, invalidated cache entries can make their way into
- * the output rendering. We can't put that into RE_BlenderFrame,
+ * the output rendering. We can't put that into RE_RenderFrame,
* since sequence rendering can call that recursively... (peter) */
BKE_sequencer_cache_cleanup(scene);
@@ -364,18 +364,17 @@ static int screen_render_exec(bContext *C, wmOperator *op)
BLI_threaded_malloc_begin();
if (is_animation) {
- RE_BlenderAnim(re,
- mainp,
- scene,
- single_layer,
- camera_override,
- scene->r.sfra,
- scene->r.efra,
- scene->r.frame_step);
+ RE_RenderAnim(re,
+ mainp,
+ scene,
+ single_layer,
+ camera_override,
+ scene->r.sfra,
+ scene->r.efra,
+ scene->r.frame_step);
}
else {
- RE_BlenderFrame(
- re, mainp, scene, single_layer, camera_override, scene->r.cfra, is_write_still);
+ RE_RenderFrame(re, mainp, scene, single_layer, camera_override, scene->r.cfra, is_write_still);
}
BLI_threaded_malloc_end();
@@ -671,23 +670,23 @@ static void render_startjob(void *rjv, short *stop, short *do_update, float *pro
RE_SetReports(rj->re, rj->reports);
if (rj->anim) {
- RE_BlenderAnim(rj->re,
+ RE_RenderAnim(rj->re,
+ rj->main,
+ rj->scene,
+ rj->single_layer,
+ rj->camera_override,
+ rj->scene->r.sfra,
+ rj->scene->r.efra,
+ rj->scene->r.frame_step);
+ }
+ else {
+ RE_RenderFrame(rj->re,
rj->main,
rj->scene,
rj->single_layer,
rj->camera_override,
- rj->scene->r.sfra,
- rj->scene->r.efra,
- rj->scene->r.frame_step);
- }
- else {
- RE_BlenderFrame(rj->re,
- rj->main,
- rj->scene,
- rj->single_layer,
- rj->camera_override,
- rj->scene->r.cfra,
- rj->write_still);
+ rj->scene->r.cfra,
+ rj->write_still);
}
RE_SetReports(rj->re, NULL);
@@ -976,7 +975,7 @@ static int screen_render_invoke(bContext *C, wmOperator *op, const wmEvent *even
/* cleanup sequencer caches before starting user triggered render.
* otherwise, invalidated cache entries can make their way into
- * the output rendering. We can't put that into RE_BlenderFrame,
+ * the output rendering. We can't put that into RE_RenderFrame,
* since sequence rendering can call that recursively... (peter) */
BKE_sequencer_cache_cleanup(scene);
diff --git a/source/blender/editors/render/render_opengl.c b/source/blender/editors/render/render_opengl.c
index 28cfce00e6e..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,
@@ -489,8 +483,6 @@ static void screen_opengl_render_apply(const bContext *C, OGLRender *oglrender)
for (view_id = 0; view_id < oglrender->views_len; view_id++) {
context.view_id = view_id;
context.gpu_offscreen = oglrender->ofs;
- context.gpu_full_samples = oglrender->ofs_full_samples;
-
oglrender->seq_data.ibufs_arr[view_id] = BKE_sequencer_give_ibuf(&context, CFRA, chanshown);
}
}
@@ -517,24 +509,6 @@ static void screen_opengl_render_apply(const bContext *C, OGLRender *oglrender)
}
}
-static bool screen_opengl_fullsample_enabled(Scene *scene)
-{
- if (scene->r.scemode & R_FULL_SAMPLE) {
- return true;
- }
- else {
- /* XXX TODO:
- * Technically if the hardware supports MSAA we could keep using Blender 2.7x approach.
- * However anti-aliasing without full_sample is not playing well even in 2.7x.
- *
- * For example, if you enable depth of field, there is aliasing, even if the viewport is fine.
- * For 2.8x this is more complicated because so many things rely on shader.
- * So until we fix the gpu_framebuffer anti-aliasing suupport we need to force full sample.
- */
- return true;
- }
-}
-
static bool screen_opengl_render_init(bContext *C, wmOperator *op)
{
/* new render clears all callbacks */
@@ -548,12 +522,11 @@ static bool screen_opengl_render_init(bContext *C, wmOperator *op)
GPUOffScreen *ofs;
OGLRender *oglrender;
int sizex, sizey;
- const int samples = (scene->r.mode & R_OSA) ? scene->r.osa : 0;
- const bool full_samples = (samples != 0) && screen_opengl_fullsample_enabled(scene);
bool is_view_context = RNA_boolean_get(op->ptr, "view_context");
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) {
@@ -598,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, full_samples ? 0 : samples, true, true, err_out);
+ ofs = GPU_offscreen_create(sizex, sizey, samples, true, true, err_out);
DRW_opengl_context_disable();
if (!ofs) {
@@ -611,8 +584,6 @@ static bool screen_opengl_render_init(bContext *C, wmOperator *op)
op->customdata = oglrender;
oglrender->ofs = ofs;
- oglrender->ofs_samples = samples;
- oglrender->ofs_full_samples = full_samples;
oglrender->sizex = sizex;
oglrender->sizey = sizey;
oglrender->bmain = CTX_data_main(C);
@@ -621,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_preview.c b/source/blender/editors/render/render_preview.c
index bf6d658f927..76b88b8df22 100644
--- a/source/blender/editors/render/render_preview.c
+++ b/source/blender/editors/render/render_preview.c
@@ -270,7 +270,7 @@ static const char *preview_collection_name(const char pr_type)
case MA_FLUID:
return "Fluid";
case MA_SPHERE_A:
- return "World Shader Ball";
+ return "World Sphere";
case MA_LAMP:
return "Lamp";
case MA_SKY:
@@ -437,7 +437,14 @@ static Scene *preview_prepare_scene(
sce->world->horb = 0.05f;
}
- set_preview_visibility(sce, view_layer, mat->pr_type, sp->pr_method);
+ if (sp->pr_method == PR_ICON_RENDER && sp->pr_main == G_pr_main_grease_pencil) {
+ /* For grease pencil, always use sphere for icon renders. */
+ set_preview_visibility(sce, view_layer, MA_SPHERE_A, sp->pr_method);
+ }
+ else {
+ /* Use specified preview shape for both preview panel and icon previews. */
+ set_preview_visibility(sce, view_layer, mat->pr_type, sp->pr_method);
+ }
if (sp->pr_method != PR_ICON_RENDER) {
if (mat->nodetree && sp->pr_method == PR_NODE_RENDER) {
@@ -449,7 +456,7 @@ static Scene *preview_prepare_scene(
}
}
else {
- sce->r.mode &= ~(R_OSA);
+ sce->display.render_aa = SCE_DISPLAY_AA_OFF;
}
for (Base *base = view_layer->object_bases.first; base; base = base->next) {
@@ -861,7 +868,7 @@ static void shader_preview_render(ShaderPreview *sp, ID *id, int split, int firs
if (sp->pr_method == PR_ICON_RENDER) {
sce->r.scemode |= R_NO_IMAGE_LOAD;
- sce->r.mode |= R_OSA;
+ sce->display.render_aa = SCE_DISPLAY_AA_SAMPLES_8;
}
else if (sp->pr_method == PR_NODE_RENDER) {
if (idtype == ID_MA) {
@@ -870,10 +877,10 @@ static void shader_preview_render(ShaderPreview *sp, ID *id, int split, int firs
else if (idtype == ID_TE) {
sce->r.scemode |= R_TEXNODE_PREVIEW;
}
- sce->r.mode &= ~R_OSA;
+ sce->display.render_aa = SCE_DISPLAY_AA_OFF;
}
else { /* PR_BUTS_RENDER */
- sce->r.mode |= R_OSA;
+ sce->display.render_aa = SCE_DISPLAY_AA_SAMPLES_8;
}
/* callbacs are cleared on GetRender() */
@@ -969,7 +976,7 @@ static void shader_preview_free(void *customdata)
/* get rid of copied ID */
properties = IDP_GetProperties(sp->id_copy, false);
if (properties) {
- IDP_FreeProperty_ex(properties, false);
+ IDP_FreePropertyContent_ex(properties, false);
MEM_freeN(properties);
}
switch (GS(sp->id_copy->name)) {
diff --git a/source/blender/editors/render/render_shading.c b/source/blender/editors/render/render_shading.c
index 3186f011c6a..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(&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(&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(&ptr, prop, idptr);
+ RNA_property_pointer_set(&ptr, prop, idptr, NULL);
RNA_property_update(C, &ptr, prop);
}
diff --git a/source/blender/editors/render/render_update.c b/source/blender/editors/render/render_update.c
index 3f3f98bc6e5..64869b71746 100644
--- a/source/blender/editors/render/render_update.c
+++ b/source/blender/editors/render/render_update.c
@@ -132,7 +132,10 @@ void ED_render_scene_update(const DEGEditorUpdateContext *update_ctx, int update
CTX_wm_region_set(C, ar);
engine->flag &= ~RE_ENGINE_DO_UPDATE;
- engine->type->view_update(engine, C);
+ /* NOTE: Important to pass non-updated depsgraph, This is because this function is called
+ * from inside dependency graph evaluation. Additionally, if we pass fully evaluated one
+ * we will loose updates stored in the graph. */
+ engine->type->view_update(engine, C, CTX_data_depsgraph(C));
}
else {
RenderEngineType *engine_type = ED_view3d_engine_type(scene, v3d->shading.type);
@@ -265,7 +268,7 @@ static void image_changed(Main *bmain, Image *ima)
/* textures */
for (tex = bmain->textures.first; tex; tex = tex->id.next) {
- if (tex->ima == ima) {
+ if (tex->type == TEX_IMAGE && tex->ima == ima) {
texture_changed(bmain, tex);
}
}
diff --git a/source/blender/editors/screen/area.c b/source/blender/editors/screen/area.c
index 38684afec39..9b35c809d5a 100644
--- a/source/blender/editors/screen/area.c
+++ b/source/blender/editors/screen/area.c
@@ -50,6 +50,7 @@
#include "ED_screen.h"
#include "ED_screen_types.h"
#include "ED_space_api.h"
+#include "ED_time_scrub_ui.h"
#include "GPU_immediate.h"
#include "GPU_immediate_util.h"
@@ -202,7 +203,7 @@ static void area_draw_azone_fullscreen(short x1, short y1, short x2, short y2, f
alpha = min_ff(alpha, 0.75f);
- UI_icon_draw_aspect(x, y, ICON_FULLSCREEN_EXIT, 0.7f / UI_DPI_FAC, alpha, NULL);
+ UI_icon_draw_ex(x, y, ICON_FULLSCREEN_EXIT, 0.7f * U.inv_dpi_fac, 0.0f, alpha, NULL, false);
/* debug drawing :
* The click_rect is the same as defined in fullscreen_click_rcti_init
@@ -457,19 +458,6 @@ void ED_area_do_msg_notify_tag_refresh(
ED_area_tag_refresh(sa);
}
-static void region_do_msg_notify_tag_redraw(
- /* Follow wmMsgNotifyFn spec */
- bContext *UNUSED(C),
- wmMsgSubscribeKey *UNUSED(msg_key),
- wmMsgSubscribeValue *msg_val)
-{
- ARegion *ar = msg_val->owner;
- ED_region_tag_redraw(ar);
-
- /* FIXME(campbell): shouldn't be needed. */
- WM_main_add_notifier(NC_SPACE | ND_SPACE_VIEW3D, NULL);
-}
-
void ED_area_do_mgs_subscribe_for_tool_header(
/* Follow ARegionType.message_subscribe */
const struct bContext *UNUSED(C),
@@ -480,18 +468,39 @@ void ED_area_do_mgs_subscribe_for_tool_header(
struct ARegion *ar,
struct wmMsgBus *mbus)
{
+ BLI_assert(ar->regiontype == RGN_TYPE_TOOL_HEADER);
wmMsgSubscribeValue msg_sub_value_region_tag_redraw = {
.owner = ar,
.user_data = ar,
- /* TODO(campbell): investigate why
- * ED_region_do_msg_notify_tag_redraw doesn't work here. */
- // .notify = ED_region_do_msg_notify_tag_redraw,
- .notify = region_do_msg_notify_tag_redraw,
+ .notify = ED_region_do_msg_notify_tag_redraw,
};
WM_msg_subscribe_rna_prop(
mbus, &workspace->id, workspace, WorkSpace, tools, &msg_sub_value_region_tag_redraw);
}
+void ED_area_do_mgs_subscribe_for_tool_ui(
+ /* Follow ARegionType.message_subscribe */
+ const struct bContext *UNUSED(C),
+ struct WorkSpace *workspace,
+ struct Scene *UNUSED(scene),
+ struct bScreen *UNUSED(screen),
+ struct ScrArea *UNUSED(sa),
+ struct ARegion *ar,
+ struct wmMsgBus *mbus)
+{
+ BLI_assert(ar->regiontype == RGN_TYPE_UI);
+ const char *category = UI_panel_category_active_get(ar, false);
+ if (category && STREQ(category, "Tool")) {
+ wmMsgSubscribeValue msg_sub_value_region_tag_redraw = {
+ .owner = ar,
+ .user_data = ar,
+ .notify = ED_region_do_msg_notify_tag_redraw,
+ };
+ WM_msg_subscribe_rna_prop(
+ mbus, &workspace->id, workspace, WorkSpace, tools, &msg_sub_value_region_tag_redraw);
+ }
+}
+
/**
* Although there's no general support for minimizing areas, the status-bar can
* be snapped to be only a few pixels high. A few pixels rather than 0 so it
@@ -1050,11 +1059,11 @@ static void region_azones_scrollbars_initialize(ScrArea *sa, ARegion *ar)
{
const View2D *v2d = &ar->v2d;
- if ((v2d->scroll & V2D_SCROLL_VERTICAL) && ((v2d->scroll & V2D_SCROLL_SCALE_VERTICAL) == 0)) {
+ if ((v2d->scroll & V2D_SCROLL_VERTICAL) && ((v2d->scroll & V2D_SCROLL_VERTICAL_HANDLES) == 0)) {
region_azone_scrollbar_initialize(sa, ar, AZ_SCROLL_VERT);
}
if ((v2d->scroll & V2D_SCROLL_HORIZONTAL) &&
- ((v2d->scroll & V2D_SCROLL_SCALE_HORIZONTAL) == 0)) {
+ ((v2d->scroll & V2D_SCROLL_HORIZONTAL_HANDLES) == 0)) {
region_azone_scrollbar_initialize(sa, ar, AZ_SCROLL_HOR);
}
}
@@ -1110,7 +1119,7 @@ static int rct_fits(const rcti *rect, char dir, int size)
static void region_overlap_fix(ScrArea *sa, ARegion *ar)
{
ARegion *ar1;
- const int align = ar->alignment & ~RGN_SPLIT_PREV;
+ const int align = RGN_ALIGN_ENUM_FROM_MASK(ar->alignment);
int align1 = 0;
/* find overlapping previous region on same place */
@@ -1227,7 +1236,7 @@ static void region_rect_recursive(
}
}
- int alignment = ar->alignment & ~RGN_SPLIT_PREV;
+ int alignment = RGN_ALIGN_ENUM_FROM_MASK(ar->alignment);
/* set here, assuming userpref switching forces to call this again */
ar->overlap = ED_region_is_overlap(sa->spacetype, ar->regiontype);
@@ -1596,14 +1605,19 @@ static void ed_default_handlers(
wmKeyMap *keymap = WM_keymap_ensure(wm->defaultconf, "View2D", 0, 0);
WM_event_add_keymap_handler(handlers, keymap);
}
- if (flag & ED_KEYMAP_MARKERS) {
+ if (flag & ED_KEYMAP_ANIMATION) {
+ wmKeyMap *keymap;
+
/* time-markers */
- wmKeyMap *keymap = WM_keymap_ensure(wm->defaultconf, "Markers", 0, 0);
+ keymap = WM_keymap_ensure(wm->defaultconf, "Markers", 0, 0);
WM_event_add_keymap_handler_poll(handlers, keymap, event_in_markers_region);
- }
- if (flag & ED_KEYMAP_ANIMATION) {
+
+ /* time-scrubbing */
+ keymap = WM_keymap_ensure(wm->defaultconf, "Scrubbing", 0, 0);
+ WM_event_add_keymap_handler_poll(handlers, keymap, ED_event_in_scrubbing_region);
+
/* frame changing and timeline operators (for time spaces) */
- wmKeyMap *keymap = WM_keymap_ensure(wm->defaultconf, "Animation", 0, 0);
+ keymap = WM_keymap_ensure(wm->defaultconf, "Animation", 0, 0);
WM_event_add_keymap_handler(handlers, keymap);
}
if (flag & ED_KEYMAP_FRAMES) {
@@ -1613,14 +1627,19 @@ static void ed_default_handlers(
}
if (flag & ED_KEYMAP_HEADER) {
/* standard keymap for headers regions */
- wmKeyMap *keymap = WM_keymap_ensure(wm->defaultconf, "Header", 0, 0);
+ wmKeyMap *keymap = WM_keymap_ensure(wm->defaultconf, "Region Context Menu", 0, 0);
WM_event_add_keymap_handler(handlers, keymap);
}
if (flag & ED_KEYMAP_FOOTER) {
/* standard keymap for footer regions */
- wmKeyMap *keymap = WM_keymap_ensure(wm->defaultconf, "Footer", 0, 0);
+ wmKeyMap *keymap = WM_keymap_ensure(wm->defaultconf, "Region Context Menu", 0, 0);
WM_event_add_keymap_handler(handlers, keymap);
}
+ if (flag & ED_KEYMAP_NAVBAR) {
+ /* standard keymap for Navigation bar regions */
+ wmKeyMap *keymap = WM_keymap_ensure(wm->defaultconf, "Region Context Menu", 0, 0);
+ WM_event_add_keymap_handler(&ar->handlers, keymap);
+ }
/* Keep last because of LMB/RMB handling, see: T57527. */
if (flag & ED_KEYMAP_GPENCIL) {
@@ -1690,7 +1709,7 @@ void ED_area_update_region_sizes(wmWindowManager *wm, wmWindow *win, ScrArea *ar
}
/* Some AZones use View2D data which is only updated in region init, so call that first! */
- region_azones_add(screen, area, ar, ar->alignment & ~RGN_SPLIT_PREV);
+ region_azones_add(screen, area, ar, RGN_ALIGN_ENUM_FROM_MASK(ar->alignment));
}
ED_area_azones_update(area, &win->eventstate->x);
@@ -1761,7 +1780,7 @@ void ED_area_initialize(wmWindowManager *wm, wmWindow *win, ScrArea *sa)
}
/* Some AZones use View2D data which is only updated in region init, so call that first! */
- region_azones_add(screen, sa, ar, ar->alignment & ~RGN_SPLIT_PREV);
+ region_azones_add(screen, sa, ar, RGN_ALIGN_ENUM_FROM_MASK(ar->alignment));
}
/* Avoid re-initializing tools while resizing the window. */
@@ -2273,7 +2292,7 @@ static void ed_panel_draw(const bContext *C,
}
}
- UI_panel_end(block, w, h);
+ UI_panel_end(block, w, h, open);
}
/**
@@ -2281,34 +2300,62 @@ static void ed_panel_draw(const bContext *C,
* Matching against any of these strings will draw the panel.
* Can be NULL to skip context checks.
*/
-void ED_region_panels_layout_ex(
- const bContext *C, ARegion *ar, const char *contexts[], int contextnr, const bool vertical)
+void ED_region_panels_layout_ex(const bContext *C,
+ ARegion *ar,
+ ListBase *paneltypes,
+ const char *contexts[],
+ int contextnr,
+ const bool vertical,
+ const char *category_override)
{
+ /* collect panels to draw */
+ WorkSpace *workspace = CTX_wm_workspace(C);
+ LinkNode *panel_types_stack = NULL;
+ for (PanelType *pt = paneltypes->last; pt; pt = pt->prev) {
+ /* Only draw top level panels. */
+ if (pt->parent) {
+ continue;
+ }
+
+ if (category_override) {
+ if (!STREQ(pt->category, category_override)) {
+ continue;
+ }
+ }
+
+ /* verify context */
+ if (contexts && pt->context[0] && !streq_array_any(pt->context, contexts)) {
+ continue;
+ }
+
+ /* If we're tagged, only use compatible. */
+ if (pt->owner_id[0] && BKE_workspace_owner_id_check(workspace, pt->owner_id) == false) {
+ continue;
+ }
+
+ /* draw panel */
+ if (pt->draw && (!pt->poll || pt->poll(C, pt))) {
+ BLI_linklist_prepend_alloca(&panel_types_stack, pt);
+ }
+ }
+
ar->runtime.category = NULL;
- const WorkSpace *workspace = CTX_wm_workspace(C);
ScrArea *sa = CTX_wm_area(C);
- PanelType *pt;
View2D *v2d = &ar->v2d;
int x, y, w, em;
- bool is_context_new = 0;
- int scroll;
/* XXX, should use some better check? */
/* For now also has hardcoded check for clip editor until it supports actual toolbar. */
- bool use_category_tabs = ((1 << ar->regiontype) & RGN_TYPE_HAS_CATEGORY_MASK) ||
- (ar->regiontype == RGN_TYPE_TOOLS && sa->spacetype == SPACE_CLIP);
+ bool use_category_tabs = (category_override == NULL) &&
+ ((((1 << ar->regiontype) & RGN_TYPE_HAS_CATEGORY_MASK) ||
+ (ar->regiontype == RGN_TYPE_TOOLS && sa->spacetype == SPACE_CLIP)));
/* offset panels for small vertical tab area */
const char *category = NULL;
const int category_tabs_width = UI_PANEL_CATEGORY_MARGIN_WIDTH;
int margin_x = 0;
const bool region_layout_based = ar->flag & RGN_FLAG_DYNAMIC_SIZE;
-
- BLI_SMALLSTACK_DECLARE(pt_stack, PanelType *);
-
- if (contextnr != -1) {
- is_context_new = UI_view2d_tab_set(v2d, contextnr);
- }
+ const bool is_context_new = (contextnr != -1) ? UI_view2d_tab_set(v2d, contextnr) : false;
/* before setting the view */
if (vertical) {
@@ -2326,45 +2373,21 @@ void ED_region_panels_layout_ex(
v2d->scroll |= (V2D_SCROLL_BOTTOM);
v2d->scroll &= ~(V2D_SCROLL_RIGHT);
}
-
- scroll = v2d->scroll;
-
- /* collect panels to draw */
- for (pt = ar->type->paneltypes.last; pt; pt = pt->prev) {
- /* Only draw top level panels. */
- if (pt->parent) {
- continue;
- }
-
- /* verify context */
- if (contexts && pt->context[0] && !streq_array_any(pt->context, contexts)) {
- continue;
- }
-
- /* If we're tagged, only use compatible. */
- if (pt->owner_id[0] && BKE_workspace_owner_id_check(workspace, pt->owner_id) == false) {
- continue;
- }
-
- /* draw panel */
- if (pt->draw && (!pt->poll || pt->poll(C, pt))) {
- BLI_SMALLSTACK_PUSH(pt_stack, pt);
- }
- }
+ const int scroll = v2d->scroll;
/* collect categories */
if (use_category_tabs) {
UI_panel_category_clear_all(ar);
/* gather unique categories */
- BLI_SMALLSTACK_ITER_BEGIN (pt_stack, pt) {
+ for (LinkNode *pt_link = panel_types_stack; pt_link; pt_link = pt_link->next) {
+ PanelType *pt = pt_link->link;
if (pt->category[0]) {
if (!UI_panel_category_find(ar, pt->category)) {
UI_panel_category_add(ar, pt->category);
}
}
}
- BLI_SMALLSTACK_ITER_END;
if (!UI_panel_category_is_visible(ar)) {
use_category_tabs = false;
@@ -2392,7 +2415,8 @@ void ED_region_panels_layout_ex(
/* set view2d view matrix - UI_block_begin() stores it */
UI_view2d_view_ortho(v2d);
- BLI_SMALLSTACK_ITER_BEGIN (pt_stack, pt) {
+ for (LinkNode *pt_link = panel_types_stack; pt_link; pt_link = pt_link->next) {
+ PanelType *pt = pt_link->link;
Panel *panel = UI_panel_find_by_type(&ar->panels, pt);
if (use_category_tabs && pt->category[0] && !STREQ(category, pt->category)) {
@@ -2403,7 +2427,6 @@ void ED_region_panels_layout_ex(
ed_panel_draw(C, sa, ar, &ar->panels, pt, panel, w, em, vertical);
}
- BLI_SMALLSTACK_ITER_END;
/* align panels and return size */
UI_panels_end(C, ar, &x, &y);
@@ -2474,9 +2497,11 @@ void ED_region_panels_layout_ex(
ar->runtime.category = category;
}
}
+
void ED_region_panels_layout(const bContext *C, ARegion *ar)
{
- ED_region_panels_layout_ex(C, ar, NULL, -1, true);
+ bool vertical = true;
+ ED_region_panels_layout_ex(C, ar, &ar->type->paneltypes, NULL, -1, vertical, NULL);
}
void ED_region_panels_draw(const bContext *C, ARegion *ar)
@@ -2525,7 +2550,7 @@ void ED_region_panels_ex(
const bContext *C, ARegion *ar, const char *contexts[], int contextnr, const bool vertical)
{
/* TODO: remove? */
- ED_region_panels_layout_ex(C, ar, contexts, contextnr, vertical);
+ ED_region_panels_layout_ex(C, ar, &ar->type->paneltypes, contexts, contextnr, vertical, NULL);
ED_region_panels_draw(C, ar);
}
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 2ce9d732eb7..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;
}
@@ -884,9 +890,11 @@ static bScreen *screen_fullscreen_find_associated_normal_screen(const Main *bmai
{
for (bScreen *screen_iter = bmain->screens.first; screen_iter;
screen_iter = screen_iter->id.next) {
- ScrArea *sa = screen_iter->areabase.first;
- if (sa && sa->full == screen) {
- return screen_iter;
+ if ((screen_iter != screen) && ELEM(screen_iter->state, SCREENMAXIMIZED, SCREENFULL)) {
+ ScrArea *sa = screen_iter->areabase.first;
+ if (sa && sa->full == screen) {
+ return screen_iter;
+ }
}
}
@@ -905,9 +913,7 @@ bScreen *screen_change_prepare(
return NULL;
}
- if (ELEM(screen_new->state, SCREENMAXIMIZED, SCREENFULL)) {
- screen_new = screen_fullscreen_find_associated_normal_screen(bmain, screen_new);
- }
+ screen_new = screen_fullscreen_find_associated_normal_screen(bmain, screen_new);
/* check for valid winid */
if (!(screen_new->winid == 0 || screen_new->winid == win->winid)) {
diff --git a/source/blender/editors/screen/screen_ops.c b/source/blender/editors/screen/screen_ops.c
index 9f452dd79e0..a94c0e35876 100644
--- a/source/blender/editors/screen/screen_ops.c
+++ b/source/blender/editors/screen/screen_ops.c
@@ -342,7 +342,7 @@ bool ED_operator_console_active(bContext *C)
static bool ed_object_hidden(Object *ob)
{
/* if hidden but in edit mode, we still display, can happen with animation */
- return ((ob->restrictflag & OB_RESTRICT_VIEW) && !(ob->mode & OB_MODE_EDIT));
+ return ((ob->restrictflag & OB_RESTRICT_VIEWPORT) && !(ob->mode & OB_MODE_EDIT));
}
bool ED_operator_object_active(bContext *C)
@@ -631,24 +631,6 @@ static bool screen_active_editable(bContext *C)
return 0;
}
-static ARegion *screen_find_region_type(bContext *C, int type)
-{
- ARegion *ar = CTX_wm_region(C);
-
- /* find the header region
- * - try context first, but upon failing, search all regions in area...
- */
- if ((ar == NULL) || (ar->regiontype != type)) {
- ScrArea *sa = CTX_wm_area(C);
- ar = BKE_area_find_region_type(sa, type);
- }
- else {
- ar = NULL;
- }
-
- return ar;
-}
-
/** \} */
/* -------------------------------------------------------------------- */
@@ -2431,7 +2413,7 @@ static int area_max_regionsize(ScrArea *sa, ARegion *scalear, AZEdge edge)
/* regions in regions. */
if (scalear->alignment & RGN_SPLIT_PREV) {
- const int align = scalear->alignment & RGN_ALIGN_ENUM_MASK;
+ const int align = RGN_ALIGN_ENUM_FROM_MASK(scalear->alignment);
if (ELEM(align, RGN_ALIGN_TOP, RGN_ALIGN_BOTTOM)) {
ARegion *ar = scalear->prev;
@@ -3582,6 +3564,12 @@ static int repeat_last_exec(bContext *C, wmOperator *UNUSED(op))
return OPERATOR_CANCELLED;
}
+static bool repeat_last_poll(bContext *C)
+{
+ wmWindowManager *wm = CTX_wm_manager(C);
+ return ED_operator_screenactive(C) && !BLI_listbase_is_empty(&wm->operators);
+}
+
static void SCREEN_OT_repeat_last(wmOperatorType *ot)
{
/* identifiers */
@@ -3592,7 +3580,7 @@ static void SCREEN_OT_repeat_last(wmOperatorType *ot)
/* api callbacks */
ot->exec = repeat_last_exec;
- ot->poll = ED_operator_screenactive;
+ ot->poll = repeat_last_poll;
}
/** \} */
@@ -3645,6 +3633,12 @@ static int repeat_history_exec(bContext *C, wmOperator *op)
return OPERATOR_FINISHED;
}
+static bool repeat_history_poll(bContext *C)
+{
+ wmWindowManager *wm = CTX_wm_manager(C);
+ return ED_operator_screenactive(C) && !BLI_listbase_is_empty(&wm->operators);
+}
+
static void SCREEN_OT_repeat_history(wmOperatorType *ot)
{
/* identifiers */
@@ -3656,7 +3650,7 @@ static void SCREEN_OT_repeat_history(wmOperatorType *ot)
ot->invoke = repeat_history_invoke;
ot->exec = repeat_history_exec;
- ot->poll = ED_operator_screenactive;
+ ot->poll = repeat_history_poll;
RNA_def_int(ot->srna, "index", 0, 0, INT_MAX, "Index", "", 0, 1000);
}
@@ -3678,6 +3672,12 @@ static int redo_last_invoke(bContext *C, wmOperator *UNUSED(op), const wmEvent *
return OPERATOR_CANCELLED;
}
+static bool redo_last_poll(bContext *C)
+{
+ wmWindowManager *wm = CTX_wm_manager(C);
+ return ED_operator_screenactive(C) && !BLI_listbase_is_empty(&wm->operators);
+}
+
static void SCREEN_OT_redo_last(wmOperatorType *ot)
{
/* identifiers */
@@ -3688,7 +3688,7 @@ static void SCREEN_OT_redo_last(wmOperatorType *ot)
/* api callbacks */
ot->invoke = redo_last_invoke;
- ot->poll = ED_operator_screenactive;
+ ot->poll = redo_last_poll;
}
/** \} */
@@ -3955,10 +3955,10 @@ static void SCREEN_OT_header_toggle_menus(wmOperatorType *ot)
/** \} */
/* -------------------------------------------------------------------- */
-/** \name Header Tools Operator
+/** \name Region Context Menu Operator (Header/Footer/Navbar)
* \{ */
-static bool header_context_menu_poll(bContext *C)
+static bool screen_region_context_menu_poll(bContext *C)
{
ScrArea *sa = CTX_wm_area(C);
return (sa && sa->spacetype != SPACE_STATUSBAR);
@@ -4008,89 +4008,17 @@ void ED_screens_header_tools_menu_create(bContext *C, uiLayout *layout, void *UN
}
}
-static int header_context_menu_invoke(bContext *C,
- wmOperator *UNUSED(op),
- const wmEvent *UNUSED(event))
-{
- uiPopupMenu *pup;
- uiLayout *layout;
-
- pup = UI_popup_menu_begin(C, IFACE_("Header"), ICON_NONE);
- layout = UI_popup_menu_layout(pup);
-
- ED_screens_header_tools_menu_create(C, layout, NULL);
-
- UI_popup_menu_end(C, pup);
-
- return OPERATOR_INTERFACE;
-}
-
-static void SCREEN_OT_header_context_menu(wmOperatorType *ot)
-{
- /* identifiers */
- ot->name = "Header Context Menu";
- ot->description = "Display header region context menu";
- ot->idname = "SCREEN_OT_header_context_menu";
-
- /* api callbacks */
- ot->poll = header_context_menu_poll;
- ot->invoke = header_context_menu_invoke;
-}
-
-/** \} */
-
-/* -------------------------------------------------------------------- */
-/** \name Footer Toggle Operator
- * \{ */
-
-static int footer_exec(bContext *C, wmOperator *UNUSED(op))
-{
- ARegion *ar = screen_find_region_type(C, RGN_TYPE_FOOTER);
-
- if (ar == NULL) {
- return OPERATOR_CANCELLED;
- }
-
- ar->flag ^= RGN_FLAG_HIDDEN;
-
- ED_area_tag_redraw(CTX_wm_area(C));
-
- WM_event_add_notifier(C, NC_SCREEN | NA_EDITED, NULL);
-
- return OPERATOR_FINISHED;
-}
-
-static void SCREEN_OT_footer(wmOperatorType *ot)
-{
- /* identifiers */
- ot->name = "Toggle Footer";
- ot->description = "Toggle footer display";
- ot->idname = "SCREEN_OT_footer";
-
- /* api callbacks */
- ot->exec = footer_exec;
-}
-
-/** \} */
-
-/* -------------------------------------------------------------------- */
-/** \name Footer Tools Operator
- * \{ */
-
-static bool footer_context_menu_poll(bContext *C)
-{
- ScrArea *sa = CTX_wm_area(C);
- return sa;
-}
-
void ED_screens_footer_tools_menu_create(bContext *C, uiLayout *layout, void *UNUSED(arg))
{
ScrArea *sa = CTX_wm_area(C);
ARegion *ar = CTX_wm_region(C);
const char *but_flip_str = (ar->alignment == RGN_ALIGN_TOP) ? IFACE_("Flip to Bottom") :
IFACE_("Flip to Top");
-
- uiItemO(layout, IFACE_("Toggle Footer"), ICON_NONE, "SCREEN_OT_footer");
+ {
+ PointerRNA ptr;
+ RNA_pointer_create((ID *)CTX_wm_screen(C), &RNA_Space, sa->spacedata.first, &ptr);
+ uiItemR(layout, &ptr, "show_region_footer", 0, IFACE_("Show Footer"), ICON_NONE);
+ }
/* default is WM_OP_INVOKE_REGION_WIN, which we don't want here. */
uiLayoutSetOperatorContext(layout, WM_OP_INVOKE_DEFAULT);
@@ -4107,51 +4035,58 @@ void ED_screens_footer_tools_menu_create(bContext *C, uiLayout *layout, void *UN
}
}
-static int footer_context_menu_invoke(bContext *C,
+void ED_screens_navigation_bar_tools_menu_create(bContext *C, uiLayout *layout, void *UNUSED(arg))
+{
+ const ARegion *ar = CTX_wm_region(C);
+ const char *but_flip_str = (ar->alignment == RGN_ALIGN_LEFT) ? IFACE_("Flip to Right") :
+ IFACE_("Flip to Left");
+
+ /* default is WM_OP_INVOKE_REGION_WIN, which we don't want here. */
+ uiLayoutSetOperatorContext(layout, WM_OP_INVOKE_DEFAULT);
+
+ uiItemO(layout, but_flip_str, ICON_NONE, "SCREEN_OT_region_flip");
+}
+
+static int screen_context_menu_invoke(bContext *C,
wmOperator *UNUSED(op),
const wmEvent *UNUSED(event))
{
uiPopupMenu *pup;
uiLayout *layout;
+ const ARegion *ar = CTX_wm_region(C);
- pup = UI_popup_menu_begin(C, IFACE_("Footer"), ICON_NONE);
- layout = UI_popup_menu_layout(pup);
-
- ED_screens_footer_tools_menu_create(C, layout, NULL);
-
- UI_popup_menu_end(C, pup);
+ if (ELEM(ar->regiontype, RGN_TYPE_HEADER, RGN_TYPE_TOOL_HEADER)) {
+ pup = UI_popup_menu_begin(C, IFACE_("Header"), ICON_NONE);
+ layout = UI_popup_menu_layout(pup);
+ ED_screens_header_tools_menu_create(C, layout, NULL);
+ UI_popup_menu_end(C, pup);
+ }
+ else if (ar->regiontype == RGN_TYPE_FOOTER) {
+ pup = UI_popup_menu_begin(C, IFACE_("Footer"), ICON_NONE);
+ layout = UI_popup_menu_layout(pup);
+ ED_screens_footer_tools_menu_create(C, layout, NULL);
+ UI_popup_menu_end(C, pup);
+ }
+ else if (ar->regiontype == RGN_TYPE_NAV_BAR) {
+ pup = UI_popup_menu_begin(C, IFACE_("Navigation Bar"), ICON_NONE);
+ layout = UI_popup_menu_layout(pup);
+ ED_screens_navigation_bar_tools_menu_create(C, layout, NULL);
+ UI_popup_menu_end(C, pup);
+ }
return OPERATOR_INTERFACE;
}
-static void SCREEN_OT_footer_context_menu(wmOperatorType *ot)
+static void SCREEN_OT_region_context_menu(wmOperatorType *ot)
{
/* identifiers */
- ot->name = "Footer Context Menu";
- ot->description = "Display footer region context menu";
- ot->idname = "SCREEN_OT_footer_context_menu";
+ ot->name = "Region Context Menu";
+ ot->description = "Display region context menu";
+ ot->idname = "SCREEN_OT_region_context_menu";
/* api callbacks */
- ot->poll = footer_context_menu_poll;
- ot->invoke = footer_context_menu_invoke;
-}
-
-/** \} */
-
-/* -------------------------------------------------------------------- */
-/** \name Navigation Bar Tools Menu
- * \{ */
-
-void ED_screens_navigation_bar_tools_menu_create(bContext *C, uiLayout *layout, void *UNUSED(arg))
-{
- const ARegion *ar = CTX_wm_region(C);
- const char *but_flip_str = (ar->alignment == RGN_ALIGN_LEFT) ? IFACE_("Flip to Right") :
- IFACE_("Flip to Left");
-
- /* default is WM_OP_INVOKE_REGION_WIN, which we don't want here. */
- uiLayoutSetOperatorContext(layout, WM_OP_INVOKE_DEFAULT);
-
- uiItemO(layout, but_flip_str, ICON_NONE, "SCREEN_OT_region_flip");
+ ot->poll = screen_region_context_menu_poll;
+ ot->invoke = screen_context_menu_invoke;
}
/** \} */
@@ -5299,9 +5234,7 @@ void ED_operatortypes_screen(void)
WM_operatortype_append(SCREEN_OT_region_scale);
WM_operatortype_append(SCREEN_OT_region_flip);
WM_operatortype_append(SCREEN_OT_header_toggle_menus);
- WM_operatortype_append(SCREEN_OT_header_context_menu);
- WM_operatortype_append(SCREEN_OT_footer);
- WM_operatortype_append(SCREEN_OT_footer_context_menu);
+ WM_operatortype_append(SCREEN_OT_region_context_menu);
WM_operatortype_append(SCREEN_OT_screen_set);
WM_operatortype_append(SCREEN_OT_screen_full_area);
WM_operatortype_append(SCREEN_OT_back_to_previous);
diff --git a/source/blender/editors/screen/workspace_edit.c b/source/blender/editors/screen/workspace_edit.c
index 6294a64af0f..863e3a15120 100644
--- a/source/blender/editors/screen/workspace_edit.c
+++ b/source/blender/editors/screen/workspace_edit.c
@@ -165,7 +165,9 @@ bool ED_workspace_change(WorkSpace *workspace_new, bContext *C, wmWindowManager
}
screen_new = screen_change_prepare(screen_old, screen_new, bmain, C, win);
- BLI_assert(BKE_workspace_layout_screen_get(layout_new) == screen_new);
+ if (BKE_workspace_layout_screen_get(layout_new) != screen_new) {
+ layout_new = BKE_workspace_layout_find(workspace_new, screen_new);
+ }
if (screen_new == NULL) {
return false;
@@ -371,13 +373,15 @@ static int workspace_append_activate_exec(bContext *C, wmOperator *op)
&bmain->workspaces, idname, offsetof(ID, name) + 2);
BLI_assert(appended_workspace != NULL);
- /* Reorder to last position. */
- BKE_id_reorder(&bmain->workspaces, &appended_workspace->id, NULL, true);
+ if (appended_workspace) {
+ /* Reorder to last position. */
+ BKE_id_reorder(&bmain->workspaces, &appended_workspace->id, NULL, true);
- /* Changing workspace changes context. Do delayed! */
- WM_event_add_notifier(C, NC_SCREEN | ND_WORKSPACE_SET, appended_workspace);
+ /* Changing workspace changes context. Do delayed! */
+ WM_event_add_notifier(C, NC_SCREEN | ND_WORKSPACE_SET, appended_workspace);
- return OPERATOR_FINISHED;
+ return OPERATOR_FINISHED;
+ }
}
return OPERATOR_CANCELLED;
diff --git a/source/blender/editors/sculpt_paint/paint_image.c b/source/blender/editors/sculpt_paint/paint_image.c
index 5a45f4946f2..f7a589350f9 100644
--- a/source/blender/editors/sculpt_paint/paint_image.c
+++ b/source/blender/editors/sculpt_paint/paint_image.c
@@ -47,6 +47,7 @@
#include "BKE_colorband.h"
#include "BKE_context.h"
#include "BKE_brush.h"
+#include "BKE_image.h"
#include "BKE_main.h"
#include "BKE_material.h"
#include "BKE_mesh.h"
@@ -154,7 +155,7 @@ void ED_imapaint_dirty_region(Image *ima, ImBuf *ibuf, int x, int y, int w, int
}
}
- ibuf->userflags |= IB_BITMAPDIRTY;
+ BKE_image_mark_dirty(ima, ibuf);
if (tmpibuf) {
IMB_freeImBuf(tmpibuf);
diff --git a/source/blender/editors/sculpt_paint/paint_image_proj.c b/source/blender/editors/sculpt_paint/paint_image_proj.c
index 0737218eea4..303c3fac363 100644
--- a/source/blender/editors/sculpt_paint/paint_image_proj.c
+++ b/source/blender/editors/sculpt_paint/paint_image_proj.c
@@ -1837,7 +1837,7 @@ static int project_paint_undo_subtiles(const TileInfo *tinf, int tx, int ty)
false);
}
- pjIma->ibuf->userflags |= IB_BITMAPDIRTY;
+ BKE_image_mark_dirty(pjIma->ima, pjIma->ibuf);
/* tile ready, publish */
if (tinf->lock) {
BLI_spin_lock(tinf->lock);
@@ -1895,7 +1895,7 @@ static ProjPixel *project_paint_uvpixel_init(const ProjPaintState *ps,
/* other thread may be initializing the tile so wait here */
while (projima->undoRect[tile_index] == TILE_PENDING) {
- ;
+ /* pass */
}
BLI_assert(tile_index < (IMAPAINT_TILE_NUMBER(ibuf->x) * IMAPAINT_TILE_NUMBER(ibuf->y)));
@@ -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,
@@ -6394,7 +6393,7 @@ static const EnumPropertyItem layer_type_items[] = {
{0, NULL, 0, NULL, NULL},
};
-static Image *proj_paint_image_create(wmOperator *op, Main *bmain)
+static Image *proj_paint_image_create(wmOperator *op, Main *bmain, bool is_data)
{
Image *ima;
float color[4] = {0.0f, 0.0f, 0.0f, 1.0f};
@@ -6417,6 +6416,11 @@ static Image *proj_paint_image_create(wmOperator *op, Main *bmain)
ima = BKE_image_add_generated(
bmain, width, height, imagename, alpha ? 32 : 24, use_float, gen_type, color, false);
+ if (is_data) {
+ STRNCPY(ima->colorspace_settings.name,
+ IMB_colormanagement_role_colorspace_name_get(COLOR_ROLE_DATA));
+ }
+
return ima;
}
@@ -6487,6 +6491,7 @@ static bool proj_paint_add_slot(bContext *C, wmOperator *op)
if (ma) {
Main *bmain = CTX_data_main(C);
int type = RNA_enum_get(op->ptr, "type");
+ bool is_data = (type > LAYER_BASE_COLOR);
bNode *imanode;
bNodeTree *ntree = ma->nodetree;
@@ -6501,7 +6506,7 @@ static bool proj_paint_add_slot(bContext *C, wmOperator *op)
/* try to add an image node */
imanode = nodeAddStaticNode(C, ntree, SH_NODE_TEX_IMAGE);
- ima = proj_paint_image_create(op, bmain);
+ ima = proj_paint_image_create(op, bmain, is_data);
imanode->id = &ima->id;
nodeSetActive(ntree, imanode);
@@ -6553,12 +6558,6 @@ static bool proj_paint_add_slot(bContext *C, wmOperator *op)
}
}
- if (type > LAYER_BASE_COLOR) {
- /* This is a "non color data" image */
- NodeTexImage *tex = imanode->storage;
- tex->color_space = SHD_COLORSPACE_NONE;
- }
-
/* Check if the socket in already connected to something */
bNodeLink *link = in_sock ? in_sock->link : NULL;
if (in_sock != NULL && link == NULL) {
diff --git a/source/blender/editors/sculpt_paint/paint_image_undo.c b/source/blender/editors/sculpt_paint/paint_image_undo.c
index b80144ac4af..bb73d424152 100644
--- a/source/blender/editors/sculpt_paint/paint_image_undo.c
+++ b/source/blender/editors/sculpt_paint/paint_image_undo.c
@@ -349,7 +349,9 @@ static void image_undo_restore_list(ListBase *lb, struct UndoIDPtrMap *id_map)
undo_copy_tile(tile, tmpibuf, ibuf, RESTORE_COPY);
+ BKE_image_mark_dirty(ima, ibuf);
GPU_free_image(ima); /* force OpenGL reload */
+
if (ibuf->rect_float) {
ibuf->userflags |= IB_RECT_INVALID; /* force recreate of char rect */
}
diff --git a/source/blender/editors/sculpt_paint/paint_utils.c b/source/blender/editors/sculpt_paint/paint_utils.c
index 6d003820723..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"
@@ -389,7 +390,8 @@ static int imapaint_pick_face(ViewContext *vc,
}
/* sample only on the exact position */
- *r_index = ED_view3d_select_id_sample(vc, mval[0], mval[1]);
+ ED_view3d_select_id_validate(vc);
+ *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 c1c2964156f..b6a6c897606 100644
--- a/source/blender/editors/sculpt_paint/paint_vertex_weight_ops.c
+++ b/source/blender/editors/sculpt_paint/paint_vertex_weight_ops.c
@@ -161,7 +161,7 @@ void PAINT_OT_weight_from_bones(wmOperatorType *ot)
ot->poll = weight_from_bones_poll;
/* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_USE_EVAL_DATA;
/* properties */
ot->prop = RNA_def_enum(
@@ -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) {
@@ -880,7 +880,7 @@ void PAINT_OT_weight_gradient(wmOperatorType *ot)
ot->cancel = WM_gesture_straightline_cancel;
/* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_USE_EVAL_DATA;
prop = RNA_def_enum(ot->srna, "type", gradient_types, 0, "Type", "");
RNA_def_property_flag(prop, PROP_SKIP_SAVE);
diff --git a/source/blender/editors/sculpt_paint/sculpt_uv.c b/source/blender/editors/sculpt_paint/sculpt_uv.c
index 3356edd6b36..36cc3605273 100644
--- a/source/blender/editors/sculpt_paint/sculpt_uv.c
+++ b/source/blender/editors/sculpt_paint/sculpt_uv.c
@@ -600,7 +600,7 @@ static UvSculptData *uv_sculpt_stroke_init(bContext *C, wmOperator *op, const wm
if (do_island_optimization && (element->island != island_index)) {
/* skip this uv if not on the active island */
for (; element->next && !(element->next->separate); element = element->next) {
- ;
+ /* pass */
}
continue;
}
diff --git a/source/blender/editors/sound/sound_ops.c b/source/blender/editors/sound/sound_ops.c
index 25c05e2d1d0..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(&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 db504272d2f..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(&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(&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(&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/action_draw.c b/source/blender/editors/space_action/action_draw.c
index 9827967f947..f32207fe08b 100644
--- a/source/blender/editors/space_action/action_draw.c
+++ b/source/blender/editors/space_action/action_draw.c
@@ -71,68 +71,50 @@ void draw_channel_names(bContext *C, bAnimContext *ac, ARegion *ar)
int filter;
View2D *v2d = &ar->v2d;
- float y = 0.0f;
size_t items;
- int height;
/* build list of channels to draw */
filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE | ANIMFILTER_LIST_CHANNELS);
items = ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype);
- height = ((items * ACHANNEL_STEP(ac)) + (ACHANNEL_HEIGHT(ac)));
- if (height > BLI_rcti_size_y(&v2d->mask)) {
- /* don't use totrect set, as the width stays the same
- * (NOTE: this is ok here, the configuration is pretty straightforward)
- */
- v2d->tot.ymin = (float)(-height);
- }
+ int height = ACHANNEL_TOT_HEIGHT(ac, items);
+ v2d->tot.ymin = -height;
+
/* need to do a view-sync here, so that the keys area doesn't jump around (it must copy this) */
UI_view2d_sync(NULL, ac->sa, v2d, V2D_LOCK_COPY);
/* loop through channels, and set up drawing depending on their type */
{ /* first pass: just the standard GL-drawing for backdrop + text */
size_t channel_index = 0;
+ float ymax = ACHANNEL_FIRST_TOP(ac);
- y = (float)ACHANNEL_FIRST(ac);
-
- for (ale = anim_data.first; ale; ale = ale->next) {
- float yminc = (float)(y - ACHANNEL_HEIGHT_HALF(ac));
- float ymaxc = (float)(y + ACHANNEL_HEIGHT_HALF(ac));
+ for (ale = anim_data.first; ale; ale = ale->next, ymax -= ACHANNEL_STEP(ac), channel_index++) {
+ float ymin = ymax - ACHANNEL_HEIGHT(ac);
/* check if visible */
- if (IN_RANGE(yminc, v2d->cur.ymin, v2d->cur.ymax) ||
- IN_RANGE(ymaxc, v2d->cur.ymin, v2d->cur.ymax)) {
+ if (IN_RANGE(ymin, v2d->cur.ymin, v2d->cur.ymax) ||
+ IN_RANGE(ymax, v2d->cur.ymin, v2d->cur.ymax)) {
/* draw all channels using standard channel-drawing API */
- ANIM_channel_draw(ac, ale, yminc, ymaxc, channel_index);
+ ANIM_channel_draw(ac, ale, ymin, ymax, channel_index);
}
-
- /* adjust y-position for next one */
- y -= ACHANNEL_STEP(ac);
- channel_index++;
}
}
{ /* second pass: widgets */
uiBlock *block = UI_block_begin(C, ar, __func__, UI_EMBOSS);
size_t channel_index = 0;
+ float ymax = ACHANNEL_FIRST_TOP(ac);
- y = (float)ACHANNEL_FIRST(ac);
-
- for (ale = anim_data.first; ale; ale = ale->next) {
- float yminc = (float)(y - ACHANNEL_HEIGHT_HALF(ac));
- float ymaxc = (float)(y + ACHANNEL_HEIGHT_HALF(ac));
+ for (ale = anim_data.first; ale; ale = ale->next, ymax -= ACHANNEL_STEP(ac), channel_index++) {
+ float ymin = ymax - ACHANNEL_HEIGHT(ac);
/* check if visible */
- if (IN_RANGE(yminc, v2d->cur.ymin, v2d->cur.ymax) ||
- IN_RANGE(ymaxc, v2d->cur.ymin, v2d->cur.ymax)) {
+ if (IN_RANGE(ymin, v2d->cur.ymin, v2d->cur.ymax) ||
+ IN_RANGE(ymax, v2d->cur.ymin, v2d->cur.ymax)) {
/* draw all channels using standard channel-drawing API */
rctf channel_rect;
- BLI_rctf_init(&channel_rect, 0, v2d->cur.xmax, yminc, ymaxc);
+ BLI_rctf_init(&channel_rect, 0, v2d->cur.xmax, ymin, ymax);
ANIM_channel_draw_widgets(C, ac, ale, block, &channel_rect, channel_index);
}
-
- /* adjust y-position for next one */
- y -= ACHANNEL_STEP(ac);
- channel_index++;
}
UI_block_end(C, block);
@@ -159,8 +141,6 @@ void draw_channel_strips(bAnimContext *ac, SpaceAction *saction, ARegion *ar)
bDopeSheet *ads = &saction->ads;
AnimData *adt = NULL;
- float y;
-
unsigned char col1[4], col2[4];
unsigned char col1a[4], col2a[4];
unsigned char col1b[4], col2b[4];
@@ -181,14 +161,8 @@ void draw_channel_strips(bAnimContext *ac, SpaceAction *saction, ARegion *ar)
int filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE | ANIMFILTER_LIST_CHANNELS);
size_t items = ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype);
- int height = ((items * ACHANNEL_STEP(ac)) + (ACHANNEL_HEIGHT(ac)));
- /* don't use totrect set, as the width stays the same
- * (NOTE: this is ok here, the configuration is pretty straightforward)
- */
- v2d->tot.ymin = (float)(-height);
-
- /* first backdrop strips */
- y = (float)(-ACHANNEL_HEIGHT(ac));
+ int height = ACHANNEL_TOT_HEIGHT(ac, items);
+ v2d->tot.ymin = -height;
GPUVertFormat *format = immVertexFormat();
uint pos = GPU_vertformat_attr_add(format, "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
@@ -197,13 +171,15 @@ void draw_channel_strips(bAnimContext *ac, SpaceAction *saction, ARegion *ar)
GPU_blend(true);
- for (ale = anim_data.first; ale; ale = ale->next) {
- const float yminc = (float)(y - ACHANNEL_HEIGHT_HALF(ac));
- const float ymaxc = (float)(y + ACHANNEL_HEIGHT_HALF(ac));
+ /* first backdrop strips */
+ float ymax = ACHANNEL_FIRST_TOP(ac);
+
+ for (ale = anim_data.first; ale; ale = ale->next, ymax -= ACHANNEL_STEP(ac)) {
+ float ymin = ymax - ACHANNEL_HEIGHT(ac);
/* check if visible */
- if (IN_RANGE(yminc, v2d->cur.ymin, v2d->cur.ymax) ||
- IN_RANGE(ymaxc, v2d->cur.ymin, v2d->cur.ymax)) {
+ if (IN_RANGE(ymin, v2d->cur.ymin, v2d->cur.ymax) ||
+ IN_RANGE(ymax, v2d->cur.ymin, v2d->cur.ymax)) {
const bAnimChannelType *acf = ANIM_channel_get_typeinfo(ale);
int sel = 0;
@@ -264,11 +240,7 @@ void draw_channel_strips(bAnimContext *ac, SpaceAction *saction, ARegion *ar)
}
/* draw region twice: firstly backdrop, then the current range */
- immRectf(pos,
- v2d->cur.xmin,
- (float)y - ACHANNEL_HEIGHT_HALF(ac),
- v2d->cur.xmax + EXTRA_SCROLL_PAD,
- (float)y + ACHANNEL_HEIGHT_HALF(ac));
+ immRectf(pos, v2d->cur.xmin, ymin, v2d->cur.xmax + EXTRA_SCROLL_PAD, ymax);
}
else if (ac->datatype == ANIMCONT_GPENCIL) {
unsigned char *color;
@@ -285,44 +257,25 @@ void draw_channel_strips(bAnimContext *ac, SpaceAction *saction, ARegion *ar)
}
/* frames less than one get less saturated background */
immUniformColor4ubv(color);
- immRectf(pos,
- 0.0f,
- (float)y - ACHANNEL_HEIGHT_HALF(ac),
- v2d->cur.xmin,
- (float)y + ACHANNEL_HEIGHT_HALF(ac));
+ immRectf(pos, 0.0f, ymin, v2d->cur.xmin, ymax);
/* frames one and higher get a saturated background */
immUniformColor3ubvAlpha(color, MIN2(255, color[3] * 2));
- immRectf(pos,
- v2d->cur.xmin,
- (float)y - ACHANNEL_HEIGHT_HALF(ac),
- v2d->cur.xmax + EXTRA_SCROLL_PAD,
- (float)y + ACHANNEL_HEIGHT_HALF(ac));
+ immRectf(pos, v2d->cur.xmin, ymin, v2d->cur.xmax + EXTRA_SCROLL_PAD, ymax);
}
else if (ac->datatype == ANIMCONT_MASK) {
/* TODO --- this is a copy of gpencil */
/* frames less than one get less saturated background */
unsigned char *color = sel ? col1 : col2;
immUniformColor4ubv(color);
- immRectf(pos,
- 0.0f,
- (float)y - ACHANNEL_HEIGHT_HALF(ac),
- v2d->cur.xmin,
- (float)y + ACHANNEL_HEIGHT_HALF(ac));
+ immRectf(pos, 0.0f, ymin, v2d->cur.xmin, ymax);
/* frames one and higher get a saturated background */
immUniformColor3ubvAlpha(color, MIN2(255, color[3] * 2));
- immRectf(pos,
- v2d->cur.xmin,
- (float)y - ACHANNEL_HEIGHT_HALF(ac),
- v2d->cur.xmax + EXTRA_SCROLL_PAD,
- (float)y + ACHANNEL_HEIGHT_HALF(ac));
+ immRectf(pos, v2d->cur.xmin, ymin, v2d->cur.xmax + EXTRA_SCROLL_PAD, ymax);
}
}
}
-
- /* Increment the step */
- y -= ACHANNEL_STEP(ac);
}
GPU_blend(false);
@@ -342,21 +295,21 @@ void draw_channel_strips(bAnimContext *ac, SpaceAction *saction, ARegion *ar)
* This is to try to optimize this for heavier data sets
* 2) Keyframes which are out of view horizontally are disregarded
*/
- y = (float)(-ACHANNEL_HEIGHT(ac));
-
int action_flag = saction->flag;
if (saction->mode == SACTCONT_TIMELINE) {
action_flag &= ~(SACTION_SHOW_INTERPOLATION | SACTION_SHOW_EXTREMES);
}
- for (ale = anim_data.first; ale; ale = ale->next) {
- const float yminc = (float)(y - ACHANNEL_HEIGHT_HALF(ac));
- const float ymaxc = (float)(y + ACHANNEL_HEIGHT_HALF(ac));
+ ymax = ACHANNEL_FIRST_TOP(ac);
+
+ for (ale = anim_data.first; ale; ale = ale->next, ymax -= ACHANNEL_STEP(ac)) {
+ float ymin = ymax - ACHANNEL_HEIGHT(ac);
+ float ycenter = (ymin + ymax) / 2.0f;
/* check if visible */
- if (IN_RANGE(yminc, v2d->cur.ymin, v2d->cur.ymax) ||
- IN_RANGE(ymaxc, v2d->cur.ymin, v2d->cur.ymax)) {
+ if (IN_RANGE(ymin, v2d->cur.ymin, v2d->cur.ymax) ||
+ IN_RANGE(ymax, v2d->cur.ymin, v2d->cur.ymax)) {
/* check if anything to show for this channel */
if (ale->datatype != ALE_NONE) {
adt = ANIM_nla_mapping_get(ac, ale);
@@ -364,34 +317,32 @@ void draw_channel_strips(bAnimContext *ac, SpaceAction *saction, ARegion *ar)
/* draw 'keyframes' for each specific datatype */
switch (ale->datatype) {
case ALE_ALL:
- draw_summary_channel(v2d, ale->data, y, ac->yscale_fac, action_flag);
+ draw_summary_channel(v2d, ale->data, ycenter, ac->yscale_fac, action_flag);
break;
case ALE_SCE:
- draw_scene_channel(v2d, ads, ale->key_data, y, ac->yscale_fac, action_flag);
+ draw_scene_channel(v2d, ads, ale->key_data, ycenter, ac->yscale_fac, action_flag);
break;
case ALE_OB:
- draw_object_channel(v2d, ads, ale->key_data, y, ac->yscale_fac, action_flag);
+ draw_object_channel(v2d, ads, ale->key_data, ycenter, ac->yscale_fac, action_flag);
break;
case ALE_ACT:
- draw_action_channel(v2d, adt, ale->key_data, y, ac->yscale_fac, action_flag);
+ draw_action_channel(v2d, adt, ale->key_data, ycenter, ac->yscale_fac, action_flag);
break;
case ALE_GROUP:
- draw_agroup_channel(v2d, adt, ale->data, y, ac->yscale_fac, action_flag);
+ draw_agroup_channel(v2d, adt, ale->data, ycenter, ac->yscale_fac, action_flag);
break;
case ALE_FCURVE:
- draw_fcurve_channel(v2d, adt, ale->key_data, y, ac->yscale_fac, action_flag);
+ draw_fcurve_channel(v2d, adt, ale->key_data, ycenter, ac->yscale_fac, action_flag);
break;
case ALE_GPFRAME:
- draw_gpl_channel(v2d, ads, ale->data, y, ac->yscale_fac, action_flag);
+ draw_gpl_channel(v2d, ads, ale->data, ycenter, ac->yscale_fac, action_flag);
break;
case ALE_MASKLAY:
- draw_masklay_channel(v2d, ads, ale->data, y, ac->yscale_fac, action_flag);
+ draw_masklay_channel(v2d, ads, ale->data, ycenter, ac->yscale_fac, action_flag);
break;
}
}
}
-
- y -= ACHANNEL_STEP(ac);
}
/* free temporary channels used for drawing */
@@ -460,7 +411,7 @@ void timeline_draw_cache(SpaceAction *saction, Object *ob, Scene *scene)
}
GPU_matrix_push();
- GPU_matrix_translate_2f(0.0, (float)V2D_SCROLL_HEIGHT_TEXT + yoffs);
+ GPU_matrix_translate_2f(0.0, (float)V2D_SCROLL_HEIGHT_HANDLES + yoffs);
GPU_matrix_scale_2f(1.0, cache_draw_height);
switch (pid->type) {
diff --git a/source/blender/editors/space_action/action_edit.c b/source/blender/editors/space_action/action_edit.c
index 8df773e98d6..7fc84db3f75 100644
--- a/source/blender/editors/space_action/action_edit.c
+++ b/source/blender/editors/space_action/action_edit.c
@@ -325,24 +325,23 @@ static bool actkeys_channels_get_selected_extents(bAnimContext *ac, float *min,
/* NOTE: not bool, since we want prioritise individual channels over expanders */
short found = 0;
- float y;
/* get all items - we need to do it this way */
filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE | ANIMFILTER_LIST_CHANNELS);
ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype);
/* loop through all channels, finding the first one that's selected */
- y = (float)ACHANNEL_FIRST(ac);
+ float ymax = ACHANNEL_FIRST_TOP(ac);
- for (ale = anim_data.first; ale; ale = ale->next) {
+ for (ale = anim_data.first; ale; ale = ale->next, ymax -= ACHANNEL_STEP(ac)) {
const bAnimChannelType *acf = ANIM_channel_get_typeinfo(ale);
/* must be selected... */
if (acf && acf->has_setting(ac, ale, ACHANNEL_SETTING_SELECT) &&
ANIM_channel_setting_get(ac, ale, ACHANNEL_SETTING_SELECT)) {
/* update best estimate */
- *min = (float)(y - ACHANNEL_HEIGHT_HALF(ac));
- *max = (float)(y + ACHANNEL_HEIGHT_HALF(ac));
+ *min = ymax - ACHANNEL_HEIGHT(ac);
+ *max = ymax;
/* is this high enough priority yet? */
found = acf->channel_role;
@@ -354,9 +353,6 @@ static bool actkeys_channels_get_selected_extents(bAnimContext *ac, float *min,
break;
}
}
-
- /* adjust y-position for next one */
- y -= ACHANNEL_STEP(ac);
}
/* free all temp data */
@@ -983,8 +979,7 @@ static bool delete_action_keys(bAnimContext *ac)
changed = delete_fcurve_keys(fcu);
/* Only delete curve too if it won't be doing anything anymore */
- if ((fcu->totvert == 0) &&
- (list_has_suitable_fmodifier(&fcu->modifiers, 0, FMI_TYPE_GENERATE_CURVE) == 0)) {
+ if (BKE_fcurve_is_empty(fcu)) {
ANIM_fcurve_delete_from_animdata(ac, adt, fcu);
ale->key_data = NULL;
}
diff --git a/source/blender/editors/space_action/action_select.c b/source/blender/editors/space_action/action_select.c
index 1614e1c432d..1371305487e 100644
--- a/source/blender/editors/space_action/action_select.c
+++ b/source/blender/editors/space_action/action_select.c
@@ -47,6 +47,7 @@
#include "BKE_gpencil.h"
#include "UI_view2d.h"
+#include "UI_interface.h"
#include "ED_anim_api.h"
#include "ED_gpencil.h"
@@ -230,7 +231,6 @@ static void box_select_action(bAnimContext *ac, const rcti rect, short mode, sho
KeyframeEditFunc ok_cb, select_cb;
View2D *v2d = &ac->ar->v2d;
rctf rectf;
- float ymin = 0, ymax = (float)(-ACHANNEL_HEIGHT_HALF(ac));
/* Convert mouse coordinates to frame ranges and channel
* coordinates corrected for view pan/zoom. */
@@ -254,12 +254,14 @@ static void box_select_action(bAnimContext *ac, const rcti rect, short mode, sho
/* init editing data */
memset(&ked, 0, sizeof(KeyframeEditData));
+ float ymax = ACHANNEL_FIRST_TOP(ac);
+
/* loop over data, doing box select */
- for (ale = anim_data.first; ale; ale = ale->next) {
+ for (ale = anim_data.first; ale; ale = ale->next, ymax -= ACHANNEL_STEP(ac)) {
AnimData *adt = ANIM_nla_mapping_get(ac, ale);
/* get new vertical minimum extent of channel */
- ymin = ymax - ACHANNEL_STEP(ac);
+ float ymin = ymax - ACHANNEL_STEP(ac);
/* set horizontal range (if applicable) */
if (ELEM(mode, ACTKEYS_BORDERSEL_FRAMERANGE, ACTKEYS_BORDERSEL_ALLKEYS)) {
@@ -314,9 +316,6 @@ static void box_select_action(bAnimContext *ac, const rcti rect, short mode, sho
}
}
}
-
- /* set minimum extent to be the maximum of the next channel */
- ymax = ymin;
}
/* cleanup */
@@ -418,7 +417,6 @@ static void region_select_action_keys(
KeyframeEditFunc ok_cb, select_cb;
View2D *v2d = &ac->ar->v2d;
rctf rectf, scaled_rectf;
- float ymin = 0, ymax = (float)(-ACHANNEL_HEIGHT_HALF(ac));
/* Convert mouse coordinates to frame ranges and channel
* coordinates corrected for view pan/zoom. */
@@ -448,15 +446,17 @@ static void region_select_action_keys(
ked.data = &scaled_rectf;
}
+ float ymax = ACHANNEL_FIRST_TOP(ac);
+
/* loop over data, doing region select */
- for (ale = anim_data.first; ale; ale = ale->next) {
+ for (ale = anim_data.first; ale; ale = ale->next, ymax -= ACHANNEL_STEP(ac)) {
AnimData *adt = ANIM_nla_mapping_get(ac, ale);
/* get new vertical minimum extent of channel */
- ymin = ymax - ACHANNEL_STEP(ac);
+ float ymin = ymax - ACHANNEL_STEP(ac);
/* compute midpoint of channel (used for testing if the key is in the region or not) */
- ked.channel_y = ymin + ACHANNEL_HEIGHT_HALF(ac);
+ ked.channel_y = (ymin + ymax) / 2.0f;
/* if channel is mapped in NLA, apply correction
* - Apply to the bounds being checked, not all the keyframe points,
@@ -520,9 +520,6 @@ static void region_select_action_keys(
break;
}
}
-
- /* set minimum extent to be the maximum of the next channel */
- ymax = ymin;
}
/* cleanup */
@@ -1453,7 +1450,7 @@ static void mouse_action_keys(bAnimContext *ac,
/* use View2D to determine the index of the channel (i.e a row in the list) where keyframe was */
UI_view2d_region_to_view(v2d, mval[0], mval[1], &x, &y);
UI_view2d_listview_view_to_cell(
- v2d, 0, ACHANNEL_STEP(ac), 0, (float)ACHANNEL_HEIGHT_HALF(ac), x, y, NULL, &channel_index);
+ 0, ACHANNEL_STEP(ac), 0, ACHANNEL_FIRST_TOP(ac), x, y, NULL, &channel_index);
/* x-range to check is +/- 7px for standard keyframe under standard dpi/y-scale
* (in screen/region-space), on either side of mouse click (size of keyframe icon).
diff --git a/source/blender/editors/space_action/space_action.c b/source/blender/editors/space_action/space_action.c
index 843abbd16db..972f19bb643 100644
--- a/source/blender/editors/space_action/space_action.c
+++ b/source/blender/editors/space_action/space_action.c
@@ -45,6 +45,7 @@
#include "WM_types.h"
#include "WM_message.h"
+#include "UI_interface.h"
#include "UI_resources.h"
#include "UI_view2d.h"
@@ -52,6 +53,7 @@
#include "ED_screen.h"
#include "ED_anim_api.h"
#include "ED_markers.h"
+#include "ED_time_scrub_ui.h"
#include "action_intern.h" /* own include */
#include "GPU_framebuffer.h"
@@ -69,7 +71,7 @@ static SpaceLink *action_new(const ScrArea *sa, const Scene *scene)
saction->autosnap = SACTSNAP_FRAME;
saction->mode = SACTCONT_DOPESHEET;
saction->mode_prev = SACTCONT_DOPESHEET;
- saction->flag = SACTION_SHOW_INTERPOLATION;
+ saction->flag = SACTION_SHOW_INTERPOLATION | SACTION_SHOW_MARKER_LINES;
saction->ads.filterflag |= ADS_FILTER_SUMMARY;
@@ -125,7 +127,7 @@ static SpaceLink *action_new(const ScrArea *sa, const Scene *scene)
ar->v2d.minzoom = 0.01f;
ar->v2d.maxzoom = 50;
- ar->v2d.scroll = (V2D_SCROLL_BOTTOM | V2D_SCROLL_SCALE_HORIZONTAL);
+ ar->v2d.scroll = (V2D_SCROLL_BOTTOM | V2D_SCROLL_HORIZONTAL_HANDLES);
ar->v2d.scroll |= (V2D_SCROLL_RIGHT);
ar->v2d.keepzoom = V2D_LOCKZOOM_Y;
ar->v2d.keepofs = V2D_KEEPOFS_Y;
@@ -234,20 +236,13 @@ static void action_main_region_draw(const bContext *C, ARegion *ar)
/* reset view matrix */
UI_view2d_view_restore(C);
+ /* scrubbing region */
+ ED_scrubbing_draw(ar, scene, saction->flag & SACTION_DRAWTIME, true);
+
/* scrollers */
scrollers = UI_view2d_scrollers_calc(v2d, NULL);
UI_view2d_scrollers_draw(v2d, scrollers);
UI_view2d_scrollers_free(scrollers);
-
- /* frame numbers */
- UI_view2d_draw_scale_x__discrete_frames_or_seconds(
- ar, v2d, &v2d->hor, scene, saction->flag & SACTION_DRAWTIME);
-
- /* draw current frame number-indicator on top of scrollers */
- if ((saction->flag & SACTION_NODRAWCFRANUM) == 0) {
- UI_view2d_view_orthoSpecial(ar, v2d, 1);
- ANIM_draw_cfra_number(C, v2d, cfra_flag);
- }
}
/* add handlers, stuff you only do once or on area/region changes */
@@ -285,6 +280,9 @@ static void action_channel_region_draw(const bContext *C, ARegion *ar)
draw_channel_names((bContext *)C, &ac, ar);
}
+ /* channel filter next to scrubbing area */
+ ED_channel_search_draw(C, ar, ac.ads);
+
/* reset view matrix */
UI_view2d_view_restore(C);
@@ -869,7 +867,7 @@ void ED_spacetype_action(void)
art->draw = action_main_region_draw;
art->listener = action_main_region_listener;
art->message_subscribe = saction_main_region_message_subscribe;
- art->keymapflag = ED_KEYMAP_VIEW2D | ED_KEYMAP_MARKERS | ED_KEYMAP_ANIMATION | ED_KEYMAP_FRAMES;
+ art->keymapflag = ED_KEYMAP_VIEW2D | ED_KEYMAP_ANIMATION | ED_KEYMAP_FRAMES;
BLI_addhead(&st->regiontypes, art);
@@ -901,7 +899,7 @@ void ED_spacetype_action(void)
/* regions: UI buttons */
art = MEM_callocN(sizeof(ARegionType), "spacetype action region");
art->regionid = RGN_TYPE_UI;
- art->prefsizex = 200;
+ art->prefsizex = UI_SIDEBAR_PANEL_WIDTH;
art->keymapflag = ED_KEYMAP_UI;
art->listener = action_region_listener;
art->init = action_buttons_area_init;
diff --git a/source/blender/editors/space_buttons/buttons_context.c b/source/blender/editors/space_buttons/buttons_context.c
index 607c3ddbb10..fde8b8f85f8 100644
--- a/source/blender/editors/space_buttons/buttons_context.c
+++ b/source/blender/editors/space_buttons/buttons_context.c
@@ -785,6 +785,10 @@ int buttons_context(const bContext *C, const char *member, bContextDataResult *r
SpaceProperties *sbuts = CTX_wm_space_properties(C);
ButsContextPath *path = sbuts ? sbuts->path : NULL;
+ if (sbuts->mainb == BCONTEXT_TOOL) {
+ return 0;
+ }
+
if (!path) {
return 0;
}
diff --git a/source/blender/editors/space_buttons/buttons_ops.c b/source/blender/editors/space_buttons/buttons_ops.c
index fe4ed0209bf..500efe4bb4d 100644
--- a/source/blender/editors/space_buttons/buttons_ops.c
+++ b/source/blender/editors/space_buttons/buttons_ops.c
@@ -56,15 +56,10 @@
static int context_menu_invoke(bContext *C, wmOperator *UNUSED(op), const wmEvent *UNUSED(event))
{
- const ARegion *ar = CTX_wm_region(C);
uiPopupMenu *pup = UI_popup_menu_begin(C, IFACE_("Context Menu"), ICON_NONE);
uiLayout *layout = UI_popup_menu_layout(pup);
uiItemM(layout, "INFO_MT_area", NULL, ICON_NONE);
- if (ar->regiontype == RGN_TYPE_NAV_BAR) {
- ED_screens_navigation_bar_tools_menu_create(C, layout, NULL);
- }
-
UI_popup_menu_end(C, pup);
return OPERATOR_INTERFACE;
diff --git a/source/blender/editors/space_buttons/space_buttons.c b/source/blender/editors/space_buttons/space_buttons.c
index f9244049d54..9b0150d731d 100644
--- a/source/blender/editors/space_buttons/space_buttons.c
+++ b/source/blender/editors/space_buttons/space_buttons.c
@@ -34,6 +34,7 @@
#include "ED_space_api.h"
#include "ED_screen.h"
+#include "ED_view3d.h" /* To draw toolbar UI. */
#include "WM_api.h"
#include "WM_types.h"
@@ -198,105 +199,7 @@ static void buttons_main_region_layout_properties(const bContext *C,
}
const bool vertical = true;
- ED_region_panels_layout_ex(C, ar, contexts, sbuts->mainb, vertical);
-}
-
-static void buttons_main_region_layout_tool(const bContext *C, ARegion *ar)
-{
- const enum eContextObjectMode mode = CTX_data_mode_enum(C);
-
- const char *contexts_base[5] = {NULL};
- contexts_base[0] = ".active_tool";
- const char **contexts = &contexts_base[1];
-
- /* Hard coded to 3D view. */
- {
- switch (mode) {
- case CTX_MODE_EDIT_MESH:
- ARRAY_SET_ITEMS(contexts, ".mesh_edit");
- break;
- case CTX_MODE_EDIT_CURVE:
- ARRAY_SET_ITEMS(contexts, ".curve_edit");
- break;
- case CTX_MODE_EDIT_SURFACE:
- ARRAY_SET_ITEMS(contexts, ".curve_edit");
- break;
- case CTX_MODE_EDIT_TEXT:
- ARRAY_SET_ITEMS(contexts, ".text_edit");
- break;
- case CTX_MODE_EDIT_ARMATURE:
- ARRAY_SET_ITEMS(contexts, ".armature_edit");
- break;
- case CTX_MODE_EDIT_METABALL:
- ARRAY_SET_ITEMS(contexts, ".mball_edit");
- break;
- case CTX_MODE_EDIT_LATTICE:
- ARRAY_SET_ITEMS(contexts, ".lattice_edit");
- break;
- case CTX_MODE_POSE:
- ARRAY_SET_ITEMS(contexts, ".posemode");
- break;
- case CTX_MODE_SCULPT:
- ARRAY_SET_ITEMS(contexts, ".paint_common", ".sculpt_mode");
- break;
- case CTX_MODE_PAINT_WEIGHT:
- ARRAY_SET_ITEMS(contexts, ".paint_common", ".weightpaint");
- break;
- case CTX_MODE_PAINT_VERTEX:
- ARRAY_SET_ITEMS(contexts, ".paint_common", ".vertexpaint");
- break;
- case CTX_MODE_PAINT_TEXTURE:
- ARRAY_SET_ITEMS(contexts, ".paint_common", ".imagepaint");
- break;
- case CTX_MODE_PARTICLE:
- ARRAY_SET_ITEMS(contexts, ".paint_common", ".particlemode");
- break;
- case CTX_MODE_OBJECT:
- ARRAY_SET_ITEMS(contexts, ".objectmode");
- break;
- case CTX_MODE_PAINT_GPENCIL:
- ARRAY_SET_ITEMS(contexts, ".greasepencil_paint");
- break;
- case CTX_MODE_SCULPT_GPENCIL:
- ARRAY_SET_ITEMS(contexts, ".greasepencil_sculpt");
- break;
- case CTX_MODE_WEIGHT_GPENCIL:
- ARRAY_SET_ITEMS(contexts, ".greasepencil_weight");
- break;
- default:
- break;
- }
- }
-
- /* for grease pencil we don't use tool system yet, so we need check outside
- * workspace->tools_space_type because this value is not available
- */
- switch (mode) {
- case CTX_MODE_PAINT_GPENCIL:
- ARRAY_SET_ITEMS(contexts, ".greasepencil_paint");
- break;
- case CTX_MODE_SCULPT_GPENCIL:
- ARRAY_SET_ITEMS(contexts, ".greasepencil_sculpt");
- break;
- case CTX_MODE_WEIGHT_GPENCIL:
- ARRAY_SET_ITEMS(contexts, ".greasepencil_weight");
- break;
- case CTX_MODE_EDIT_GPENCIL:
- ARRAY_SET_ITEMS(contexts, ".greasepencil_edit");
- break;
- default:
- break;
- }
-
- int i = 0;
- while (contexts_base[i]) {
- i++;
- }
- BLI_assert(i < ARRAY_SIZE(contexts_base));
- contexts_base[i] = ".workspace";
-
- const bool vertical = true;
- ED_region_panels_layout_ex(C, ar, contexts_base, -1, vertical);
+ ED_region_panels_layout_ex(C, ar, &ar->type->paneltypes, contexts, sbuts->mainb, vertical, NULL);
}
static void buttons_main_region_layout(const bContext *C, ARegion *ar)
@@ -305,7 +208,7 @@ static void buttons_main_region_layout(const bContext *C, ARegion *ar)
SpaceProperties *sbuts = CTX_wm_space_properties(C);
if (sbuts->mainb == BCONTEXT_TOOL) {
- buttons_main_region_layout_tool(C, ar);
+ ED_view3d_buttons_region_layout_ex(C, ar, "Tool");
}
else {
buttons_main_region_layout_properties(C, sbuts, ar);
@@ -400,9 +303,6 @@ static void buttons_header_region_message_subscribe(const bContext *UNUSED(C),
static void buttons_navigation_bar_region_init(wmWindowManager *wm, ARegion *ar)
{
- wmKeyMap *keymap = WM_keymap_ensure(wm->defaultconf, "Property Editor", SPACE_PROPERTIES, 0);
- WM_event_add_keymap_handler(&ar->handlers, keymap);
-
ar->flag |= RGN_FLAG_PREFSIZE_OR_HIDDEN;
ED_region_panels_init(wm, ar);
@@ -749,7 +649,7 @@ void ED_spacetype_buttons(void)
art->regionid = RGN_TYPE_NAV_BAR;
art->prefsizex = AREAMINX - 3; /* XXX Works and looks best,
* should we update AREAMINX accordingly? */
- art->keymapflag = ED_KEYMAP_UI | ED_KEYMAP_FRAMES;
+ art->keymapflag = ED_KEYMAP_UI | ED_KEYMAP_FRAMES | ED_KEYMAP_NAVBAR;
art->init = buttons_navigation_bar_region_init;
art->draw = buttons_navigation_bar_region_draw;
art->message_subscribe = buttons_navigation_bar_region_message_subscribe;
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 70dc1caf36f..081515ca4bc 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 (-0.8f * U.widget_unit)
+#define CHANNEL_FIRST (-UI_SCRUBBING_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 3f971c4444a..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(&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) {
@@ -955,10 +955,10 @@ static bool change_frame_poll(bContext *C)
{
/* prevent changes during render */
if (G.is_rendering) {
- return 0;
+ return false;
}
-
- return ED_space_clip_poll(C);
+ SpaceClip *space_clip = CTX_wm_space_clip(C);
+ return space_clip != NULL;
}
static void change_frame_apply(bContext *C, wmOperator *op)
diff --git a/source/blender/editors/space_clip/space_clip.c b/source/blender/editors/space_clip/space_clip.c
index 542f99e49ee..f26175a6c57 100644
--- a/source/blender/editors/space_clip/space_clip.c
+++ b/source/blender/editors/space_clip/space_clip.c
@@ -47,6 +47,7 @@
#include "ED_mask.h"
#include "ED_space_api.h"
#include "ED_screen.h"
+#include "ED_time_scrub_ui.h"
#include "ED_select_utils.h"
#include "ED_clip.h"
#include "ED_transform.h"
@@ -94,7 +95,7 @@ static void init_preview_region(const Scene *scene,
ar->v2d.minzoom = 0.01f;
ar->v2d.maxzoom = 50;
- ar->v2d.scroll = (V2D_SCROLL_BOTTOM | V2D_SCROLL_SCALE_HORIZONTAL);
+ ar->v2d.scroll = (V2D_SCROLL_BOTTOM | V2D_SCROLL_HORIZONTAL_HANDLES);
ar->v2d.scroll |= (V2D_SCROLL_RIGHT);
ar->v2d.keepzoom = V2D_LOCKZOOM_Y;
ar->v2d.keepofs = V2D_KEEPOFS_Y;
@@ -115,8 +116,8 @@ static void init_preview_region(const Scene *scene,
ar->v2d.max[0] = MAXFRAMEF;
ar->v2d.max[1] = FLT_MAX;
- ar->v2d.scroll = (V2D_SCROLL_BOTTOM | V2D_SCROLL_SCALE_HORIZONTAL);
- ar->v2d.scroll |= (V2D_SCROLL_LEFT | V2D_SCROLL_SCALE_VERTICAL);
+ ar->v2d.scroll = (V2D_SCROLL_BOTTOM | V2D_SCROLL_HORIZONTAL_HANDLES);
+ ar->v2d.scroll |= (V2D_SCROLL_RIGHT | V2D_SCROLL_VERTICAL_HANDLES);
ar->v2d.minzoom = 0.0f;
ar->v2d.maxzoom = 0.0f;
@@ -249,7 +250,7 @@ static SpaceLink *clip_new(const ScrArea *sa, const Scene *scene)
sc->zoom = 1.0f;
sc->path_length = 20;
sc->scopes.track_preview_height = 120;
- sc->around = V3D_AROUND_LOCAL_ORIGINS;
+ sc->around = V3D_AROUND_CENTER_MEDIAN;
/* header */
ar = MEM_callocN(sizeof(ARegion), "header for clip");
@@ -1001,9 +1002,13 @@ static void clip_preview_region_init(wmWindowManager *wm, ARegion *ar)
UI_view2d_region_reinit(&ar->v2d, V2D_COMMONVIEW_CUSTOM, ar->winx, ar->winy);
/* own keymap */
+
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 Graph Editor", SPACE_CLIP, 0);
WM_event_add_keymap_handler_v2d_mask(&ar->handlers, keymap);
@@ -1041,22 +1046,24 @@ static void graph_region_draw(const bContext *C, ARegion *ar)
/* reset view matrix */
UI_view2d_view_restore(C);
+ /* time-scrubbing */
+ ED_scrubbing_draw(ar, scene, sc->flag & SC_SHOW_SECONDS, true);
+
/* scrollers */
scrollers = UI_view2d_scrollers_calc(v2d, NULL);
UI_view2d_scrollers_draw(v2d, scrollers);
UI_view2d_scrollers_free(scrollers);
/* scale indicators */
- UI_view2d_draw_scale_x__discrete_frames_or_seconds(
- ar, v2d, &v2d->hor, scene, sc->flag & SC_SHOW_SECONDS);
- UI_view2d_draw_scale_y__values(ar, v2d, &v2d->vert);
-
- /* current frame indicator */
- if (sc->flag & SC_SHOW_SECONDS) {
- cfra_flag |= DRAWCFRA_UNIT_SECONDS;
+ {
+ rcti rect;
+ BLI_rcti_init(&rect,
+ 0,
+ 15 * UI_DPI_FAC,
+ 15 * UI_DPI_FAC,
+ UI_DPI_FAC * ar->sizey - UI_SCRUBBING_MARGIN_Y);
+ UI_view2d_draw_scale_y__values(ar, v2d, &rect, TH_TEXT);
}
- UI_view2d_view_orthoSpecial(ar, v2d, 1);
- ANIM_draw_cfra_number(C, v2d, cfra_flag);
}
static void dopesheet_region_draw(const bContext *C, ARegion *ar)
@@ -1093,18 +1100,13 @@ static void dopesheet_region_draw(const bContext *C, ARegion *ar)
/* reset view matrix */
UI_view2d_view_restore(C);
+ /* time-scrubbing */
+ ED_scrubbing_draw(ar, scene, sc->flag & SC_SHOW_SECONDS, true);
+
/* scrollers */
scrollers = UI_view2d_scrollers_calc(v2d, NULL);
UI_view2d_scrollers_draw(v2d, scrollers);
UI_view2d_scrollers_free(scrollers);
-
- /* frame numbers */
- UI_view2d_draw_scale_x__discrete_frames_or_seconds(
- ar, v2d, &v2d->hor, scene, sc->flag & SC_SHOW_SECONDS);
-
- /* current frame number indicator */
- UI_view2d_view_orthoSpecial(ar, v2d, 1);
- ANIM_draw_cfra_number(C, v2d, cfra_flag);
}
static void clip_preview_region_draw(const bContext *C, ARegion *ar)
@@ -1369,7 +1371,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;
@@ -1380,7 +1382,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 18d48b426e0..b51baafbcf5 100644
--- a/source/blender/editors/space_clip/tracking_ops.c
+++ b/source/blender/editors/space_clip/tracking_ops.c
@@ -1299,6 +1299,12 @@ void CLIP_OT_hide_tracks_clear(wmOperatorType *ot)
/********************** frame jump operator *********************/
+static bool frame_jump_poll(bContext *C)
+{
+ SpaceClip *space_clip = CTX_wm_space_clip(C);
+ return space_clip != NULL;
+}
+
static int frame_jump_exec(bContext *C, wmOperator *op)
{
Scene *scene = CTX_data_scene(C);
@@ -1377,7 +1383,7 @@ void CLIP_OT_frame_jump(wmOperatorType *ot)
/* api callbacks */
ot->exec = frame_jump_exec;
- ot->poll = ED_space_clip_poll;
+ ot->poll = frame_jump_poll;
/* flags */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
diff --git a/source/blender/editors/space_file/file_draw.c b/source/blender/editors/space_file/file_draw.c
index bb8680682d2..6b3baa1e766 100644
--- a/source/blender/editors/space_file/file_draw.c
+++ b/source/blender/editors/space_file/file_draw.c
@@ -478,7 +478,7 @@ static void file_draw_preview(uiBlock *block,
GPU_SRC_ALPHA, GPU_ONE_MINUS_SRC_ALPHA, GPU_ONE, GPU_ONE_MINUS_SRC_ALPHA);
if (icon) {
- UI_icon_draw_aspect((float)xco, (float)yco, icon, icon_aspect, 1.0f, NULL);
+ UI_icon_draw_ex((float)xco, (float)yco, icon, icon_aspect, 1.0f, 0.0f, NULL, false);
}
/* border */
diff --git a/source/blender/editors/space_file/file_ops.c b/source/blender/editors/space_file/file_ops.c
index 674735f3e1d..5ac7ff72aed 100644
--- a/source/blender/editors/space_file/file_ops.c
+++ b/source/blender/editors/space_file/file_ops.c
@@ -1011,7 +1011,7 @@ static int bookmark_cleanup_exec(bContext *C, wmOperator *UNUSED(op))
BLI_make_file_string(
"/", name, BKE_appdir_folder_id_create(BLENDER_USER_CONFIG, NULL), BLENDER_BOOKMARK_FILE);
fsmenu_write_file(fsmenu, name);
- fsmenu_refresh_bookmarks_status(fsmenu);
+ fsmenu_refresh_bookmarks_status(CTX_wm_manager(C), fsmenu);
ED_area_tag_refresh(sa);
ED_area_tag_redraw(sa);
}
@@ -1567,6 +1567,9 @@ static int file_refresh_exec(bContext *C, wmOperator *UNUSED(unused))
/* refresh system directory menu */
fsmenu_refresh_system_category(fsmenu);
+ /* Update bookmarks 'valid' state. */
+ fsmenu_refresh_bookmarks_status(wm, fsmenu);
+
WM_event_add_notifier(C, NC_SPACE | ND_SPACE_FILE_LIST, NULL);
return OPERATOR_FINISHED;
diff --git a/source/blender/editors/space_file/fsmenu.c b/source/blender/editors/space_file/fsmenu.c
index 38423a87447..b50c37baae6 100644
--- a/source/blender/editors/space_file/fsmenu.c
+++ b/source/blender/editors/space_file/fsmenu.c
@@ -44,6 +44,9 @@
# include "BLI_winstuff.h"
#endif
+#include "WM_api.h"
+#include "WM_types.h"
+
#ifdef __APPLE__
# include <Carbon/Carbon.h>
#endif /* __APPLE__ */
@@ -721,31 +724,59 @@ void fsmenu_refresh_system_category(struct FSMenu *fsmenu)
fsmenu_read_system(fsmenu, true);
}
-void fsmenu_refresh_bookmarks_status(struct FSMenu *fsmenu)
+static void fsmenu_free_ex(FSMenu **fsmenu)
{
- int categories[] = {
- FS_CATEGORY_SYSTEM, FS_CATEGORY_SYSTEM_BOOKMARKS, FS_CATEGORY_BOOKMARKS, FS_CATEGORY_RECENT};
- int i;
-
- for (i = sizeof(categories) / sizeof(*categories); i--;) {
- FSMenuEntry *fsm_iter = ED_fsmenu_get_category(fsmenu, categories[i]);
- for (; fsm_iter; fsm_iter = fsm_iter->next) {
- fsmenu_entry_refresh_valid(fsm_iter);
- }
+ if (*fsmenu != NULL) {
+ fsmenu_free_category(*fsmenu, FS_CATEGORY_SYSTEM);
+ fsmenu_free_category(*fsmenu, FS_CATEGORY_SYSTEM_BOOKMARKS);
+ fsmenu_free_category(*fsmenu, FS_CATEGORY_BOOKMARKS);
+ fsmenu_free_category(*fsmenu, FS_CATEGORY_RECENT);
+ MEM_freeN(*fsmenu);
}
+
+ *fsmenu = NULL;
}
void fsmenu_free(void)
{
- if (g_fsmenu) {
- fsmenu_free_category(g_fsmenu, FS_CATEGORY_SYSTEM);
- fsmenu_free_category(g_fsmenu, FS_CATEGORY_SYSTEM_BOOKMARKS);
- fsmenu_free_category(g_fsmenu, FS_CATEGORY_BOOKMARKS);
- fsmenu_free_category(g_fsmenu, FS_CATEGORY_RECENT);
- MEM_freeN(g_fsmenu);
+ fsmenu_free_ex(&g_fsmenu);
+}
+
+static void fsmenu_copy_category(struct FSMenu *fsmenu_dst,
+ struct FSMenu *fsmenu_src,
+ const FSMenuCategory category)
+{
+ FSMenuEntry *fsm_dst_prev = NULL, *fsm_dst_head = NULL;
+ FSMenuEntry *fsm_src_iter = ED_fsmenu_get_category(fsmenu_src, category);
+
+ for (; fsm_src_iter != NULL; fsm_src_iter = fsm_src_iter->next) {
+ FSMenuEntry *fsm_dst = MEM_dupallocN(fsm_src_iter);
+ if (fsm_dst->path != NULL) {
+ fsm_dst->path = MEM_dupallocN(fsm_dst->path);
+ }
+
+ if (fsm_dst_prev != NULL) {
+ fsm_dst_prev->next = fsm_dst;
+ }
+ else {
+ fsm_dst_head = fsm_dst;
+ }
+ fsm_dst_prev = fsm_dst;
}
- g_fsmenu = NULL;
+ ED_fsmenu_set_category(fsmenu_dst, category, fsm_dst_head);
+}
+
+static FSMenu *fsmenu_copy(FSMenu *fsmenu)
+{
+ FSMenu *fsmenu_copy = MEM_dupallocN(fsmenu);
+
+ fsmenu_copy_category(fsmenu_copy, fsmenu_copy, FS_CATEGORY_SYSTEM);
+ fsmenu_copy_category(fsmenu_copy, fsmenu_copy, FS_CATEGORY_SYSTEM_BOOKMARKS);
+ fsmenu_copy_category(fsmenu_copy, fsmenu_copy, FS_CATEGORY_BOOKMARKS);
+ fsmenu_copy_category(fsmenu_copy, fsmenu_copy, FS_CATEGORY_RECENT);
+
+ return fsmenu_copy;
}
int fsmenu_get_active_indices(struct FSMenu *fsmenu, enum FSMenuCategory category, const char *dir)
@@ -761,3 +792,99 @@ int fsmenu_get_active_indices(struct FSMenu *fsmenu, enum FSMenuCategory categor
return -1;
}
+
+/* Thanks to some bookmarks sometimes being network drives that can have tens of seconds of delay
+ * before being defined as unreachable by the OS, we need to validate the bookmarks in an async
+ * job...
+ */
+static void fsmenu_bookmark_validate_job_startjob(void *fsmenuv,
+ short *stop,
+ short *do_update,
+ float *UNUSED(progress))
+{
+ FSMenu *fsmenu = fsmenuv;
+
+ int categories[] = {
+ FS_CATEGORY_SYSTEM, FS_CATEGORY_SYSTEM_BOOKMARKS, FS_CATEGORY_BOOKMARKS, FS_CATEGORY_RECENT};
+
+ for (size_t i = ARRAY_SIZE(categories); i--;) {
+ FSMenuEntry *fsm_iter = ED_fsmenu_get_category(fsmenu, categories[i]);
+ for (; fsm_iter; fsm_iter = fsm_iter->next) {
+ if (*stop) {
+ return;
+ }
+ /* Note that we do not really need atomics primitives or thread locks here, since this only
+ * sets one short, which is assumed to be 'atomic'-enough for us here. */
+ fsmenu_entry_refresh_valid(fsm_iter);
+ *do_update = true;
+ }
+ }
+}
+
+static void fsmenu_bookmark_validate_job_update(void *fsmenuv)
+{
+ FSMenu *fsmenu_job = fsmenuv;
+
+ int categories[] = {
+ FS_CATEGORY_SYSTEM, FS_CATEGORY_SYSTEM_BOOKMARKS, FS_CATEGORY_BOOKMARKS, FS_CATEGORY_RECENT};
+
+ for (size_t i = ARRAY_SIZE(categories); i--;) {
+ FSMenuEntry *fsm_iter_src = ED_fsmenu_get_category(fsmenu_job, categories[i]);
+ FSMenuEntry *fsm_iter_dst = ED_fsmenu_get_category(ED_fsmenu_get(), categories[i]);
+ for (; fsm_iter_dst != NULL; fsm_iter_dst = fsm_iter_dst->next) {
+ while (fsm_iter_src != NULL && !STREQ(fsm_iter_dst->path, fsm_iter_src->path)) {
+ fsm_iter_src = fsm_iter_src->next;
+ }
+ if (fsm_iter_src == NULL) {
+ return;
+ }
+ fsm_iter_dst->valid = fsm_iter_src->valid;
+ }
+ }
+}
+
+static void fsmenu_bookmark_validate_job_end(void *fsmenuv)
+{
+ /* In case there would be some dangling update... */
+ fsmenu_bookmark_validate_job_update(fsmenuv);
+}
+
+static void fsmenu_bookmark_validate_job_free(void *fsmenuv)
+{
+ FSMenu *fsmenu = fsmenuv;
+ fsmenu_free_ex(&fsmenu);
+}
+
+static void fsmenu_bookmark_validate_job_start(wmWindowManager *wm)
+{
+ wmJob *wm_job;
+ FSMenu *fsmenu_job = fsmenu_copy(g_fsmenu);
+
+ /* setup job */
+ wm_job = WM_jobs_get(
+ wm, wm->winactive, wm, "Validating Bookmarks...", 0, WM_JOB_TYPE_FSMENU_BOOKMARK_VALIDATE);
+ WM_jobs_customdata_set(wm_job, fsmenu_job, fsmenu_bookmark_validate_job_free);
+ WM_jobs_timer(wm_job, 0.01, NC_SPACE | ND_SPACE_FILE_LIST, NC_SPACE | ND_SPACE_FILE_LIST);
+ WM_jobs_callbacks(wm_job,
+ fsmenu_bookmark_validate_job_startjob,
+ NULL,
+ fsmenu_bookmark_validate_job_update,
+ fsmenu_bookmark_validate_job_end);
+
+ /* start the job */
+ WM_jobs_start(wm, wm_job);
+}
+
+static void fsmenu_bookmark_validate_job_stop(wmWindowManager *wm)
+{
+ WM_jobs_kill_type(wm, wm, WM_JOB_TYPE_FSMENU_BOOKMARK_VALIDATE);
+}
+
+void fsmenu_refresh_bookmarks_status(wmWindowManager *wm, FSMenu *fsmenu)
+{
+ BLI_assert(fsmenu == ED_fsmenu_get());
+ UNUSED_VARS_NDEBUG(fsmenu);
+
+ fsmenu_bookmark_validate_job_stop(wm);
+ fsmenu_bookmark_validate_job_start(wm);
+}
diff --git a/source/blender/editors/space_file/fsmenu.h b/source/blender/editors/space_file/fsmenu.h
index cb0dccf0499..d9850cb855d 100644
--- a/source/blender/editors/space_file/fsmenu.h
+++ b/source/blender/editors/space_file/fsmenu.h
@@ -68,7 +68,7 @@ void fsmenu_free(void);
void fsmenu_refresh_system_category(struct FSMenu *fsmenu);
/** Refresh 'valid' status of all menu entries */
-void fsmenu_refresh_bookmarks_status(struct FSMenu *fsmenu);
+void fsmenu_refresh_bookmarks_status(struct wmWindowManager *wm, struct FSMenu *fsmenu);
/** Get active index based on given directory. */
int fsmenu_get_active_indices(struct FSMenu *fsmenu,
diff --git a/source/blender/editors/space_file/space_file.c b/source/blender/editors/space_file/space_file.c
index 9fb07042104..1fd878e4662 100644
--- a/source/blender/editors/space_file/space_file.c
+++ b/source/blender/editors/space_file/space_file.c
@@ -142,18 +142,16 @@ static void file_free(SpaceLink *sl)
}
/* spacetype; init callback, area size changes, screen set, etc */
-static void file_init(wmWindowManager *UNUSED(wm), ScrArea *sa)
+static void file_init(wmWindowManager *wm, ScrArea *sa)
{
SpaceFile *sfile = (SpaceFile *)sa->spacedata.first;
+ struct FSMenu *fsmenu = ED_fsmenu_get();
/* refresh system directory list */
- fsmenu_refresh_system_category(ED_fsmenu_get());
+ fsmenu_refresh_system_category(fsmenu);
- /* Update bookmarks 'valid' state.
- * Done here, because it seems BLI_is_dir() can have huge impact on performances
- * in some cases, on win systems... See T43684.
- */
- fsmenu_refresh_bookmarks_status(ED_fsmenu_get());
+ /* Update bookmarks 'valid' state. */
+ fsmenu_refresh_bookmarks_status(wm, fsmenu);
if (sfile->layout) {
sfile->layout->dirty = true;
diff --git a/source/blender/editors/space_graph/graph_draw.c b/source/blender/editors/space_graph/graph_draw.c
index dfc59a79c49..062c9f86fab 100644
--- a/source/blender/editors/space_graph/graph_draw.c
+++ b/source/blender/editors/space_graph/graph_draw.c
@@ -1230,9 +1230,8 @@ void graph_draw_channel_names(bContext *C, bAnimContext *ac, ARegion *ar)
int filter;
View2D *v2d = &ar->v2d;
- float y = 0.0f, height;
+ float height;
size_t items;
- int i = 0;
/* build list of channels to draw */
filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE | ANIMFILTER_LIST_CHANNELS);
@@ -1240,62 +1239,47 @@ void graph_draw_channel_names(bContext *C, bAnimContext *ac, ARegion *ar)
/* Update max-extent of channels here (taking into account scrollers):
* - this is done to allow the channel list to be scrollable, but must be done here
- * to avoid regenerating the list again and/or also because channels list is drawn first
- * - offset of ACHANNEL_HEIGHT*2 is added to the height of the channels, as first is for
- * start of list offset, and the second is as a correction for the scrollers.
- */
- height = (float)((items * ACHANNEL_STEP(ac)) + (ACHANNEL_HEIGHT(ac) * 2));
- UI_view2d_totRect_set(v2d, BLI_rcti_size_x(&ar->v2d.mask), height);
+ * to avoid regenerating the list again and/or also because channels list is drawn first */
+ height = ACHANNEL_TOT_HEIGHT(ac, items);
+ v2d->tot.ymin = -height;
/* loop through channels, and set up drawing depending on their type */
{ /* first pass: just the standard GL-drawing for backdrop + text */
size_t channel_index = 0;
+ float ymax = ACHANNEL_FIRST_TOP(ac);
- y = (float)ACHANNEL_FIRST(ac);
-
- for (ale = anim_data.first, i = 0; ale; ale = ale->next, i++) {
- const float yminc = (float)(y - ACHANNEL_HEIGHT_HALF(ac));
- const float ymaxc = (float)(y + ACHANNEL_HEIGHT_HALF(ac));
+ for (ale = anim_data.first; ale; ale = ale->next, ymax -= ACHANNEL_STEP(ac), channel_index++) {
+ float ymin = ymax - ACHANNEL_HEIGHT(ac);
/* check if visible */
- if (IN_RANGE(yminc, v2d->cur.ymin, v2d->cur.ymax) ||
- IN_RANGE(ymaxc, v2d->cur.ymin, v2d->cur.ymax)) {
+ if (IN_RANGE(ymin, v2d->cur.ymin, v2d->cur.ymax) ||
+ IN_RANGE(ymax, v2d->cur.ymin, v2d->cur.ymax)) {
/* draw all channels using standard channel-drawing API */
- ANIM_channel_draw(ac, ale, yminc, ymaxc, channel_index);
+ ANIM_channel_draw(ac, ale, ymin, ymax, channel_index);
}
-
- /* adjust y-position for next one */
- y -= ACHANNEL_STEP(ac);
- channel_index++;
}
}
{ /* second pass: widgets */
uiBlock *block = UI_block_begin(C, ar, __func__, UI_EMBOSS);
size_t channel_index = 0;
-
- y = (float)ACHANNEL_FIRST(ac);
+ float ymax = ACHANNEL_FIRST_TOP(ac);
/* set blending again, as may not be set in previous step */
GPU_blend_set_func_separate(
GPU_SRC_ALPHA, GPU_ONE_MINUS_SRC_ALPHA, GPU_ONE, GPU_ONE_MINUS_SRC_ALPHA);
GPU_blend(true);
- for (ale = anim_data.first, i = 0; ale; ale = ale->next, i++) {
- const float yminc = (float)(y - ACHANNEL_HEIGHT_HALF(ac));
- const float ymaxc = (float)(y + ACHANNEL_HEIGHT_HALF(ac));
+ for (ale = anim_data.first; ale; ale = ale->next, ymax -= ACHANNEL_STEP(ac), channel_index++) {
+ float ymin = ymax - ACHANNEL_HEIGHT(ac);
/* check if visible */
- if (IN_RANGE(yminc, v2d->cur.ymin, v2d->cur.ymax) ||
- IN_RANGE(ymaxc, v2d->cur.ymin, v2d->cur.ymax)) {
+ if (IN_RANGE(ymin, v2d->cur.ymin, v2d->cur.ymax) ||
+ IN_RANGE(ymax, v2d->cur.ymin, v2d->cur.ymax)) {
/* draw all channels using standard channel-drawing API */
rctf channel_rect;
- BLI_rctf_init(&channel_rect, 0, v2d->cur.xmax - V2D_SCROLL_WIDTH, yminc, ymaxc);
+ BLI_rctf_init(&channel_rect, 0, v2d->cur.xmax - V2D_SCROLL_WIDTH, ymin, ymax);
ANIM_channel_draw_widgets(C, ac, ale, block, &channel_rect, channel_index);
}
-
- /* adjust y-position for next one */
- y -= ACHANNEL_STEP(ac);
- channel_index++;
}
UI_block_end(C, block);
diff --git a/source/blender/editors/space_graph/graph_edit.c b/source/blender/editors/space_graph/graph_edit.c
index 0954538e430..b3fafa09256 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_SCRUBBING_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;
}
@@ -1172,9 +1181,7 @@ static bool delete_graph_keys(bAnimContext *ac)
}
/* Only delete curve too if it won't be doing anything anymore */
- if ((fcu->totvert == 0) &&
- (list_has_suitable_fmodifier(&fcu->modifiers, 0, FMI_TYPE_GENERATE_CURVE) == 0) &&
- (fcu->driver == NULL)) {
+ if (BKE_fcurve_is_empty(fcu)) {
ANIM_fcurve_delete_from_animdata(ac, adt, fcu);
ale->key_data = NULL;
}
@@ -2820,6 +2827,7 @@ void GRAPH_OT_fmodifier_add(wmOperatorType *ot)
/* id-props */
prop = RNA_def_enum(ot->srna, "type", rna_enum_fmodifier_type_items, 0, "Type", "");
+ RNA_def_property_translation_context(prop, BLT_I18NCONTEXT_ID_ACTION);
RNA_def_enum_funcs(prop, graph_fmodifier_itemf);
ot->prop = prop;
diff --git a/source/blender/editors/space_graph/graph_select.c b/source/blender/editors/space_graph/graph_select.c
index 13a42f091f6..5ea07c56286 100644
--- a/source/blender/editors/space_graph/graph_select.c
+++ b/source/blender/editors/space_graph/graph_select.c
@@ -1141,7 +1141,7 @@ typedef enum eGraphVertIndex {
/* Tolerance for absolute radius (in pixels) of the vert from the cursor to use */
// TODO: perhaps this should depend a bit on the size that the user set the vertices to be?
-#define GVERTSEL_TOL 10
+#define GVERTSEL_TOL (10 * U.pixelsize)
/* ....... */
diff --git a/source/blender/editors/space_graph/space_graph.c b/source/blender/editors/space_graph/space_graph.c
index 86d0b961a31..4e131c653f8 100644
--- a/source/blender/editors/space_graph/space_graph.c
+++ b/source/blender/editors/space_graph/space_graph.c
@@ -42,6 +42,7 @@
#include "ED_screen.h"
#include "ED_anim_api.h"
#include "ED_markers.h"
+#include "ED_time_scrub_ui.h"
#include "GPU_immediate.h"
#include "GPU_state.h"
@@ -57,6 +58,7 @@
#include "UI_resources.h"
#include "UI_view2d.h"
+#include "UI_interface.h"
#include "graph_intern.h" // own include
@@ -79,7 +81,7 @@ static SpaceLink *graph_new(const ScrArea *UNUSED(sa), const Scene *scene)
/* settings for making it easier by default to just see what you're interested in tweaking */
sipo->ads->filterflag |= ADS_FILTER_ONLYSEL;
- sipo->flag |= SIPO_SELVHANDLESONLY;
+ sipo->flag |= SIPO_SELVHANDLESONLY | SIPO_MARKER_LINES;
/* header */
ar = MEM_callocN(sizeof(ARegion), "header for graphedit");
@@ -124,8 +126,8 @@ static SpaceLink *graph_new(const ScrArea *UNUSED(sa), const Scene *scene)
ar->v2d.max[0] = MAXFRAMEF;
ar->v2d.max[1] = FLT_MAX;
- ar->v2d.scroll = (V2D_SCROLL_BOTTOM | V2D_SCROLL_SCALE_HORIZONTAL);
- ar->v2d.scroll |= (V2D_SCROLL_LEFT | V2D_SCROLL_SCALE_VERTICAL);
+ ar->v2d.scroll = (V2D_SCROLL_BOTTOM | V2D_SCROLL_HORIZONTAL_HANDLES);
+ ar->v2d.scroll |= (V2D_SCROLL_RIGHT | V2D_SCROLL_VERTICAL_HANDLES);
ar->v2d.keeptot = 0;
@@ -291,12 +293,14 @@ static void graph_main_region_draw(const bContext *C, ARegion *ar)
}
/* markers */
- UI_view2d_view_orthoSpecial(ar, v2d, 1);
- int marker_draw_flag = DRAW_MARKERS_MARGIN;
- if (sipo->flag & SIPO_MARKER_LINES) {
- marker_draw_flag |= DRAW_MARKERS_LINES;
+ if (sipo->mode != SIPO_MODE_DRIVERS) {
+ UI_view2d_view_orthoSpecial(ar, v2d, 1);
+ int marker_draw_flag = DRAW_MARKERS_MARGIN;
+ if (sipo->flag & SIPO_MARKER_LINES) {
+ marker_draw_flag |= DRAW_MARKERS_LINES;
+ }
+ ED_markers_draw(C, marker_draw_flag);
}
- ED_markers_draw(C, marker_draw_flag);
/* preview range */
UI_view2d_view_ortho(v2d);
@@ -309,6 +313,9 @@ static void graph_main_region_draw(const bContext *C, ARegion *ar)
/* reset view matrix */
UI_view2d_view_restore(C);
+ /* time-scrubbing */
+ ED_scrubbing_draw(ar, scene, display_seconds, false);
+
/* scrollers */
// FIXME: args for scrollers depend on the type of data being shown...
scrollers = UI_view2d_scrollers_calc(v2d, NULL);
@@ -316,13 +323,14 @@ static void graph_main_region_draw(const bContext *C, ARegion *ar)
UI_view2d_scrollers_free(scrollers);
/* scale numbers */
- UI_view2d_draw_scale_x__frames_or_seconds(ar, v2d, &v2d->hor, scene, display_seconds);
- UI_view2d_draw_scale_y__values(ar, v2d, &v2d->vert);
-
- /* draw current frame number-indicator on top of scrollers */
- if ((sipo->mode != SIPO_MODE_DRIVERS) && ((sipo->flag & SIPO_NODRAWCFRANUM) == 0)) {
- UI_view2d_view_orthoSpecial(ar, v2d, 1);
- ANIM_draw_cfra_number(C, v2d, cfra_flag);
+ {
+ rcti rect;
+ BLI_rcti_init(&rect,
+ 0,
+ 15 * UI_DPI_FAC,
+ 15 * UI_DPI_FAC,
+ UI_DPI_FAC * ar->sizey - UI_SCRUBBING_MARGIN_Y);
+ UI_view2d_draw_scale_y__values(ar, v2d, &rect, TH_SCROLL_TEXT);
}
}
@@ -367,6 +375,9 @@ static void graph_channel_region_draw(const bContext *C, ARegion *ar)
graph_draw_channel_names((bContext *)C, &ac, ar);
}
+ /* channel filter next to scrubbing area */
+ ED_channel_search_draw(C, ar, ac.ads);
+
/* reset view matrix */
UI_view2d_view_restore(C);
@@ -849,7 +860,7 @@ void ED_spacetype_ipo(void)
art->draw = graph_main_region_draw;
art->listener = graph_region_listener;
art->message_subscribe = graph_region_message_subscribe;
- art->keymapflag = ED_KEYMAP_VIEW2D | ED_KEYMAP_MARKERS | ED_KEYMAP_ANIMATION | ED_KEYMAP_FRAMES;
+ art->keymapflag = ED_KEYMAP_VIEW2D | ED_KEYMAP_ANIMATION | ED_KEYMAP_FRAMES;
BLI_addhead(&st->regiontypes, art);
@@ -880,7 +891,7 @@ void ED_spacetype_ipo(void)
/* regions: UI buttons */
art = MEM_callocN(sizeof(ARegionType), "spacetype graphedit region");
art->regionid = RGN_TYPE_UI;
- art->prefsizex = 200;
+ art->prefsizex = UI_SIDEBAR_PANEL_WIDTH;
art->keymapflag = ED_KEYMAP_UI | ED_KEYMAP_FRAMES;
art->listener = graph_region_listener;
art->init = graph_buttons_region_init;
diff --git a/source/blender/editors/space_image/image_buttons.c b/source/blender/editors/space_image/image_buttons.c
index 752eedebe71..b32f5ef6d9e 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)
{
@@ -650,23 +576,6 @@ static void image_multiview_cb(bContext *C, void *rnd_pt, void *UNUSED(arg_v))
WM_event_add_notifier(C, NC_IMAGE | ND_DRAW, NULL);
}
-#if 0
-static void image_freecache_cb(bContext *C, void *ima_v, void *unused)
-{
- Scene *scene = CTX_data_scene(C);
- BKE_image_free_anim_ibufs(ima_v, scene->r.cfra);
- WM_event_add_notifier(C, NC_IMAGE, ima_v);
-}
-#endif
-
-#if 0
-static void image_user_change(bContext *C, void *iuser_v, void *unused)
-{
- Scene *scene = CTX_data_scene(C);
- BKE_image_user_calc_imanr(iuser_v, scene->r.cfra, 0);
-}
-#endif
-
static void uiblock_layer_pass_buttons(
uiLayout *layout, Image *image, RenderResult *rr, ImageUser *iuser, int w, short *render_slot)
{
@@ -839,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,
@@ -847,23 +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);
- 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);
@@ -878,23 +791,20 @@ 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);
- if (!compact) {
+ SpaceImage *space_image = CTX_wm_space_image(C);
+ if (!compact && (space_image == NULL || iuser != &space_image->iuser)) {
uiTemplateID(layout,
C,
ptr,
@@ -904,217 +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->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);
-
- uiItemL(layout, ima->id.name + 2, ICON_NONE);
- uiItemL(layout, str, ICON_NONE);
-
- if (ima->type == IMA_TYPE_COMPOSITE) {
- // XXX not working yet
-#if 0
- iuser = ntree_get_active_iuser(scene->nodetree);
- if (iuser) {
- UI_block_align_begin(block);
- uiDefIconTextBut(block,
- UI_BTYPE_BUT,
- B_SIMA_RECORD,
- ICON_REC,
- "Record",
- 10,
- 120,
- 100,
- 20,
- 0,
- 0,
- 0,
- 0,
- 0,
- "");
- uiDefIconTextBut(block,
- UI_BTYPE_BUT,
- B_SIMA_PLAY,
- ICON_PLAY,
- "Play",
- 110,
- 120,
- 100,
- 20,
- 0,
- 0,
- 0,
- 0,
- 0,
- "");
- but = uiDefBut(
- block, UI_BTYPE_BUT, B_NOP, "Free Cache", 210, 120, 100, 20, 0, 0, 0, 0, 0, "");
- UI_but_func_set(but, image_freecache_cb, ima, NULL);
-
- if (iuser->frames)
- BLI_snprintf(str, sizeof(str), "(%d) Frames:", iuser->framenr);
- else
- strcpy(str, "Frames:");
- UI_block_align_begin(block);
- uiDefButI(block,
- UI_BTYPE_NUM,
- imagechanged,
- str,
- 10,
- 90,
- 150,
- 20,
- &iuser->frames,
- 0.0,
- MAXFRAMEF,
- 0,
- 0,
- "Number of images of a movie to use");
- uiDefButI(block,
- UI_BTYPE_NUM,
- imagechanged,
- "StartFr:",
- 160,
- 90,
- 150,
- 20,
- &iuser->sfra,
- 1.0,
- MAXFRAMEF,
- 0,
- 0,
- "Global starting frame of the movie");
- }
-#endif
- }
- 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 == NULL) {
+ return;
+ }
+
+ if (ima->source == IMA_SRC_VIEWER) {
+ /* Viewer images. */
+ uiTemplateImageInfo(layout, C, ima, iuser);
+
+ 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 {
- uiItemR(layout, &imaptr, "source", 0, NULL, ICON_NONE);
+ uiItemO(row, "", ICON_UGLYPACKAGE, "image.pack");
+ }
- if (ima->source != IMA_SRC_GENERATED) {
- row = uiLayoutRow(layout, true);
- if (BKE_image_has_packedfile(ima)) {
- uiItemO(row, "", ICON_PACKAGE, "image.unpack");
- }
- else {
- uiItemO(row, "", ICON_UGLYPACKAGE, "image.pack");
- }
+ row = uiLayoutRow(row, true);
+ uiLayoutSetEnabled(row, is_packed == false);
+ uiItemR(row, &imaptr, "filepath", 0, "", ICON_NONE);
+ uiItemO(row, "", ICON_FILE_REFRESH, "image.reload");
+ }
- row = uiLayoutRow(row, true);
- uiLayoutSetEnabled(row, BKE_image_has_packedfile(ima) == false);
- uiItemR(row, &imaptr, "filepath", 0, "", ICON_NONE);
- uiItemO(row, "", ICON_FILE_REFRESH, "image.reload");
- }
+ /* Image layers and Info */
+ if (ima->type == IMA_TYPE_MULTILAYER && ima->rr) {
+ uiItemS(layout);
- /* multilayer? */
- 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);
- }
- }
+ 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);
- col = uiLayoutColumn(layout, false);
- uiTemplateColorspaceSettings(col, &imaptr, "colorspace_settings");
- uiItemR(col, &imaptr, "use_view_as_render", 0, NULL, ICON_NONE);
+ /* Generated */
+ uiLayout *col = uiLayoutColumn(layout, false);
+ uiLayoutSetPropSep(col, true);
- 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 *sub = uiLayoutColumn(col, true);
+ uiItemR(sub, &imaptr, "generated_width", 0, "X", ICON_NONE);
+ uiItemR(sub, &imaptr, "generated_height", 0, "Y", ICON_NONE);
+
+ uiItemR(col, &imaptr, "use_generated_float", 0, NULL, ICON_NONE);
+
+ uiItemS(col);
+
+ 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);
+ }
+
+ if (BKE_image_is_animated(ima)) {
+ /* Animation */
+ uiItemS(layout);
- if (BKE_image_is_animated(ima)) {
- uiItemS(layout);
+ uiLayout *col = uiLayoutColumn(layout, true);
+ uiLayoutSetPropSep(col, true);
- split = uiLayoutSplit(layout, 0.0f, false);
+ 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");
- col = uiLayoutColumn(split, false);
+ uiItemR(sub, userptr, "frame_start", 0, IFACE_("Start"), ICON_NONE);
+ uiItemR(sub, userptr, "frame_offset", 0, NULL, ICON_NONE);
- 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);
+ uiItemR(col, userptr, "use_cyclic", 0, NULL, ICON_NONE);
+ uiItemR(col, userptr, "use_auto_refresh", 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 (ima->source == IMA_SRC_MOVIE && compact == 0) {
+ uiItemR(col, &imaptr, "use_deinterlace", 0, IFACE_("Deinterlace"), ICON_NONE);
+ }
+ }
+
+ /* Multiview */
+ if (multiview && compact == 0) {
+ if ((scene->r.scemode & R_MULTIVIEW) != 0) {
+ uiItemS(layout);
+
+ uiLayout *col = uiLayoutColumn(layout, false);
+ uiLayoutSetPropSep(col, true);
+ uiItemR(col, &imaptr, "use_multiview", 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)
@@ -1327,21 +1198,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
@@ -1373,6 +1310,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_intern.h b/source/blender/editors/space_image/image_intern.h
index a851684f2f3..2c723f45e94 100644
--- a/source/blender/editors/space_image/image_intern.h
+++ b/source/blender/editors/space_image/image_intern.h
@@ -66,6 +66,7 @@ void IMAGE_OT_reload(struct wmOperatorType *ot);
void IMAGE_OT_save(struct wmOperatorType *ot);
void IMAGE_OT_save_as(struct wmOperatorType *ot);
void IMAGE_OT_save_sequence(struct wmOperatorType *ot);
+void IMAGE_OT_save_all_modified(struct wmOperatorType *ot);
void IMAGE_OT_pack(struct wmOperatorType *ot);
void IMAGE_OT_unpack(struct wmOperatorType *ot);
diff --git a/source/blender/editors/space_image/image_ops.c b/source/blender/editors/space_image/image_ops.c
index cec2e1c68d9..bcea65d1634 100644
--- a/source/blender/editors/space_image/image_ops.c
+++ b/source/blender/editors/space_image/image_ops.c
@@ -34,8 +34,10 @@
#include "MEM_guardedalloc.h"
-#include "BLI_math.h"
#include "BLI_blenlib.h"
+#include "BLI_ghash.h"
+#include "BLI_math.h"
+#include "BLI_string.h"
#include "BLI_utildefines.h"
#include "BLT_translation.h"
@@ -179,31 +181,59 @@ static void sima_zoom_set_from_bounds(SpaceImage *sima, ARegion *ar, const rctf
sima_zoom_set(sima, ar, size, NULL);
}
-#if 0 // currently unused
-static bool image_poll(bContext *C)
+static Image *image_from_context(const bContext *C)
{
- return (CTX_data_edit_image(C) != NULL);
+ /* Edit image is set by templates used throughout the interface, so image
+ * operations work outside the image editor. */
+ Image *ima = CTX_data_pointer_get_type(C, "edit_image", &RNA_Image).data;
+
+ if (ima) {
+ return ima;
+ }
+ else {
+ /* Image editor. */
+ SpaceImage *sima = CTX_wm_space_image(C);
+ return (sima) ? sima->image : NULL;
+ }
}
-#endif
-static bool space_image_buffer_exists_poll(bContext *C)
+static ImageUser *image_user_from_context(const bContext *C)
{
- SpaceImage *sima = CTX_wm_space_image(C);
- if (sima && ED_space_image_has_buffer(sima)) {
- return true;
+ /* Edit image user is set by templates used throughout the interface, so
+ * image operations work outside the image editor. */
+ ImageUser *iuser = CTX_data_pointer_get_type(C, "edit_image_user", &RNA_ImageUser).data;
+
+ if (iuser) {
+ return iuser;
+ }
+ else {
+ /* Image editor. */
+ SpaceImage *sima = CTX_wm_space_image(C);
+ return (sima) ? &sima->iuser : NULL;
}
- return false;
}
-static bool image_not_packed_poll(bContext *C)
+static bool image_buffer_exists_from_context(bContext *C)
{
- SpaceImage *sima = CTX_wm_space_image(C);
+ Image *ima = image_from_context(C);
+ ImageUser *iuser = image_user_from_context(C);
- /* Do not run 'replace' on packed images, it does not give user expected results at all. */
- if (sima && sima->image && BLI_listbase_is_empty(&sima->image->packedfiles)) {
- return true;
+ if (ima == NULL) {
+ return false;
}
- return false;
+
+ void *lock;
+ ImBuf *ibuf = BKE_image_acquire_ibuf(ima, iuser, &lock);
+ const bool has_buffer = (ibuf && (ibuf->rect || ibuf->rect_float));
+ BKE_image_release_ibuf(ima, ibuf, lock);
+ return has_buffer;
+}
+
+static bool image_not_packed_poll(bContext *C)
+{
+ /* Do not run 'replace' on packed images, it does not give user expected results at all. */
+ Image *ima = image_from_context(C);
+ return (ima && BLI_listbase_is_empty(&ima->packedfiles));
}
static bool imbuf_format_writeable(const ImBuf *ibuf)
@@ -214,52 +244,6 @@ static bool imbuf_format_writeable(const ImBuf *ibuf)
return (BKE_image_imtype_to_ftype(im_format.imtype, &options_dummy) == ibuf->ftype);
}
-static bool space_image_file_exists_poll(bContext *C)
-{
- if (space_image_buffer_exists_poll(C)) {
- Main *bmain = CTX_data_main(C);
- SpaceImage *sima = CTX_wm_space_image(C);
- ImBuf *ibuf;
- void *lock;
- bool ret = false;
- char name[FILE_MAX];
-
- ibuf = ED_space_image_acquire_buffer(sima, &lock);
- if (ibuf) {
- BLI_strncpy(name, ibuf->name, FILE_MAX);
- BLI_path_abs(name, BKE_main_blendfile_path(bmain));
-
- if (BLI_exists(name) == false) {
- CTX_wm_operator_poll_msg_set(C, "image file not found");
- }
- else if (!BLI_file_is_writable(name)) {
- CTX_wm_operator_poll_msg_set(C, "image path can't be written to");
- }
- else if (!imbuf_format_writeable(ibuf)) {
- CTX_wm_operator_poll_msg_set(C, "image format is read-only");
- }
- else {
- ret = true;
- }
- }
- ED_space_image_release_buffer(sima, ibuf, lock);
-
- return ret;
- }
- return false;
-}
-
-#if 0 /* UNUSED */
-static bool space_image_poll(bContext *C)
-{
- SpaceImage *sima = CTX_wm_space_image(C);
- if (sima && sima->image) {
- return true;
- }
- return false;
-}
-#endif
-
bool space_image_main_region_poll(bContext *C)
{
SpaceImage *sima = CTX_wm_space_image(C);
@@ -288,24 +272,23 @@ static bool space_image_main_area_not_uv_brush_poll(bContext *C)
static bool image_sample_poll(bContext *C)
{
SpaceImage *sima = CTX_wm_space_image(C);
- if (sima) {
- Object *obedit = CTX_data_edit_object(C);
- if (obedit) {
- /* Disable when UV editing so it doesn't swallow all click events
- * (use for setting cursor). */
- if (ED_space_image_show_uvedit(sima, obedit)) {
- return false;
- }
- }
- else if (sima->mode != SI_MODE_VIEW) {
+ if (sima == NULL) {
+ return false;
+ }
+
+ Object *obedit = CTX_data_edit_object(C);
+ if (obedit) {
+ /* Disable when UV editing so it doesn't swallow all click events
+ * (use for setting cursor). */
+ if (ED_space_image_show_uvedit(sima, obedit)) {
return false;
}
-
- return space_image_main_region_poll(C);
}
- else {
+ else if (sima->mode != SI_MODE_VIEW) {
return false;
}
+
+ return true;
}
/********************** view pan operator *********************/
@@ -1337,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(&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);
}
@@ -1522,21 +1505,16 @@ void IMAGE_OT_open(wmOperatorType *ot)
static int image_match_len_exec(bContext *C, wmOperator *UNUSED(op))
{
Scene *scene = CTX_data_scene(C);
- Image *ima = CTX_data_pointer_get_type(C, "edit_image", &RNA_Image).data;
- ImageUser *iuser = CTX_data_pointer_get_type(C, "edit_image_user", &RNA_ImageUser).data;
+ Image *ima = image_from_context(C);
+ ImageUser *iuser = image_user_from_context(C);
if (!ima || !iuser) {
/* Try to get a Texture, or a SpaceImage from context... */
- SpaceImage *sima = CTX_wm_space_image(C);
Tex *tex = CTX_data_pointer_get_type(C, "texture", &RNA_Texture).data;
if (tex && tex->type == TEX_IMAGE) {
ima = tex->ima;
iuser = &tex->iuser;
}
- else if (sima) {
- ima = sima->image;
- iuser = &sima->iuser;
- }
}
if (!ima || !iuser || !BKE_image_has_anim(ima)) {
@@ -1811,14 +1789,11 @@ static void image_save_options_to_op(ImageSaveOptions *opts, wmOperator *op)
RNA_string_set(op->ptr, "filepath", opts->filepath);
}
-static bool save_image_op(const bContext *C,
- SpaceImage *sima,
- wmOperator *op,
- ImageSaveOptions *opts)
+static bool save_image_op(const bContext *C, wmOperator *op, ImageSaveOptions *opts)
{
Main *bmain = CTX_data_main(C);
- Image *ima = ED_space_image(sima);
- ImageUser *iuser = &sima->iuser;
+ Image *ima = image_from_context(C);
+ ImageUser *iuser = image_user_from_context(C);
opts->relative = (RNA_struct_find_property(op->ptr, "relative_path") &&
RNA_boolean_get(op->ptr, "relative_path"));
@@ -1856,21 +1831,27 @@ static int image_save_as_exec(bContext *C, wmOperator *op)
{
Main *bmain = CTX_data_main(C);
Scene *scene = CTX_data_scene(C);
- SpaceImage *sima = CTX_wm_space_image(C);
+ Image *image = image_from_context(C);
+ ImageUser *iuser = image_user_from_context(C);
ImageSaveOptions opts;
BKE_image_save_options_init(&opts, bmain, scene);
/* just in case to initialize values,
* these should be set on invoke or by the caller. */
- image_save_options_init(bmain, &opts, sima->image, &sima->iuser, false, false);
+ image_save_options_init(bmain, &opts, image, iuser, false, false);
image_save_options_from_op(bmain, &opts, op);
opts.do_newpath = true;
- save_image_op(C, sima, op, &opts);
+ save_image_op(C, op, &opts);
+
+ if (opts.save_copy == false) {
+ BKE_image_free_packedfiles(image);
+ }
image_save_as_free(op);
+
return OPERATOR_FINISHED;
}
@@ -1883,8 +1864,8 @@ static bool image_save_as_check(bContext *UNUSED(C), wmOperator *op)
static int image_save_as_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event))
{
Main *bmain = CTX_data_main(C);
- SpaceImage *sima = CTX_wm_space_image(C);
- Image *ima = ED_space_image(sima);
+ Image *ima = image_from_context(C);
+ ImageUser *iuser = image_user_from_context(C);
Scene *scene = CTX_data_scene(C);
ImageSaveOptions opts;
PropertyRNA *prop;
@@ -1897,7 +1878,7 @@ static int image_save_as_invoke(bContext *C, wmOperator *op, const wmEvent *UNUS
BKE_image_save_options_init(&opts, bmain, scene);
- if (image_save_options_init(bmain, &opts, ima, &sima->iuser, true, save_as_render) == 0) {
+ if (image_save_options_init(bmain, &opts, ima, iuser, true, save_as_render) == 0) {
return OPERATOR_CANCELLED;
}
image_save_options_to_op(&opts, op);
@@ -1965,20 +1946,21 @@ static void image_save_as_draw(bContext *UNUSED(C), wmOperator *op)
static bool image_save_as_poll(bContext *C)
{
- if (space_image_buffer_exists_poll(C)) {
- if (G.is_rendering) {
- /* no need to NULL check here */
- SpaceImage *sima = CTX_wm_space_image(C);
- Image *ima = ED_space_image(sima);
+ if (!image_buffer_exists_from_context(C)) {
+ return false;
+ }
- if (ima->source == IMA_SRC_VIEWER) {
- CTX_wm_operator_poll_msg_set(C, "can't save image while rendering");
- return false;
- }
+ if (G.is_rendering) {
+ /* no need to NULL check here */
+ Image *ima = image_from_context(C);
+
+ if (ima->source == IMA_SRC_VIEWER) {
+ CTX_wm_operator_poll_msg_set(C, "can't save image while rendering");
+ return false;
}
- return true;
}
- return false;
+
+ return true;
}
void IMAGE_OT_save_as(wmOperatorType *ot)
@@ -2022,21 +2004,83 @@ void IMAGE_OT_save_as(wmOperatorType *ot)
/******************** save image operator ********************/
+static bool image_file_path_saveable(bContext *C, Image *ima, ImageUser *iuser)
+{
+ /* Can always repack images. */
+ if (BKE_image_has_packedfile(ima)) {
+ return true;
+ }
+
+ /* Test for valid filepath. */
+ void *lock;
+ ImBuf *ibuf = BKE_image_acquire_ibuf(ima, iuser, &lock);
+ bool ret = false;
+
+ if (ibuf) {
+ Main *bmain = CTX_data_main(C);
+ char name[FILE_MAX];
+ BLI_strncpy(name, ibuf->name, FILE_MAX);
+ BLI_path_abs(name, BKE_main_blendfile_path(bmain));
+
+ if (BLI_exists(name) == false) {
+ CTX_wm_operator_poll_msg_set(C, "image file not found");
+ }
+ else if (!BLI_file_is_writable(name)) {
+ CTX_wm_operator_poll_msg_set(C, "image path can't be written to");
+ }
+ else if (!imbuf_format_writeable(ibuf)) {
+ CTX_wm_operator_poll_msg_set(C, "image format is read-only");
+ }
+ else {
+ ret = true;
+ }
+ }
+
+ BKE_image_release_ibuf(ima, ibuf, lock);
+ return ret;
+}
+
+static bool image_save_poll(bContext *C)
+{
+ /* Can't save if there are no pixels. */
+ if (image_buffer_exists_from_context(C) == false) {
+ return false;
+ }
+
+ Image *ima = image_from_context(C);
+ ImageUser *iuser = image_user_from_context(C);
+
+ /* Images without a filepath will go to save as. */
+ if (!BKE_image_has_filepath(ima)) {
+ return true;
+ }
+
+ /* Check if there is a valid file path and image format we can write. */
+ return image_file_path_saveable(C, ima, iuser);
+}
+
static int image_save_exec(bContext *C, wmOperator *op)
{
Main *bmain = CTX_data_main(C);
- SpaceImage *sima = CTX_wm_space_image(C);
+ Image *image = image_from_context(C);
+ ImageUser *iuser = image_user_from_context(C);
Scene *scene = CTX_data_scene(C);
ImageSaveOptions opts;
+ if (BKE_image_has_packedfile(image)) {
+ /* Save packed files to memory. */
+ BKE_image_memorypack(image);
+ return OPERATOR_FINISHED;
+ }
+
BKE_image_save_options_init(&opts, bmain, scene);
- if (image_save_options_init(bmain, &opts, sima->image, &sima->iuser, false, false) == 0) {
+ if (image_save_options_init(bmain, &opts, image, iuser, false, false) == 0) {
return OPERATOR_CANCELLED;
}
image_save_options_from_op(bmain, &opts, op);
if (BLI_exists(opts.filepath) && BLI_file_is_writable(opts.filepath)) {
- if (save_image_op(C, sima, op, &opts)) {
+ if (save_image_op(C, op, &opts)) {
/* report since this can be called from key-shortcuts */
BKE_reportf(op->reports, RPT_INFO, "Saved Image '%s'", opts.filepath);
}
@@ -2050,6 +2094,19 @@ static int image_save_exec(bContext *C, wmOperator *op)
return OPERATOR_FINISHED;
}
+static int image_save_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event))
+{
+ Image *ima = image_from_context(C);
+
+ if (!BKE_image_has_packedfile(ima) && !BKE_image_has_filepath(ima)) {
+ WM_operator_name_call(C, "IMAGE_OT_save_as", WM_OP_INVOKE_DEFAULT, NULL);
+ return OPERATOR_CANCELLED;
+ }
+ else {
+ return image_save_exec(C, op);
+ }
+}
+
void IMAGE_OT_save(wmOperatorType *ot)
{
/* identifiers */
@@ -2059,7 +2116,8 @@ void IMAGE_OT_save(wmOperatorType *ot)
/* api callbacks */
ot->exec = image_save_exec;
- ot->poll = space_image_file_exists_poll;
+ ot->invoke = image_save_invoke;
+ ot->poll = image_save_poll;
/* flags */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
@@ -2070,30 +2128,30 @@ void IMAGE_OT_save(wmOperatorType *ot)
static int image_save_sequence_exec(bContext *C, wmOperator *op)
{
Main *bmain = CTX_data_main(C);
- SpaceImage *sima = CTX_wm_space_image(C);
+ Image *image = image_from_context(C);
ImBuf *ibuf, *first_ibuf = NULL;
int tot = 0;
char di[FILE_MAX];
struct MovieCacheIter *iter;
- if (sima->image == NULL) {
+ if (image == NULL) {
return OPERATOR_CANCELLED;
}
- if (sima->image->source != IMA_SRC_SEQUENCE) {
+ if (image->source != IMA_SRC_SEQUENCE) {
BKE_report(op->reports, RPT_ERROR, "Can only save sequence on image sequences");
return OPERATOR_CANCELLED;
}
- if (sima->image->type == IMA_TYPE_MULTILAYER) {
+ if (image->type == IMA_TYPE_MULTILAYER) {
BKE_report(op->reports, RPT_ERROR, "Cannot save multilayer sequences");
return OPERATOR_CANCELLED;
}
/* get total dirty buffers and first dirty buffer which is used for menu */
ibuf = NULL;
- if (sima->image->cache != NULL) {
- iter = IMB_moviecacheIter_new(sima->image->cache);
+ if (image->cache != NULL) {
+ iter = IMB_moviecacheIter_new(image->cache);
while (!IMB_moviecacheIter_done(iter)) {
ibuf = IMB_moviecacheIter_getImBuf(iter);
if (ibuf->userflags & IB_BITMAPDIRTY) {
@@ -2116,7 +2174,7 @@ static int image_save_sequence_exec(bContext *C, wmOperator *op)
BLI_split_dir_part(first_ibuf->name, di, sizeof(di));
BKE_reportf(op->reports, RPT_INFO, "%d image(s) will be saved in %s", tot, di);
- iter = IMB_moviecacheIter_new(sima->image->cache);
+ iter = IMB_moviecacheIter_new(image->cache);
while (!IMB_moviecacheIter_done(iter)) {
ibuf = IMB_moviecacheIter_getImBuf(iter);
@@ -2151,7 +2209,139 @@ void IMAGE_OT_save_sequence(wmOperatorType *ot)
/* api callbacks */
ot->exec = image_save_sequence_exec;
- ot->poll = space_image_buffer_exists_poll;
+ ot->poll = image_buffer_exists_from_context;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+}
+
+/********************** save all operator **********************/
+
+static bool image_should_be_saved_when_modified(Image *ima)
+{
+ return !ELEM(ima->type, IMA_TYPE_R_RESULT, IMA_TYPE_COMPOSITE);
+}
+
+static bool image_should_be_saved(Image *ima)
+{
+ if (BKE_image_is_dirty(ima) &&
+ (ima->source == IMA_SRC_FILE || ima->source == IMA_SRC_GENERATED)) {
+ return image_should_be_saved_when_modified(ima);
+ }
+ else {
+ return false;
+ }
+}
+
+static bool image_has_valid_path(Image *ima)
+{
+ return strchr(ima->name, '\\') || strchr(ima->name, '/');
+}
+
+bool ED_image_should_save_modified(const bContext *C)
+{
+ return ED_image_save_all_modified_info(C, NULL) > 0;
+}
+
+int ED_image_save_all_modified_info(const bContext *C, ReportList *reports)
+{
+ Main *bmain = CTX_data_main(C);
+ GSet *unique_paths = BLI_gset_str_new(__func__);
+
+ int num_saveable_images = 0;
+
+ for (Image *ima = bmain->images.first; ima; ima = ima->id.next) {
+ if (image_should_be_saved(ima)) {
+ if (BKE_image_has_packedfile(ima) || (ima->source == IMA_SRC_GENERATED)) {
+ if (ima->id.lib == NULL) {
+ num_saveable_images++;
+ }
+ else {
+ BKE_reportf(reports,
+ RPT_WARNING,
+ "Packed library image: %s from library %s can't be saved",
+ ima->id.name,
+ ima->id.lib->name);
+ }
+ }
+ else {
+ if (image_has_valid_path(ima)) {
+ num_saveable_images++;
+ if (BLI_gset_haskey(unique_paths, ima->name)) {
+ BKE_reportf(reports,
+ RPT_WARNING,
+ "File path used by more than one saved image: %s",
+ ima->name);
+ }
+ else {
+ BLI_gset_insert(unique_paths, BLI_strdup(ima->name));
+ }
+ }
+ else {
+ BKE_reportf(reports,
+ RPT_WARNING,
+ "Image %s can't be saved, no valid file path: %s",
+ ima->id.name,
+ ima->name);
+ }
+ }
+ }
+ }
+
+ BLI_gset_free(unique_paths, MEM_freeN);
+ return num_saveable_images;
+}
+
+bool ED_image_save_all_modified(const bContext *C, ReportList *reports)
+{
+ ED_image_save_all_modified_info(C, reports);
+
+ Main *bmain = CTX_data_main(C);
+ bool ok = true;
+
+ for (Image *ima = bmain->images.first; ima; ima = ima->id.next) {
+ if (image_should_be_saved(ima)) {
+ if (BKE_image_has_packedfile(ima) || (ima->source == IMA_SRC_GENERATED)) {
+ BKE_image_memorypack(ima);
+ }
+ else {
+ if (image_has_valid_path(ima)) {
+ ImageSaveOptions opts;
+ Scene *scene = CTX_data_scene(C);
+ BKE_image_save_options_init(&opts, bmain, scene);
+ if (image_save_options_init(bmain, &opts, ima, NULL, false, false)) {
+ bool saved_successfully = BKE_image_save(reports, bmain, ima, NULL, &opts);
+ ok = ok && saved_successfully;
+ }
+ }
+ }
+ }
+ }
+ return ok;
+}
+
+static bool image_save_all_modified_poll(bContext *C)
+{
+ int num_files = ED_image_save_all_modified_info(C, NULL);
+ return num_files > 0;
+}
+
+static int image_save_all_modified_exec(bContext *C, wmOperator *op)
+{
+ ED_image_save_all_modified(C, op->reports);
+ return OPERATOR_FINISHED;
+}
+
+void IMAGE_OT_save_all_modified(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name = "Save All Modified";
+ ot->idname = "IMAGE_OT_save_all_modified";
+ ot->description = "Save all modified images";
+
+ /* api callbacks */
+ ot->exec = image_save_all_modified_exec;
+ ot->poll = image_save_all_modified_poll;
/* flags */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
@@ -2162,8 +2352,8 @@ void IMAGE_OT_save_sequence(wmOperatorType *ot)
static int image_reload_exec(bContext *C, wmOperator *UNUSED(op))
{
Main *bmain = CTX_data_main(C);
- Image *ima = CTX_data_edit_image(C);
- SpaceImage *sima = CTX_wm_space_image(C);
+ Image *ima = image_from_context(C);
+ ImageUser *iuser = image_user_from_context(C);
if (!ima) {
return OPERATOR_CANCELLED;
@@ -2172,7 +2362,7 @@ static int image_reload_exec(bContext *C, wmOperator *UNUSED(op))
/* XXX unpackImage frees image buffers */
ED_preview_kill_jobs(CTX_wm_manager(C), CTX_data_main(C));
- BKE_image_signal(bmain, ima, (sima) ? &sima->iuser : NULL, IMA_SIGNAL_RELOAD);
+ BKE_image_signal(bmain, ima, iuser, IMA_SIGNAL_RELOAD);
DEG_id_tag_update(&ima->id, 0);
WM_event_add_notifier(C, NC_IMAGE | NA_EDITED, ima);
@@ -2284,7 +2474,7 @@ static int image_new_exec(bContext *C, wmOperator *op)
PointerRNA imaptr;
RNA_id_pointer_create(&ima->id, &imaptr);
- RNA_property_pointer_set(&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) {
@@ -2414,14 +2604,14 @@ void IMAGE_OT_new(wmOperatorType *ot)
static bool image_invert_poll(bContext *C)
{
- Image *ima = CTX_data_edit_image(C);
+ Image *ima = image_from_context(C);
return BKE_image_has_ibuf(ima, NULL);
}
static int image_invert_exec(bContext *C, wmOperator *op)
{
- Image *ima = CTX_data_edit_image(C);
+ Image *ima = image_from_context(C);
ImBuf *ibuf = BKE_image_acquire_ibuf(ima, NULL, NULL);
SpaceImage *sima = CTX_wm_space_image(C);
/* undo is supported only on image paint mode currently */
@@ -2494,7 +2684,8 @@ static int image_invert_exec(bContext *C, wmOperator *op)
return OPERATOR_CANCELLED;
}
- ibuf->userflags |= IB_BITMAPDIRTY | IB_DISPLAY_BUFFER_INVALID;
+ ibuf->userflags |= IB_DISPLAY_BUFFER_INVALID;
+ BKE_image_mark_dirty(ima, ibuf);
if (ibuf->mipmap[0]) {
ibuf->userflags |= IB_MIPMAP_INVALID;
@@ -2545,7 +2736,7 @@ void IMAGE_OT_invert(wmOperatorType *ot)
static bool image_pack_test(bContext *C, wmOperator *op)
{
- Image *ima = CTX_data_edit_image(C);
+ Image *ima = image_from_context(C);
if (!ima) {
return 0;
@@ -2562,7 +2753,7 @@ static bool image_pack_test(bContext *C, wmOperator *op)
static int image_pack_exec(bContext *C, wmOperator *op)
{
struct Main *bmain = CTX_data_main(C);
- Image *ima = CTX_data_edit_image(C);
+ Image *ima = image_from_context(C);
if (!image_pack_test(C, op)) {
return OPERATOR_CANCELLED;
@@ -2598,7 +2789,7 @@ void IMAGE_OT_pack(wmOperatorType *ot)
static int image_unpack_exec(bContext *C, wmOperator *op)
{
- Image *ima = CTX_data_edit_image(C);
+ Image *ima = image_from_context(C);
int method = RNA_enum_get(op->ptr, "method");
/* find the suppplied image by name */
@@ -2607,7 +2798,7 @@ static int image_unpack_exec(bContext *C, wmOperator *op)
RNA_string_get(op->ptr, "id", imaname);
ima = BLI_findstring(&CTX_data_main(C)->images, imaname, offsetof(ID, name) + 2);
if (!ima) {
- ima = CTX_data_edit_image(C);
+ ima = image_from_context(C);
}
}
@@ -2638,7 +2829,7 @@ static int image_unpack_exec(bContext *C, wmOperator *op)
static int image_unpack_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event))
{
- Image *ima = CTX_data_edit_image(C);
+ Image *ima = image_from_context(C);
if (RNA_struct_property_is_set(op->ptr, "id")) {
return image_unpack_exec(C, op);
@@ -3225,176 +3416,18 @@ void IMAGE_OT_curves_point_set(wmOperatorType *ot)
RNA_def_property_flag(prop, PROP_SKIP_SAVE);
}
-#if 0 /* Not ported to 2.5x yet */
-/******************** record composite operator *********************/
-
-typedef struct RecordCompositeData {
- wmTimer *timer;
- int old_cfra;
- int sfra, efra;
-} RecordCompositeData;
-
-static int image_record_composite_apply(bContext *C, wmOperator *op)
-{
- SpaceImage *sima = CTX_wm_space_image(C);
- RecordCompositeData *rcd = op->customdata;
- Scene *scene = CTX_data_scene(C);
- ImBuf *ibuf;
-
- WM_cursor_time(CTX_wm_window(C), scene->r.cfra);
-
- // XXX scene->nodetree->test_break = BKE_blender_test_break;
- // XXX scene->nodetree->test_break = NULL;
-
- BKE_image_all_free_anim_ibufs(scene->r.cfra);
- ntreeCompositExecTree(scene->nodetree,
- &scene->r,
- 0,
- scene->r.cfra != rcd->old_cfra,
- &scene->view_settings,
- &scene->display_settings); /* 1 is no previews */
-
- ED_area_tag_redraw(CTX_wm_area(C));
-
- ibuf = BKE_image_acquire_ibuf(sima->image, &sima->iuser, NULL);
- /* save memory in flipbooks */
- if (ibuf)
- imb_freerectfloatImBuf(ibuf);
-
- BKE_image_release_ibuf(sima->image, ibuf, NULL);
-
- scene->r.cfra++;
-
- return (scene->r.cfra <= rcd->efra);
-}
-
-static int image_record_composite_init(bContext *C, wmOperator *op)
-{
- SpaceImage *sima = CTX_wm_space_image(C);
- Scene *scene = CTX_data_scene(C);
- RecordCompositeData *rcd;
-
- if (sima->iuser.frames < 2)
- return 0;
- if (scene->nodetree == NULL)
- return 0;
-
- op->customdata = rcd = MEM_callocN(sizeof(RecordCompositeData), "ImageRecordCompositeData");
-
- rcd->old_cfra = scene->r.cfra;
- rcd->sfra = sima->iuser.sfra;
- rcd->efra = sima->iuser.sfra + sima->iuser.frames - 1;
- scene->r.cfra = rcd->sfra;
-
- return 1;
-}
-
-static void image_record_composite_exit(bContext *C, wmOperator *op)
-{
- Scene *scene = CTX_data_scene(C);
- SpaceImage *sima = CTX_wm_space_image(C);
- RecordCompositeData *rcd = op->customdata;
-
- scene->r.cfra = rcd->old_cfra;
-
- WM_cursor_modal_restore(CTX_wm_window(C));
-
- if (rcd->timer)
- WM_event_remove_timer(CTX_wm_manager(C), CTX_wm_window(C), rcd->timer);
-
- WM_event_add_notifier(C, NC_IMAGE | NA_EDITED, sima->image);
-
- // XXX play_anim(0);
- // XXX allqueue(REDRAWNODE, 1);
-
- MEM_freeN(rcd);
-}
-
-static int image_record_composite_exec(bContext *C, wmOperator *op)
-{
- if (!image_record_composite_init(C, op))
- return OPERATOR_CANCELLED;
-
- while (image_record_composite_apply(C, op)) {
- }
-
- image_record_composite_exit(C, op);
-
- return OPERATOR_FINISHED;
-}
-
-static int image_record_composite_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event))
-{
- RecordCompositeData *rcd;
-
- if (!image_record_composite_init(C, op))
- return OPERATOR_CANCELLED;
-
- rcd = op->customdata;
- rcd->timer = WM_event_add_timer(CTX_wm_manager(C), CTX_wm_window(C), TIMER, 0.0f);
- WM_event_add_modal_handler(C, op);
-
- if (!image_record_composite_apply(C, op))
- return OPERATOR_FINISHED;
-
- return OPERATOR_RUNNING_MODAL;
-}
-
-static int image_record_composite_modal(bContext *C, wmOperator *op, const wmEvent *event)
-{
- RecordCompositeData *rcd = op->customdata;
-
- switch (event->type) {
- case TIMER:
- if (rcd->timer == event->customdata) {
- if (!image_record_composite_apply(C, op)) {
- image_record_composite_exit(C, op);
- return OPERATOR_FINISHED;
- }
- }
- break;
- case ESCKEY:
- image_record_composite_exit(C, op);
- return OPERATOR_FINISHED;
- }
-
- return OPERATOR_RUNNING_MODAL;
-}
-
-static void image_record_composite_cancel(bContext *C, wmOperator *op)
-{
- image_record_composite_exit(C, op);
- return OPERATOR_CANCELLED;
-}
-
-void IMAGE_OT_record_composite(wmOperatorType *ot)
-{
- /* identifiers */
- ot->name = "Record Composite";
- ot->idname = "IMAGE_OT_record_composite";
-
- /* api callbacks */
- ot->exec = image_record_composite_exec;
- ot->invoke = image_record_composite_invoke;
- ot->modal = image_record_composite_modal;
- ot->cancel = image_record_composite_cancel;
- ot->poll = space_image_buffer_exists_poll;
-}
-
-#endif
-
/********************* cycle render slot operator *********************/
static bool image_cycle_render_slot_poll(bContext *C)
{
- Image *ima = CTX_data_edit_image(C);
+ Image *ima = image_from_context(C);
return (ima && ima->type == IMA_TYPE_R_RESULT);
}
static int image_cycle_render_slot_exec(bContext *C, wmOperator *op)
{
- Image *ima = CTX_data_edit_image(C);
+ Image *ima = image_from_context(C);
const int direction = RNA_boolean_get(op->ptr, "reverse") ? -1 : 1;
if (!ED_image_slot_cycle(ima, direction)) {
@@ -3434,7 +3467,7 @@ void IMAGE_OT_cycle_render_slot(wmOperatorType *ot)
static int image_clear_render_slot_exec(bContext *C, wmOperator *UNUSED(op))
{
SpaceImage *sima = CTX_wm_space_image(C);
- Image *ima = CTX_data_edit_image(C);
+ Image *ima = image_from_context(C);
if (!BKE_image_clear_renderslot(ima, &sima->iuser, ima->render_slot)) {
return OPERATOR_CANCELLED;
@@ -3464,7 +3497,7 @@ void IMAGE_OT_clear_render_slot(wmOperatorType *ot)
static int image_add_render_slot_exec(bContext *C, wmOperator *UNUSED(op))
{
- Image *ima = CTX_data_edit_image(C);
+ Image *ima = image_from_context(C);
RenderSlot *slot = BKE_image_add_renderslot(ima, NULL);
ima->render_slot = BLI_findindex(&ima->renderslots, slot);
@@ -3494,7 +3527,7 @@ void IMAGE_OT_add_render_slot(wmOperatorType *ot)
static int image_remove_render_slot_exec(bContext *C, wmOperator *UNUSED(op))
{
SpaceImage *sima = CTX_wm_space_image(C);
- Image *ima = CTX_data_edit_image(C);
+ Image *ima = image_from_context(C);
if (!BKE_image_remove_renderslot(ima, &sima->iuser, ima->render_slot)) {
return OPERATOR_CANCELLED;
diff --git a/source/blender/editors/space_image/space_image.c b/source/blender/editors/space_image/space_image.c
index 386e258a833..a8be93ad213 100644
--- a/source/blender/editors/space_image/space_image.c
+++ b/source/blender/editors/space_image/space_image.c
@@ -224,6 +224,7 @@ static void image_operatortypes(void)
WM_operatortype_append(IMAGE_OT_save);
WM_operatortype_append(IMAGE_OT_save_as);
WM_operatortype_append(IMAGE_OT_save_sequence);
+ WM_operatortype_append(IMAGE_OT_save_all_modified);
WM_operatortype_append(IMAGE_OT_pack);
WM_operatortype_append(IMAGE_OT_unpack);
@@ -567,7 +568,8 @@ static void image_main_region_draw(const bContext *C, ARegion *ar)
Object *obedit = CTX_data_edit_object(C);
Depsgraph *depsgraph = CTX_data_depsgraph(C);
Mask *mask = NULL;
- bool curve = false;
+ bool show_uvedit = false;
+ bool show_curve = false;
Scene *scene = CTX_data_scene(C);
ViewLayer *view_layer = CTX_data_view_layer(C);
View2D *v2d = &ar->v2d;
@@ -609,13 +611,13 @@ static void image_main_region_draw(const bContext *C, ARegion *ar)
/* check for mask (delay draw) */
if (ED_space_image_show_uvedit(sima, obedit)) {
- /* pass */
+ show_uvedit = true;
}
else if (sima->mode == SI_MODE_MASK) {
mask = ED_space_image_get_mask(sima);
}
else if (ED_space_image_paint_curve(C)) {
- curve = true;
+ show_curve = true;
}
ED_region_draw_cb_draw(C, ar, REGION_DRAW_POST_VIEW);
@@ -669,12 +671,9 @@ static void image_main_region_draw(const bContext *C, ARegion *ar)
false,
NULL,
C);
-
- UI_view2d_view_ortho(v2d);
- ED_image_draw_cursor(ar, sima->cursor);
- UI_view2d_view_restore(C);
}
- else if (curve) {
+
+ if (show_uvedit || mask || show_curve) {
UI_view2d_view_ortho(v2d);
ED_image_draw_cursor(ar, sima->cursor);
UI_view2d_view_restore(C);
@@ -764,7 +763,7 @@ static void image_buttons_region_layout(const bContext *C, ARegion *ar)
}
const bool vertical = true;
- ED_region_panels_layout_ex(C, ar, contexts_base, -1, vertical);
+ ED_region_panels_layout_ex(C, ar, &ar->type->paneltypes, contexts_base, -1, vertical, NULL);
}
static void image_buttons_region_draw(const bContext *C, ARegion *ar)
@@ -1035,9 +1034,10 @@ void ED_spacetype_image(void)
/* regions: listview/buttons/scopes */
art = MEM_callocN(sizeof(ARegionType), "spacetype image region");
art->regionid = RGN_TYPE_UI;
- art->prefsizex = 220; // XXX
+ art->prefsizex = UI_SIDEBAR_PANEL_WIDTH;
art->keymapflag = ED_KEYMAP_UI | ED_KEYMAP_FRAMES;
art->listener = image_buttons_region_listener;
+ art->message_subscribe = ED_area_do_mgs_subscribe_for_tool_ui;
art->init = image_buttons_region_init;
art->layout = image_buttons_region_layout;
art->draw = image_buttons_region_draw;
diff --git a/source/blender/editors/space_info/info_ops.c b/source/blender/editors/space_info/info_ops.c
index 171d8505222..bf43e493cc5 100644
--- a/source/blender/editors/space_info/info_ops.c
+++ b/source/blender/editors/space_info/info_ops.c
@@ -160,19 +160,11 @@ static int pack_all_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(ev
{
Main *bmain = CTX_data_main(C);
Image *ima;
- ImBuf *ibuf;
// first check for dirty images
for (ima = bmain->images.first; ima; ima = ima->id.next) {
- if (BKE_image_has_loaded_ibuf(ima)) { /* XXX FIX */
- ibuf = BKE_image_acquire_ibuf(ima, NULL, NULL);
-
- if (ibuf && (ibuf->userflags & IB_BITMAPDIRTY)) {
- BKE_image_release_ibuf(ima, ibuf, NULL);
- break;
- }
-
- BKE_image_release_ibuf(ima, ibuf, NULL);
+ if (BKE_image_is_dirty(ima)) {
+ break;
}
}
diff --git a/source/blender/editors/space_nla/nla_channels.c b/source/blender/editors/space_nla/nla_channels.c
index 4115d6b49ba..e5c116e85de 100644
--- a/source/blender/editors/space_nla/nla_channels.c
+++ b/source/blender/editors/space_nla/nla_channels.c
@@ -52,6 +52,8 @@
#include "WM_api.h"
#include "WM_types.h"
+#include "UI_interface.h"
+
#include "DEG_depsgraph.h"
#include "DEG_depsgraph_build.h"
@@ -384,19 +386,12 @@ static int nlachannels_mouseclick_invoke(bContext *C, wmOperator *op, const wmEv
selectmode = SELECT_REPLACE;
}
- /**
- * Figure out which channel user clicked in:
- *
- * \note Although channels technically start at y= NLACHANNEL_FIRST,
- * we need to adjust by half a channel's height so that the tops of channels get caught ok.
- * Since NLACHANNEL_FIRST is really NLACHANNEL_HEIGHT, we simply use NLACHANNEL_HEIGHT_HALF.
- */
+ /* Figure out which channel user clicked in. */
UI_view2d_region_to_view(v2d, event->mval[0], event->mval[1], &x, &y);
- UI_view2d_listview_view_to_cell(v2d,
- NLACHANNEL_NAMEWIDTH,
+ UI_view2d_listview_view_to_cell(NLACHANNEL_NAMEWIDTH,
NLACHANNEL_STEP(snla),
0,
- (float)NLACHANNEL_HEIGHT_HALF(snla),
+ NLACHANNEL_FIRST_TOP(&ac),
x,
y,
NULL,
diff --git a/source/blender/editors/space_nla/nla_draw.c b/source/blender/editors/space_nla/nla_draw.c
index 1df2190b7af..68cbfd76331 100644
--- a/source/blender/editors/space_nla/nla_draw.c
+++ b/source/blender/editors/space_nla/nla_draw.c
@@ -689,23 +689,19 @@ void draw_nla_main_data(bAnimContext *ac, SpaceNla *snla, ARegion *ar)
* - offset of NLACHANNEL_HEIGHT*2 is added to the height of the channels, as first is for
* start of list offset, and the second is as a correction for the scrollers.
*/
- int height = ((items * NLACHANNEL_STEP(snla)) + (NLACHANNEL_HEIGHT(snla) * 2));
-
- /* don't use totrect set, as the width stays the same
- * (NOTE: this is ok here, the configuration is pretty straightforward)
- */
- v2d->tot.ymin = (float)(-height);
+ int height = NLACHANNEL_TOT_HEIGHT(ac, items);
+ v2d->tot.ymin = -height;
/* loop through channels, and set up drawing depending on their type */
- float y = (float)(-NLACHANNEL_HEIGHT(snla));
+ float ymax = NLACHANNEL_FIRST_TOP(ac);
- for (bAnimListElem *ale = anim_data.first; ale; ale = ale->next) {
- const float yminc = (float)(y - NLACHANNEL_HEIGHT_HALF(snla));
- const float ymaxc = (float)(y + NLACHANNEL_HEIGHT_HALF(snla));
+ for (bAnimListElem *ale = anim_data.first; ale; ale = ale->next, ymax -= NLACHANNEL_STEP(snla)) {
+ float ymin = ymax - NLACHANNEL_HEIGHT(snla);
+ float ycenter = (ymax + ymin) / 2.0f;
/* check if visible */
- if (IN_RANGE(yminc, v2d->cur.ymin, v2d->cur.ymax) ||
- IN_RANGE(ymaxc, v2d->cur.ymin, v2d->cur.ymax)) {
+ if (IN_RANGE(ymin, v2d->cur.ymin, v2d->cur.ymax) ||
+ IN_RANGE(ymax, v2d->cur.ymin, v2d->cur.ymax)) {
/* data to draw depends on the type of channel */
switch (ale->type) {
case ANIMTYPE_NLATRACK: {
@@ -721,18 +717,18 @@ void draw_nla_main_data(bAnimContext *ac, SpaceNla *snla, ARegion *ar)
const float xmaxc = strip->end + text_margin_x;
/* draw the visualization of the strip */
- nla_draw_strip(snla, adt, nlt, strip, v2d, yminc, ymaxc);
+ nla_draw_strip(snla, adt, nlt, strip, v2d, ymin, ymax);
/* add the text for this strip to the cache */
if (xminc < xmaxc) {
- nla_draw_strip_text(adt, nlt, strip, index, v2d, xminc, xmaxc, yminc, ymaxc);
+ nla_draw_strip_text(adt, nlt, strip, index, v2d, xminc, xmaxc, ymin, ymax);
}
/* if transforming strips (only real reason for temp-metas currently),
* add to the cache the frame numbers of the strip's extents
*/
if (strip->flag & NLASTRIP_FLAG_TEMP_META) {
- nla_draw_strip_frames_text(nlt, strip, v2d, yminc, ymaxc);
+ nla_draw_strip_frames_text(nlt, strip, v2d, ymin, ymax);
}
}
}
@@ -761,27 +757,27 @@ void draw_nla_main_data(bAnimContext *ac, SpaceNla *snla, ARegion *ar)
* but also slightly shorter for some more contrast when viewing the strips
*/
immRectf(
- pos, v2d->cur.xmin, yminc + NLACHANNEL_SKIP, v2d->cur.xmax, ymaxc - NLACHANNEL_SKIP);
+ pos, v2d->cur.xmin, ymin + NLACHANNEL_SKIP, v2d->cur.xmax, ymax - NLACHANNEL_SKIP);
/* draw 'embossed' lines above and below the strip for effect */
/* white base-lines */
GPU_line_width(2.0f);
immUniformColor4f(1.0f, 1.0f, 1.0f, 0.3f);
immBegin(GPU_PRIM_LINES, 4);
- immVertex2f(pos, v2d->cur.xmin, yminc + NLACHANNEL_SKIP);
- immVertex2f(pos, v2d->cur.xmax, yminc + NLACHANNEL_SKIP);
- immVertex2f(pos, v2d->cur.xmin, ymaxc - NLACHANNEL_SKIP);
- immVertex2f(pos, v2d->cur.xmax, ymaxc - NLACHANNEL_SKIP);
+ immVertex2f(pos, v2d->cur.xmin, ymin + NLACHANNEL_SKIP);
+ immVertex2f(pos, v2d->cur.xmax, ymin + NLACHANNEL_SKIP);
+ immVertex2f(pos, v2d->cur.xmin, ymax - NLACHANNEL_SKIP);
+ immVertex2f(pos, v2d->cur.xmax, ymax - NLACHANNEL_SKIP);
immEnd();
/* black top-lines */
GPU_line_width(1.0f);
immUniformColor3f(0.0f, 0.0f, 0.0f);
immBegin(GPU_PRIM_LINES, 4);
- immVertex2f(pos, v2d->cur.xmin, yminc + NLACHANNEL_SKIP);
- immVertex2f(pos, v2d->cur.xmax, yminc + NLACHANNEL_SKIP);
- immVertex2f(pos, v2d->cur.xmin, ymaxc - NLACHANNEL_SKIP);
- immVertex2f(pos, v2d->cur.xmax, ymaxc - NLACHANNEL_SKIP);
+ immVertex2f(pos, v2d->cur.xmin, ymin + NLACHANNEL_SKIP);
+ immVertex2f(pos, v2d->cur.xmax, ymin + NLACHANNEL_SKIP);
+ immVertex2f(pos, v2d->cur.xmin, ymax - NLACHANNEL_SKIP);
+ immVertex2f(pos, v2d->cur.xmax, ymax - NLACHANNEL_SKIP);
immEnd();
/* TODO: these lines but better --^ */
@@ -790,16 +786,13 @@ void draw_nla_main_data(bAnimContext *ac, SpaceNla *snla, ARegion *ar)
/* draw keyframes in the action */
nla_action_draw_keyframes(
- v2d, adt, ale->data, y, yminc + NLACHANNEL_SKIP, ymaxc - NLACHANNEL_SKIP);
+ v2d, adt, ale->data, ycenter, ymin + NLACHANNEL_SKIP, ymax - NLACHANNEL_SKIP);
GPU_blend(false);
break;
}
}
}
-
- /* adjust y-position for next one */
- y -= NLACHANNEL_STEP(snla);
}
/* free tempolary channels */
@@ -817,7 +810,6 @@ void draw_nla_channel_list(const bContext *C, bAnimContext *ac, ARegion *ar)
SpaceNla *snla = (SpaceNla *)ac->sl;
View2D *v2d = &ar->v2d;
- float y = 0.0f;
size_t items;
/* build list of channels to draw */
@@ -830,11 +822,9 @@ void draw_nla_channel_list(const bContext *C, bAnimContext *ac, ARegion *ar)
* - offset of NLACHANNEL_HEIGHT*2 is added to the height of the channels, as first is for
* start of list offset, and the second is as a correction for the scrollers.
*/
- int height = ((items * NLACHANNEL_STEP(snla)) + (NLACHANNEL_HEIGHT(snla) * 2));
- /* don't use totrect set, as the width stays the same
- * (NOTE: this is ok here, the configuration is pretty straightforward)
- */
- v2d->tot.ymin = (float)(-height);
+ int height = NLACHANNEL_TOT_HEIGHT(ac, items);
+ v2d->tot.ymin = -height;
+
/* need to do a view-sync here, so that the keys area doesn't jump around
* (it must copy this) */
UI_view2d_sync(NULL, ac->sa, v2d, V2D_LOCK_COPY);
@@ -842,30 +832,24 @@ void draw_nla_channel_list(const bContext *C, bAnimContext *ac, ARegion *ar)
/* draw channels */
{ /* first pass: just the standard GL-drawing for backdrop + text */
size_t channel_index = 0;
+ float ymax = NLACHANNEL_FIRST_TOP(ac);
- y = (float)(-NLACHANNEL_HEIGHT(snla));
-
- for (ale = anim_data.first; ale; ale = ale->next) {
- float yminc = (float)(y - NLACHANNEL_HEIGHT_HALF(snla));
- float ymaxc = (float)(y + NLACHANNEL_HEIGHT_HALF(snla));
+ for (ale = anim_data.first; ale;
+ ale = ale->next, ymax -= NLACHANNEL_STEP(snla), channel_index++) {
+ float ymin = ymax - NLACHANNEL_HEIGHT(snla);
/* check if visible */
- if (IN_RANGE(yminc, v2d->cur.ymin, v2d->cur.ymax) ||
- IN_RANGE(ymaxc, v2d->cur.ymin, v2d->cur.ymax)) {
+ if (IN_RANGE(ymin, v2d->cur.ymin, v2d->cur.ymax) ||
+ IN_RANGE(ymax, v2d->cur.ymin, v2d->cur.ymax)) {
/* draw all channels using standard channel-drawing API */
- ANIM_channel_draw(ac, ale, yminc, ymaxc, channel_index);
+ ANIM_channel_draw(ac, ale, ymin, ymax, channel_index);
}
-
- /* adjust y-position for next one */
- y -= NLACHANNEL_STEP(snla);
- channel_index++;
}
}
{ /* second pass: UI widgets */
uiBlock *block = UI_block_begin(C, ar, __func__, UI_EMBOSS);
size_t channel_index = 0;
-
- y = (float)(-NLACHANNEL_HEIGHT(snla));
+ float ymax = NLACHANNEL_FIRST_TOP(ac);
/* set blending again, as may not be set in previous step */
GPU_blend_set_func_separate(
@@ -873,22 +857,18 @@ void draw_nla_channel_list(const bContext *C, bAnimContext *ac, ARegion *ar)
GPU_blend(true);
/* loop through channels, and set up drawing depending on their type */
- for (ale = anim_data.first; ale; ale = ale->next) {
- const float yminc = (float)(y - NLACHANNEL_HEIGHT_HALF(snla));
- const float ymaxc = (float)(y + NLACHANNEL_HEIGHT_HALF(snla));
+ for (ale = anim_data.first; ale;
+ ale = ale->next, ymax -= NLACHANNEL_STEP(snla), channel_index++) {
+ float ymin = ymax - NLACHANNEL_HEIGHT(snla);
/* check if visible */
- if (IN_RANGE(yminc, v2d->cur.ymin, v2d->cur.ymax) ||
- IN_RANGE(ymaxc, v2d->cur.ymin, v2d->cur.ymax)) {
+ if (IN_RANGE(ymin, v2d->cur.ymin, v2d->cur.ymax) ||
+ IN_RANGE(ymax, v2d->cur.ymin, v2d->cur.ymax)) {
/* draw all channels using standard channel-drawing API */
rctf channel_rect;
- BLI_rctf_init(&channel_rect, 0, v2d->cur.xmax, yminc, ymaxc);
+ BLI_rctf_init(&channel_rect, 0, v2d->cur.xmax, ymin, ymax);
ANIM_channel_draw_widgets(C, ac, ale, block, &channel_rect, channel_index);
}
-
- /* adjust y-position for next one */
- y -= NLACHANNEL_STEP(snla);
- channel_index++;
}
UI_block_end(C, block);
diff --git a/source/blender/editors/space_nla/nla_edit.c b/source/blender/editors/space_nla/nla_edit.c
index 0446235a776..acb3d913114 100644
--- a/source/blender/editors/space_nla/nla_edit.c
+++ b/source/blender/editors/space_nla/nla_edit.c
@@ -421,27 +421,25 @@ static bool nla_channels_get_selected_extents(bAnimContext *ac, float *min, floa
int filter;
SpaceNla *snla = (SpaceNla *)ac->sl;
- const float half_height = NLACHANNEL_HEIGHT_HALF(snla);
/* NOTE: not bool, since we want prioritise individual channels over expanders */
short found = 0;
- float y;
/* get all items - we need to do it this way */
filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE | ANIMFILTER_LIST_CHANNELS);
ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype);
/* loop through all channels, finding the first one that's selected */
- y = (float)NLACHANNEL_FIRST;
+ float ymax = NLACHANNEL_FIRST_TOP(ac);
- for (ale = anim_data.first; ale; ale = ale->next) {
+ for (ale = anim_data.first; ale; ale = ale->next, ymax -= NLACHANNEL_STEP(snla)) {
const bAnimChannelType *acf = ANIM_channel_get_typeinfo(ale);
/* must be selected... */
if (acf && acf->has_setting(ac, ale, ACHANNEL_SETTING_SELECT) &&
ANIM_channel_setting_get(ac, ale, ACHANNEL_SETTING_SELECT)) {
/* update best estimate */
- *min = (float)(y - half_height);
- *max = (float)(y + half_height);
+ *min = ymax - NLACHANNEL_HEIGHT(snla);
+ *max = ymax;
/* is this high enough priority yet? */
found = acf->channel_role;
@@ -453,9 +451,6 @@ static bool nla_channels_get_selected_extents(bAnimContext *ac, float *min, floa
break;
}
}
-
- /* adjust y-position for next one */
- y -= NLACHANNEL_STEP(snla);
}
/* free all temp data */
@@ -2451,6 +2446,7 @@ void NLA_OT_fmodifier_add(wmOperatorType *ot)
/* id-props */
ot->prop = RNA_def_enum(ot->srna, "type", rna_enum_fmodifier_type_items, 0, "Type", "");
+ RNA_def_property_translation_context(ot->prop, BLT_I18NCONTEXT_ID_ACTION);
RNA_def_enum_funcs(ot->prop, nla_fmodifier_itemf);
RNA_def_boolean(ot->srna,
diff --git a/source/blender/editors/space_nla/nla_select.c b/source/blender/editors/space_nla/nla_select.c
index 5c9e48f3d5d..0de9acfec25 100644
--- a/source/blender/editors/space_nla/nla_select.c
+++ b/source/blender/editors/space_nla/nla_select.c
@@ -47,6 +47,7 @@
#include "WM_types.h"
#include "UI_view2d.h"
+#include "UI_interface.h"
#include "nla_intern.h" // own include
@@ -541,15 +542,8 @@ static void mouse_nla_strips(
/* use View2D to determine the index of the channel
* (i.e a row in the list) where keyframe was */
UI_view2d_region_to_view(v2d, mval[0], mval[1], &x, &y);
- UI_view2d_listview_view_to_cell(v2d,
- 0,
- NLACHANNEL_STEP(snla),
- 0,
- (float)NLACHANNEL_HEIGHT_HALF(snla),
- x,
- y,
- NULL,
- &channel_index);
+ UI_view2d_listview_view_to_cell(
+ 0, NLACHANNEL_STEP(snla), 0, NLACHANNEL_FIRST_TOP(ac), x, y, NULL, &channel_index);
/* x-range to check is +/- 7 (in screen/region-space) on either side of mouse click
* (that is the size of keyframe icons, so user should be expecting similar tolerances)
diff --git a/source/blender/editors/space_nla/space_nla.c b/source/blender/editors/space_nla/space_nla.c
index b054f550c6c..4b7dfe5d653 100644
--- a/source/blender/editors/space_nla/space_nla.c
+++ b/source/blender/editors/space_nla/space_nla.c
@@ -40,6 +40,7 @@
#include "ED_anim_api.h"
#include "ED_markers.h"
#include "ED_screen.h"
+#include "ED_time_scrub_ui.h"
#include "WM_api.h"
#include "WM_types.h"
@@ -47,6 +48,7 @@
#include "RNA_access.h"
+#include "UI_interface.h"
#include "UI_resources.h"
#include "UI_view2d.h"
@@ -69,6 +71,7 @@ static SpaceLink *nla_new(const ScrArea *sa, const Scene *scene)
/* set auto-snapping settings */
snla->autosnap = SACTSNAP_FRAME;
+ snla->flag = SNLA_SHOW_MARKER_LINES;
/* header */
ar = MEM_callocN(sizeof(ARegion), "header for nla");
@@ -116,7 +119,7 @@ static SpaceLink *nla_new(const ScrArea *sa, const Scene *scene)
ar->v2d.minzoom = 0.01f;
ar->v2d.maxzoom = 50;
- ar->v2d.scroll = (V2D_SCROLL_BOTTOM | V2D_SCROLL_SCALE_HORIZONTAL);
+ ar->v2d.scroll = (V2D_SCROLL_BOTTOM | V2D_SCROLL_HORIZONTAL_HANDLES);
ar->v2d.scroll |= (V2D_SCROLL_RIGHT);
ar->v2d.keepzoom = V2D_LOCKZOOM_Y;
ar->v2d.keepofs = V2D_KEEPOFS_Y;
@@ -201,6 +204,9 @@ static void nla_channel_region_draw(const bContext *C, ARegion *ar)
draw_nla_channel_list(C, &ac, ar);
}
+ /* channel filter next to scrubbing area */
+ ED_channel_search_draw(C, ar, ac.ads);
+
/* reset view matrix */
UI_view2d_view_restore(C);
@@ -284,20 +290,12 @@ 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);
+
/* scrollers */
scrollers = UI_view2d_scrollers_calc(v2d, NULL);
UI_view2d_scrollers_draw(v2d, scrollers);
UI_view2d_scrollers_free(scrollers);
-
- /* frame numbers */
- UI_view2d_draw_scale_x__discrete_frames_or_seconds(
- ar, v2d, &v2d->hor, scene, snla->flag & SNLA_DRAWTIME);
-
- /* draw current frame number-indicator on top of scrollers */
- if ((snla->flag & SNLA_NODRAWCFRANUM) == 0) {
- UI_view2d_view_orthoSpecial(ar, v2d, 1);
- ANIM_draw_cfra_number(C, v2d, cfra_flag);
- }
}
/* add handlers, stuff you only do once or on area/region changes */
@@ -614,7 +612,7 @@ void ED_spacetype_nla(void)
art->draw = nla_main_region_draw;
art->listener = nla_main_region_listener;
art->message_subscribe = nla_main_region_message_subscribe;
- art->keymapflag = ED_KEYMAP_VIEW2D | ED_KEYMAP_MARKERS | ED_KEYMAP_ANIMATION | ED_KEYMAP_FRAMES;
+ art->keymapflag = ED_KEYMAP_VIEW2D | ED_KEYMAP_ANIMATION | ED_KEYMAP_FRAMES;
BLI_addhead(&st->regiontypes, art);
@@ -645,7 +643,7 @@ void ED_spacetype_nla(void)
/* regions: UI buttons */
art = MEM_callocN(sizeof(ARegionType), "spacetype nla region");
art->regionid = RGN_TYPE_UI;
- art->prefsizex = 200;
+ art->prefsizex = UI_SIDEBAR_PANEL_WIDTH;
art->keymapflag = ED_KEYMAP_UI;
art->listener = nla_region_listener;
art->init = nla_buttons_region_init;
diff --git a/source/blender/editors/space_node/drawnode.c b/source/blender/editors/space_node/drawnode.c
index 447fea8098c..e39e024e44a 100644
--- a/source/blender/editors/space_node/drawnode.c
+++ b/source/blender/editors/space_node/drawnode.c
@@ -708,6 +708,16 @@ static void node_buts_image_user(uiLayout *layout,
col = uiLayoutColumn(layout, false);
uiItemR(col, ptr, "layer", 0, NULL, ICON_NONE);
}
+
+ uiLayout *split = uiLayoutSplit(layout, 0.5f, true);
+ 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)
@@ -782,7 +792,6 @@ static void node_shader_buts_tex_image(uiLayout *layout, bContext *C, PointerRNA
NULL,
UI_TEMPLATE_ID_FILTER_ALL,
false);
- uiItemR(layout, ptr, "color_space", 0, "", ICON_NONE);
uiItemR(layout, ptr, "interpolation", 0, "", ICON_NONE);
uiItemR(layout, ptr, "projection", 0, "", ICON_NONE);
@@ -820,11 +829,10 @@ static void node_shader_buts_tex_environment(uiLayout *layout, bContext *C, Poin
UI_TEMPLATE_ID_FILTER_ALL,
false);
- node_buts_image_user(layout, C, &iuserptr, &imaptr, &iuserptr, false);
-
- uiItemR(layout, ptr, "color_space", 0, "", ICON_NONE);
uiItemR(layout, ptr, "interpolation", 0, "", ICON_NONE);
uiItemR(layout, ptr, "projection", 0, "", ICON_NONE);
+
+ node_buts_image_user(layout, C, &iuserptr, &imaptr, &iuserptr, false);
}
static void node_shader_buts_tex_environment_ex(uiLayout *layout, bContext *C, PointerRNA *ptr)
@@ -875,7 +883,6 @@ static void node_shader_buts_tex_environment_ex(uiLayout *layout, bContext *C, P
uiTemplateImageInfo(layout, C, ima, iuserptr.data);
}
- uiItemR(layout, ptr, "color_space", 0, IFACE_("Color Space"), ICON_NONE);
uiItemR(layout, ptr, "interpolation", 0, IFACE_("Interpolation"), ICON_NONE);
uiItemR(layout, ptr, "projection", 0, IFACE_("Projection"), ICON_NONE);
}
diff --git a/source/blender/editors/space_node/node_add.c b/source/blender/editors/space_node/node_add.c
index 714ed707e18..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(&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_edit.c b/source/blender/editors/space_node/node_edit.c
index 3e73cc52c52..fb34d9dc459 100644
--- a/source/blender/editors/space_node/node_edit.c
+++ b/source/blender/editors/space_node/node_edit.c
@@ -453,13 +453,8 @@ void ED_node_shader_default(const bContext *C, ID *id)
output_type = SH_NODE_OUTPUT_LIGHT;
shader_type = SH_NODE_EMISSION;
- copy_v3_v3(color, &la->r);
- if (la->type == LA_LOCAL || la->type == LA_SPOT || la->type == LA_AREA) {
- strength = 100.0f;
- }
- else {
- strength = 1.0f;
- }
+ copy_v3_fl3(color, 1.0f, 1.0f, 1.0f);
+ strength = 1.0f;
break;
}
default:
diff --git a/source/blender/editors/space_node/node_select.c b/source/blender/editors/space_node/node_select.c
index b52d1d3b78f..a8331c26ce6 100644
--- a/source/blender/editors/space_node/node_select.c
+++ b/source/blender/editors/space_node/node_select.c
@@ -429,19 +429,24 @@ void node_select_single(bContext *C, bNode *node)
WM_event_add_notifier(C, NC_NODE | NA_SELECTED, NULL);
}
-static int node_mouse_select(Main *bmain,
- SpaceNode *snode,
- ARegion *ar,
+static int node_mouse_select(bContext *C,
const int mval[2],
const bool extend,
const bool socket_select,
- const bool deselect_all)
+ const bool deselect_all,
+ const bool wait_to_deselect_others)
{
+ Main *bmain = CTX_data_main(C);
+ SpaceNode *snode = CTX_wm_space_node(C);
+ ARegion *ar = CTX_wm_region(C);
bNode *node, *tnode;
bNodeSocket *sock = NULL;
bNodeSocket *tsock;
float cursor[2];
- bool selected = false;
+ int ret_value = OPERATOR_CANCELLED;
+
+ /* Waiting to deselect others is only allowed for basic selection. */
+ BLI_assert(!(extend || socket_select) || !wait_to_deselect_others);
/* get mouse coordinates in view2d space */
UI_view2d_region_to_view(&ar->v2d, mval[0], mval[1], &cursor[0], &cursor[1]);
@@ -449,89 +454,114 @@ static int node_mouse_select(Main *bmain,
/* first do socket selection, these generally overlap with nodes. */
if (socket_select) {
if (node_find_indicated_socket(snode, &node, &sock, cursor, SOCK_IN)) {
- node_socket_toggle(node, sock, 1);
- selected = true;
+ /* NOTE: SOCK_IN does not take into account the extend case...
+ * This feature is not really used anyway currently? */
+ node_socket_toggle(node, sock, true);
+ ret_value = OPERATOR_FINISHED;
}
else if (node_find_indicated_socket(snode, &node, &sock, cursor, SOCK_OUT)) {
if (sock->flag & SELECT) {
if (extend) {
- node_socket_deselect(node, sock, 1);
+ node_socket_deselect(node, sock, true);
}
else {
- selected = true;
+ ret_value = OPERATOR_FINISHED;
}
}
else {
- /* only allow one selected output per node, for sensible linking.
- * allows selecting outputs from different nodes though. */
+ /* Only allow one selected output per node, for sensible linking.
+ * Allow selecting outputs from different nodes though, if extend is true. */
if (node) {
for (tsock = node->outputs.first; tsock; tsock = tsock->next) {
- node_socket_deselect(node, tsock, 1);
+ if (tsock == sock) {
+ continue;
+ }
+ node_socket_deselect(node, tsock, true);
}
}
- if (extend) {
- /* only allow one selected output per node, for sensible linking.
- * allows selecting outputs from different nodes though. */
- for (tsock = node->outputs.first; tsock; tsock = tsock->next) {
- if (tsock != sock) {
- node_socket_deselect(node, tsock, 1);
+ if (!extend) {
+ for (tnode = snode->edittree->nodes.first; tnode; tnode = tnode->next) {
+ if (tnode == node) {
+ continue;
+ }
+ for (tsock = tnode->outputs.first; tsock; tsock = tsock->next) {
+ node_socket_deselect(tnode, tsock, true);
}
}
}
node_socket_select(node, sock);
- selected = true;
+ ret_value = OPERATOR_FINISHED;
}
}
}
- if (!sock) {
- if (extend) {
- /* find the closest visible node */
- node = node_under_mouse_select(snode->edittree, cursor[0], cursor[1]);
+ /* 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 (node) {
- if ((node->flag & SELECT) && (node->flag & NODE_ACTIVE) == 0) {
- /* if node is selected but not active make it active */
- ED_node_set_active(bmain, snode->edittree, node);
- }
- else {
+ if (sock == NULL) {
+ /* find the closest visible node */
+ node = node_under_mouse_select(snode->edittree, (int)cursor[0], (int)cursor[1]);
+
+ if (extend) {
+ if (node != NULL) {
+ /* If node is selected but not active, we want to make it active,
+ * but not toggle (deselect) it. */
+ if (!((node->flag & SELECT) && (node->flag & NODE_ACTIVE) == 0)) {
node_toggle(node);
- ED_node_set_active(bmain, snode->edittree, node);
}
- selected = true;
+ ret_value = OPERATOR_FINISHED;
}
}
- else {
- /* find the closest visible node */
- node = node_under_mouse_select(snode->edittree, cursor[0], cursor[1]);
+ else if (deselect_all && node == NULL) {
+ /* Deselect in empty space. */
+ for (tnode = snode->edittree->nodes.first; tnode; tnode = tnode->next) {
+ nodeSetSelected(tnode, false);
+ }
+ ret_value = OPERATOR_FINISHED;
+ }
+ else if (node != NULL) {
+ /* When clicking on an already selected node, we want to wait to deselect
+ * others and allow the user to start moving the node without that. */
+ if (wait_to_deselect_others && (node->flag & SELECT)) {
+ ret_value = OPERATOR_RUNNING_MODAL;
+ }
+ else {
+ nodeSetSelected(node, true);
- if (node != NULL || deselect_all) {
for (tnode = snode->edittree->nodes.first; tnode; tnode = tnode->next) {
- nodeSetSelected(tnode, false);
- }
- selected = true;
- if (node != NULL) {
- nodeSetSelected(node, true);
- ED_node_set_active(bmain, snode->edittree, node);
+ if (tnode != node) {
+ nodeSetSelected(tnode, false);
+ }
}
+
+ ret_value = OPERATOR_FINISHED;
}
}
}
/* update node order */
- if (selected) {
+ if (ret_value != OPERATOR_CANCELLED) {
+ if (node != NULL && ret_value != OPERATOR_RUNNING_MODAL) {
+ ED_node_set_active(bmain, snode->edittree, node);
+ }
ED_node_set_active_viewer_key(snode);
ED_node_sort(snode->edittree);
+
+ WM_event_add_notifier(C, NC_NODE | NA_SELECTED, NULL);
}
- return selected;
+ return ret_value;
}
static int node_select_exec(bContext *C, wmOperator *op)
{
- Main *bmain = CTX_data_main(C);
- SpaceNode *snode = CTX_wm_space_node(C);
- ARegion *ar = CTX_wm_region(C);
int mval[2];
/* get settings from RNA properties for operator */
@@ -544,17 +574,70 @@ static int node_select_exec(bContext *C, wmOperator *op)
const bool deselect_all = RNA_boolean_get(op->ptr, "deselect_all");
/* perform the select */
- if (node_mouse_select(bmain, snode, ar, mval, extend, socket_select, deselect_all)) {
- /* send notifiers */
- WM_event_add_notifier(C, NC_NODE | NA_SELECTED, NULL);
+ const int ret_value = node_mouse_select(C, mval, extend, socket_select, deselect_all, false);
+
+ /* allow tweak event to work too */
+ return ret_value | OPERATOR_PASS_THROUGH;
+}
+
+static int node_select_modal(bContext *C, wmOperator *op, const wmEvent *event)
+{
+ const short init_event_type = (short)POINTER_AS_INT(op->customdata);
+
+ /* get settings from RNA properties for operator */
+ int mval[2];
+ mval[0] = RNA_int_get(op->ptr, "mouse_x");
+ mval[1] = RNA_int_get(op->ptr, "mouse_y");
+
+ const bool extend = RNA_boolean_get(op->ptr, "extend");
+ /* always do socket_select when extending selection. */
+ const bool socket_select = extend || RNA_boolean_get(op->ptr, "socket_select");
+ const bool deselect_all = RNA_boolean_get(op->ptr, "deselect_all");
- /* allow tweak event to work too */
- return OPERATOR_FINISHED | OPERATOR_PASS_THROUGH;
+ /* These cases are never modal. */
+ if (extend || socket_select) {
+ return node_select_exec(C, op);
}
- else {
- /* allow tweak event to work too */
- return OPERATOR_CANCELLED | OPERATOR_PASS_THROUGH;
+
+ if (init_event_type == 0) {
+ if (event->val == KM_PRESS) {
+ const int ret_value = node_mouse_select(C, mval, extend, socket_select, deselect_all, true);
+
+ op->customdata = POINTER_FROM_INT((int)event->type);
+ if (ret_value & OPERATOR_RUNNING_MODAL) {
+ WM_event_add_modal_handler(C, op);
+ }
+ return ret_value | OPERATOR_PASS_THROUGH;
+ }
+ else {
+ /* If we are in init phase, and cannot validate init of modal operations,
+ * just fall back to basic exec.
+ */
+ return node_select_exec(C, op);
+ }
}
+ else if (event->type == init_event_type && event->val == KM_RELEASE) {
+ const int ret_value = node_mouse_select(C, mval, extend, socket_select, deselect_all, false);
+ return ret_value | OPERATOR_PASS_THROUGH;
+ }
+ else if (ELEM(event->type, MOUSEMOVE, INBETWEEN_MOUSEMOVE)) {
+ const int dx = mval[0] - event->mval[0];
+ const int dy = mval[1] - event->mval[1];
+ const float tweak_threshold = U.tweak_threshold * U.dpi_fac;
+ /* If user moves mouse more than defined threshold, we consider select operator as
+ * finished. Otherwise, it is still running until we get an 'release' event. In any
+ * case, we pass through event, but select op is not finished yet. */
+ if (abs(dx) + abs(dy) > tweak_threshold) {
+ return OPERATOR_FINISHED | OPERATOR_PASS_THROUGH;
+ }
+ else {
+ /* Important not to return anything other than PASS_THROUGH here,
+ * otherwise it prevents underlying tweak detection code to work properly. */
+ return OPERATOR_PASS_THROUGH;
+ }
+ }
+
+ return OPERATOR_FINISHED | OPERATOR_PASS_THROUGH;
}
static int node_select_invoke(bContext *C, wmOperator *op, const wmEvent *event)
@@ -562,7 +645,9 @@ static int node_select_invoke(bContext *C, wmOperator *op, const wmEvent *event)
RNA_int_set(op->ptr, "mouse_x", event->mval[0]);
RNA_int_set(op->ptr, "mouse_y", event->mval[1]);
- return node_select_exec(C, op);
+ op->customdata = POINTER_FROM_INT(0);
+
+ return node_select_modal(C, op, event);
}
void NODE_OT_select(wmOperatorType *ot)
@@ -575,6 +660,7 @@ void NODE_OT_select(wmOperatorType *ot)
/* api callbacks */
ot->invoke = node_select_invoke;
ot->exec = node_select_exec;
+ ot->modal = node_select_modal;
ot->poll = ED_operator_node_active;
/* flags */
@@ -1186,7 +1272,7 @@ static uiBlock *node_find_menu(bContext *C, ARegion *ar, void *arg_op)
static int node_find_node_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event))
{
- UI_popup_block_invoke(C, node_find_menu, op);
+ UI_popup_block_invoke(C, node_find_menu, op, NULL);
return OPERATOR_CANCELLED;
}
diff --git a/source/blender/editors/space_node/space_node.c b/source/blender/editors/space_node/space_node.c
index 2152bb9847a..7183512a5bc 100644
--- a/source/blender/editors/space_node/space_node.c
+++ b/source/blender/editors/space_node/space_node.c
@@ -998,9 +998,10 @@ void ED_spacetype_node(void)
/* regions: listview/buttons */
art = MEM_callocN(sizeof(ARegionType), "spacetype node region");
art->regionid = RGN_TYPE_UI;
- art->prefsizex = 180; // XXX
+ art->prefsizex = UI_SIDEBAR_PANEL_WIDTH;
art->keymapflag = ED_KEYMAP_UI | ED_KEYMAP_FRAMES;
art->listener = node_region_listener;
+ art->message_subscribe = ED_area_do_mgs_subscribe_for_tool_ui;
art->init = node_buttons_region_init;
art->draw = node_buttons_region_draw;
BLI_addhead(&st->regiontypes, art);
diff --git a/source/blender/editors/space_outliner/outliner_collections.c b/source/blender/editors/space_outliner/outliner_collections.c
index 6da42ecb3c0..21e54a29fb9 100644
--- a/source/blender/editors/space_outliner/outliner_collections.c
+++ b/source/blender/editors/space_outliner/outliner_collections.c
@@ -855,7 +855,7 @@ static int collection_view_layer_exec(bContext *C, wmOperator *op)
void OUTLINER_OT_collection_exclude_set(wmOperatorType *ot)
{
/* identifiers */
- ot->name = "Set Exclude";
+ ot->name = "Disable from View Layer";
ot->idname = "OUTLINER_OT_collection_exclude_set";
ot->description = "Exclude collection from the active view layer";
@@ -870,7 +870,7 @@ void OUTLINER_OT_collection_exclude_set(wmOperatorType *ot)
void OUTLINER_OT_collection_exclude_clear(wmOperatorType *ot)
{
/* identifiers */
- ot->name = "Clear Exclude";
+ ot->name = "Enable in View Layer";
ot->idname = "OUTLINER_OT_collection_exclude_clear";
ot->description = "Include collection in the active view layer";
@@ -965,8 +965,8 @@ static int collection_isolate_exec(bContext *C, wmOperator *op)
LayerCollection *lc_master = view_layer->layer_collections.first;
for (LayerCollection *lc_iter = lc_master->layer_collections.first; lc_iter;
lc_iter = lc_iter->next) {
- lc_iter->flag |= LAYER_COLLECTION_RESTRICT_VIEW;
- layer_collection_flag_recursive_set(lc_iter, LAYER_COLLECTION_RESTRICT_VIEW);
+ lc_iter->flag |= LAYER_COLLECTION_HIDE;
+ layer_collection_flag_recursive_set(lc_iter, LAYER_COLLECTION_HIDE);
}
}
@@ -1023,12 +1023,12 @@ void OUTLINER_OT_collection_isolate(wmOperatorType *ot)
static bool collection_show_poll(bContext *C)
{
- return collections_view_layer_poll(C, true, LAYER_COLLECTION_RESTRICT_VIEW);
+ return collections_view_layer_poll(C, true, LAYER_COLLECTION_HIDE);
}
static bool collection_hide_poll(bContext *C)
{
- return collections_view_layer_poll(C, false, LAYER_COLLECTION_RESTRICT_VIEW);
+ return collections_view_layer_poll(C, false, LAYER_COLLECTION_HIDE);
}
static bool collection_inside_poll(bContext *C)
@@ -1163,12 +1163,12 @@ static bool collection_flag_poll(bContext *C, bool clear, int flag)
static bool collection_enable_poll(bContext *C)
{
- return collection_flag_poll(C, true, COLLECTION_RESTRICT_VIEW);
+ return collection_flag_poll(C, true, COLLECTION_RESTRICT_VIEWPORT);
}
static bool collection_disable_poll(bContext *C)
{
- return collection_flag_poll(C, false, COLLECTION_RESTRICT_VIEW);
+ return collection_flag_poll(C, false, COLLECTION_RESTRICT_VIEWPORT);
}
static bool collection_enable_render_poll(bContext *C)
@@ -1188,7 +1188,7 @@ static int collection_flag_exec(bContext *C, wmOperator *op)
SpaceOutliner *soops = CTX_wm_space_outliner(C);
const bool is_render = strstr(op->idname, "render");
const bool clear = strstr(op->idname, "show") || strstr(op->idname, "enable");
- int flag = is_render ? COLLECTION_RESTRICT_RENDER : COLLECTION_RESTRICT_VIEW;
+ int flag = is_render ? COLLECTION_RESTRICT_RENDER : COLLECTION_RESTRICT_VIEWPORT;
struct CollectionEditData data = {
.scene = scene,
.soops = soops,
@@ -1215,7 +1215,7 @@ static int collection_flag_exec(bContext *C, wmOperator *op)
/* Make sure (at least for this view layer) the collection is visible. */
if (clear && !is_render) {
- layer_collection->flag &= ~LAYER_COLLECTION_RESTRICT_VIEW;
+ layer_collection->flag &= ~LAYER_COLLECTION_HIDE;
}
}
BLI_gset_free(data.collections_to_edit, NULL);
@@ -1408,8 +1408,8 @@ static int outliner_unhide_all_exec(bContext *C, wmOperator *UNUSED(op))
LayerCollection *lc_master = view_layer->layer_collections.first;
for (LayerCollection *lc_iter = lc_master->layer_collections.first; lc_iter;
lc_iter = lc_iter->next) {
- lc_iter->flag &= ~LAYER_COLLECTION_RESTRICT_VIEW;
- layer_collection_flag_recursive_set(lc_iter, LAYER_COLLECTION_RESTRICT_VIEW);
+ lc_iter->flag &= ~LAYER_COLLECTION_HIDE;
+ layer_collection_flag_recursive_set(lc_iter, LAYER_COLLECTION_HIDE);
}
/* Unhide all objects. */
diff --git a/source/blender/editors/space_outliner/outliner_draw.c b/source/blender/editors/space_outliner/outliner_draw.c
index b556f58a02d..aed7af3911f 100644
--- a/source/blender/editors/space_outliner/outliner_draw.c
+++ b/source/blender/editors/space_outliner/outliner_draw.c
@@ -270,127 +270,413 @@ static void restrictbutton_id_user_toggle(bContext *UNUSED(C), void *poin, void
}
}
-static int base_pushed_state_cb(bContext *UNUSED(C), void *poin)
+static void outliner_object_set_flag_recursive_cb(bContext *C,
+ Base *base,
+ Object *ob,
+ const char *propname)
+{
+ Main *bmain = CTX_data_main(C);
+ wmWindow *win = CTX_wm_window(C);
+ Scene *scene = CTX_data_scene(C);
+ ViewLayer *view_layer = CTX_data_view_layer(C);
+ PointerRNA ptr;
+
+ bool extend = (win->eventstate->shift != 0);
+
+ if (!extend) {
+ return;
+ }
+
+ /* Create PointerRNA and PropertyRNA for either Object or Base. */
+ ID *id = ob ? &ob->id : &scene->id;
+ StructRNA *struct_rna = ob ? &RNA_Object : &RNA_ObjectBase;
+ void *data = ob ? (void *)ob : (void *)base;
+
+ RNA_pointer_create(id, struct_rna, data, &ptr);
+ PropertyRNA *base_or_object_prop = RNA_struct_type_find_property(struct_rna, propname);
+ const bool value = RNA_property_boolean_get(&ptr, base_or_object_prop);
+
+ Object *ob_parent = ob ? ob : base->object;
+
+ for (Object *ob_iter = bmain->objects.first; ob_iter; ob_iter = ob_iter->id.next) {
+ if (BKE_object_is_child_recursive(ob_parent, ob_iter)) {
+ if (ob) {
+ RNA_id_pointer_create(&ob_iter->id, &ptr);
+ DEG_id_tag_update(&ob_iter->id, ID_RECALC_COPY_ON_WRITE);
+ }
+ else {
+ Base *base_iter = BKE_view_layer_base_find(view_layer, ob_iter);
+ RNA_pointer_create(&scene->id, &RNA_ObjectBase, base_iter, &ptr);
+ }
+ RNA_property_boolean_set(&ptr, base_or_object_prop, value);
+ }
+ }
+
+ /* We don't call RNA_property_update() due to performance, so we batch update them. */
+ if (ob) {
+ BKE_main_collection_sync_remap(bmain);
+ DEG_relations_tag_update(bmain);
+ }
+ else {
+ BKE_layer_collection_sync(scene, view_layer);
+ DEG_id_tag_update(&scene->id, ID_RECALC_BASE_FLAGS);
+ }
+}
+
+/**
+ * Object properties.
+ * */
+static void outliner__object_set_flag_recursive_cb(bContext *C, void *poin, void *poin2)
+{
+ Object *ob = poin;
+ char *propname = poin2;
+ outliner_object_set_flag_recursive_cb(C, NULL, ob, propname);
+}
+
+/**
+ * Base properties.
+ * */
+static void outliner__base_set_flag_recursive_cb(bContext *C, void *poin, void *poin2)
{
Base *base = poin;
- Object *ob = base->object;
+ char *propname = poin2;
+ outliner_object_set_flag_recursive_cb(C, base, NULL, propname);
+}
- const bool is_visible = ((base->flag & BASE_HIDDEN) == 0) &&
- ((ob->restrictflag & OB_RESTRICT_VIEW) == 0);
- return !is_visible;
+/** Create either a RNA_LayerCollection or a RNA_Collection pointer. */
+static void outliner_layer_or_collection_pointer_create(Scene *scene,
+ LayerCollection *layer_collection,
+ Collection *collection,
+ PointerRNA *ptr)
+{
+ if (collection) {
+ RNA_id_pointer_create(&collection->id, ptr);
+ }
+ else {
+ RNA_pointer_create(&scene->id, &RNA_LayerCollection, layer_collection, ptr);
+ }
}
-static void hidebutton_base_flag_cb(bContext *C, void *poin, void *poin2)
+/** Create either a RNA_ObjectBase or a RNA_Object pointer. */
+static void outliner_base_or_object_pointer_create(ViewLayer *view_layer,
+ Collection *collection,
+ Object *ob,
+ PointerRNA *ptr)
{
- wmWindow *win = CTX_wm_window(C);
- Main *bmain = CTX_data_main(C);
- Scene *scene = CTX_data_scene(C);
- ViewLayer *view_layer = poin;
- Base *base = poin2;
- Object *ob = base->object;
- bool do_disable = (CTX_wm_window(C)->eventstate->alt != 0);
- bool do_isolate = (win->eventstate->ctrl != 0) && !do_disable;
- bool extend = (win->eventstate->shift != 0);
- bool depsgraph_changed = false;
- const bool is_linked = ID_IS_LINKED(ob);
+ if (collection) {
+ RNA_id_pointer_create(&ob->id, ptr);
+ }
+ else {
+ Base *base = BKE_view_layer_base_find(view_layer, ob);
+ RNA_pointer_create(&base->object->id, &RNA_ObjectBase, base, ptr);
+ }
+}
- if (do_disable) {
- if (!is_linked) {
- ob->restrictflag |= OB_RESTRICT_VIEW;
- depsgraph_changed = true;
- }
+/* Note: Collection is only valid when we want to change the collection data, otherwise we get it
+ * from layer collection. Layer collection is valid whenever we are looking at a view layer. */
+static void outliner_collection_set_flag_recursive(Scene *scene,
+ ViewLayer *view_layer,
+ LayerCollection *layer_collection,
+ Collection *collection,
+ PropertyRNA *layer_or_collection_prop,
+ PropertyRNA *base_or_object_prop,
+ const bool value)
+{
+ if (layer_collection && layer_collection->flag & LAYER_COLLECTION_EXCLUDE) {
+ return;
}
- else if (do_isolate) {
- depsgraph_changed = (!is_linked) && ((ob->restrictflag & OB_RESTRICT_VIEW) != 0);
+ PointerRNA ptr;
+ outliner_layer_or_collection_pointer_create(scene, layer_collection, collection, &ptr);
+ RNA_property_boolean_set(&ptr, layer_or_collection_prop, value);
- if (!extend) {
- /* Make only one base visible. */
- for (Base *other = view_layer->object_bases.first; other; other = other->next) {
- other->flag |= BASE_HIDDEN;
- }
+ /* Set the same flag for the nested objects as well. */
+ if (base_or_object_prop) {
+ /* Note: We can't use BKE_collection_object_cache_get()
+ * otherwise we would not take collection exclusion into account. */
+ for (CollectionObject *cob = layer_collection->collection->gobject.first; cob;
+ cob = cob->next) {
- base->flag &= ~BASE_HIDDEN;
- }
- else {
- /* Toggle visibility of one base. */
- base->flag ^= BASE_HIDDEN;
- }
+ outliner_base_or_object_pointer_create(view_layer, collection, cob->ob, &ptr);
+ RNA_property_boolean_set(&ptr, base_or_object_prop, value);
- if (!is_linked) {
- ob->restrictflag &= ~OB_RESTRICT_VIEW;
+ if (collection) {
+ DEG_id_tag_update(&cob->ob->id, ID_RECALC_COPY_ON_WRITE);
+ }
}
}
- else if (ob->restrictflag & OB_RESTRICT_VIEW) {
- if (!is_linked) {
- ob->restrictflag &= ~OB_RESTRICT_VIEW;
- base->flag &= ~BASE_HIDDEN;
+
+ /* Keep going recursively. */
+ ListBase *lb = (layer_collection ? &layer_collection->layer_collections : &collection->children);
+ for (Link *link = lb->first; link; link = link->next) {
+ LayerCollection *layer_collection_iter = layer_collection ? (LayerCollection *)link : NULL;
+ Collection *collection_iter = layer_collection ?
+ (collection ? layer_collection_iter->collection : NULL) :
+ ((CollectionChild *)link)->collection;
+ outliner_collection_set_flag_recursive(scene,
+ view_layer,
+ layer_collection_iter,
+ collection_iter,
+ layer_or_collection_prop,
+ base_or_object_prop,
+ value);
+ }
+
+ if (collection) {
+ DEG_id_tag_update(&collection->id, ID_RECALC_COPY_ON_WRITE);
+ }
+}
+
+/** Check if collection is already isolated.
+ *
+ * A collection is isolated if all its parents and children are "visible".
+ * All the other collections must be "invisible".
+ *
+ * Note: We could/should boost performance by iterating over the tree twice.
+ * First tagging all the children/parent collections, then getting their values and comparing.
+ * To run BKE_collection_has_collection() so many times is silly and slow.
+ */
+static bool outliner_collection_is_isolated(Scene *scene,
+ const LayerCollection *layer_collection_cmp,
+ const Collection *collection_cmp,
+ const bool value_cmp,
+ const PropertyRNA *layer_or_collection_prop,
+ LayerCollection *layer_collection,
+ Collection *collection)
+{
+ PointerRNA ptr;
+ outliner_layer_or_collection_pointer_create(scene, layer_collection, collection, &ptr);
+ const bool value = RNA_property_boolean_get(&ptr, (PropertyRNA *)layer_or_collection_prop);
+ Collection *collection_ensure = collection ? collection : layer_collection->collection;
+ const Collection *collection_ensure_cmp = collection_cmp ? collection_cmp :
+ layer_collection_cmp->collection;
+
+ if (collection_ensure->flag & COLLECTION_IS_MASTER) {
+ }
+ else if (collection_ensure == collection_ensure_cmp) {
+ }
+ else if (BKE_collection_has_collection(collection_ensure, (Collection *)collection_ensure_cmp) ||
+ BKE_collection_has_collection((Collection *)collection_ensure_cmp, collection_ensure)) {
+ /* This collection is either a parent or a child of the collection.
+ * We expect it to be set "visble" already. */
+ if (value != value_cmp) {
+ return false;
}
- depsgraph_changed = true;
}
else {
- base->flag ^= BASE_HIDDEN;
+ /* This collection is neither a parent nor a child of the collection.
+ * We expect it to be "invisble". */
+ if (value == value_cmp) {
+ return false;
+ }
}
- if (depsgraph_changed) {
- BKE_main_collection_sync_remap(bmain);
- DEG_id_tag_update(&ob->id, ID_RECALC_COPY_ON_WRITE);
- DEG_relations_tag_update(bmain);
- WM_main_add_notifier(NC_OBJECT | ND_DRAW, &ob->id);
+ /* Keep going recursively. */
+ ListBase *lb = (layer_collection ? &layer_collection->layer_collections : &collection->children);
+ for (Link *link = lb->first; link; link = link->next) {
+ LayerCollection *layer_collection_iter = layer_collection ? (LayerCollection *)link : NULL;
+ Collection *collection_iter = layer_collection ?
+ (collection ? layer_collection_iter->collection : NULL) :
+ ((CollectionChild *)link)->collection;
+ if (layer_collection_iter && layer_collection_iter->flag & LAYER_COLLECTION_EXCLUDE) {
+ continue;
+ }
+ if (!outliner_collection_is_isolated(scene,
+ layer_collection_cmp,
+ collection_cmp,
+ value_cmp,
+ layer_or_collection_prop,
+ layer_collection_iter,
+ collection_iter)) {
+ return false;
+ }
}
- if (!do_disable) {
- BKE_layer_collection_sync(scene, view_layer);
- DEG_id_tag_update(&scene->id, ID_RECALC_BASE_FLAGS);
- WM_event_add_notifier(C, NC_SCENE | ND_OB_SELECT, scene);
- }
+ return true;
}
-static int layer_collection_pushed_state_cb(bContext *UNUSED(C), void *poin)
+static void outliner_collection_isolate_flag(Scene *scene,
+ ViewLayer *view_layer,
+ LayerCollection *layer_collection,
+ Collection *collection,
+ PropertyRNA *layer_or_collection_prop,
+ const char *propname,
+ const bool value)
{
- LayerCollection *lc = poin;
- Collection *collection = lc->collection;
+ PointerRNA ptr;
+ const bool is_hide = strstr(propname, "hide_") != NULL;
+
+ LayerCollection *top_layer_collection = layer_collection ? view_layer->layer_collections.first :
+ NULL;
+ Collection *top_collection = collection ? scene->master_collection : NULL;
+
+ bool was_isolated = (value == is_hide);
+ was_isolated &= outliner_collection_is_isolated(scene,
+ layer_collection,
+ collection,
+ !is_hide,
+ layer_or_collection_prop,
+ top_layer_collection,
+ top_collection);
+
+ if (was_isolated) {
+ const bool default_value = RNA_property_boolean_get_default(NULL, layer_or_collection_prop);
+ /* Make every collection go back to its default "visibility" state. */
+ outliner_collection_set_flag_recursive(scene,
+ view_layer,
+ top_layer_collection,
+ top_collection,
+ layer_or_collection_prop,
+ NULL,
+ default_value);
+ return;
+ }
+
+ /* Make every collection "invisible". */
+ outliner_collection_set_flag_recursive(scene,
+ view_layer,
+ top_layer_collection,
+ top_collection,
+ layer_or_collection_prop,
+ NULL,
+ is_hide);
+
+ /* Make this collection and its children collections the only "visible". */
+ outliner_collection_set_flag_recursive(
+ scene, view_layer, layer_collection, collection, layer_or_collection_prop, NULL, !is_hide);
+
+ /* Make this collection direct parents also "visible". */
+ if (layer_collection) {
+ LayerCollection *lc_parent = layer_collection;
+ for (LayerCollection *lc_iter = top_layer_collection->layer_collections.first; lc_iter;
+ lc_iter = lc_iter->next) {
+ if (BKE_layer_collection_has_layer_collection(lc_iter, layer_collection)) {
+ lc_parent = lc_iter;
+ break;
+ }
+ }
- const bool is_visible = ((lc->flag & LAYER_COLLECTION_RESTRICT_VIEW) == 0) &&
- ((collection->flag & COLLECTION_RESTRICT_VIEW) == 0);
- return !is_visible;
+ while (lc_parent != layer_collection) {
+ outliner_layer_or_collection_pointer_create(
+ scene, lc_parent, collection ? lc_parent->collection : NULL, &ptr);
+ RNA_property_boolean_set(&ptr, layer_or_collection_prop, !is_hide);
+
+ for (LayerCollection *lc_iter = lc_parent->layer_collections.first; lc_iter;
+ lc_iter = lc_iter->next) {
+ if (BKE_layer_collection_has_layer_collection(lc_iter, layer_collection)) {
+ lc_parent = lc_iter;
+ break;
+ }
+ }
+ }
+ }
+ else {
+ CollectionParent *parent;
+ Collection *child = collection;
+ while ((parent = child->parents.first)) {
+ if (parent->collection->flag & COLLECTION_IS_MASTER) {
+ break;
+ }
+ RNA_id_pointer_create(&parent->collection->id, &ptr);
+ RNA_property_boolean_set(&ptr, layer_or_collection_prop, !is_hide);
+ child = parent->collection;
+ }
+ }
}
-static void hidebutton_layer_collection_flag_cb(bContext *C, void *poin, void *poin2)
+static void outliner_collection_set_flag_recursive_cb(bContext *C,
+ LayerCollection *layer_collection,
+ Collection *collection,
+ const char *propname)
{
Main *bmain = CTX_data_main(C);
wmWindow *win = CTX_wm_window(C);
Scene *scene = CTX_data_scene(C);
- ViewLayer *view_layer = poin;
- LayerCollection *lc = poin2;
- Collection *collection = lc->collection;
- bool do_disable = (win->eventstate->alt != 0);
- bool do_isolate = (win->eventstate->ctrl != 0) && !do_disable;
+ ViewLayer *view_layer = CTX_data_view_layer(C);
+ PointerRNA ptr;
+
+ bool do_isolate = (win->eventstate->ctrl != 0);
bool extend = (win->eventstate->shift != 0);
- bool depsgraph_changed = false;
- if (do_disable) {
- if (!ID_IS_LINKED(collection)) {
- collection->flag |= COLLECTION_RESTRICT_VIEW;
- depsgraph_changed = true;
- }
+ if (!ELEM(true, do_isolate, extend)) {
+ return;
}
- else if (do_isolate) {
- depsgraph_changed |= BKE_layer_collection_isolate(scene, view_layer, lc, extend);
+
+ /* Create PointerRNA and PropertyRNA for either Collection or LayerCollection. */
+ ID *id = collection ? &collection->id : &scene->id;
+ StructRNA *struct_rna = collection ? &RNA_Collection : &RNA_LayerCollection;
+ void *data = collection ? (void *)collection : (void *)layer_collection;
+
+ RNA_pointer_create(id, struct_rna, data, &ptr);
+ outliner_layer_or_collection_pointer_create(scene, layer_collection, collection, &ptr);
+ PropertyRNA *layer_or_collection_prop = RNA_struct_type_find_property(struct_rna, propname);
+ const bool value = RNA_property_boolean_get(&ptr, layer_or_collection_prop);
+
+ PropertyRNA *base_or_object_prop = NULL;
+ if (layer_collection != NULL) {
+ /* If we are toggling Layer collections we still want to change the properties of the base
+ * or the objects. If we have a matching property, toggle it as well, it can be NULL. */
+ struct_rna = collection ? &RNA_Object : &RNA_ObjectBase;
+ base_or_object_prop = RNA_struct_type_find_property(struct_rna, propname);
}
- else {
- bool make_visible = ((lc->flag & LAYER_COLLECTION_RESTRICT_VIEW) != 0) ||
- ((collection->flag & COLLECTION_RESTRICT_VIEW) != 0);
- depsgraph_changed |= BKE_layer_collection_set_visible(view_layer, lc, make_visible, extend);
+
+ if (extend) {
+ outliner_collection_set_flag_recursive(scene,
+ view_layer,
+ layer_collection,
+ collection,
+ layer_or_collection_prop,
+ base_or_object_prop,
+ value);
}
+ else {
+ outliner_collection_isolate_flag(scene,
+ view_layer,
+ layer_collection,
+ collection,
+ layer_or_collection_prop,
+ propname,
+ value);
+ }
+
+ /* We don't call RNA_property_update() due to performance, so we batch update them. */
+ BKE_main_collection_sync_remap(bmain);
+ DEG_relations_tag_update(bmain);
+}
- BKE_layer_collection_sync(scene, view_layer);
- DEG_id_tag_update(&scene->id, ID_RECALC_BASE_FLAGS);
+/**
+ * Layer collection properties called from the ViewLayer mode.
+ * Change the (non-excluded) collection children, and the objects nested to them all.
+ */
+static void view_layer__layer_collection_set_flag_recursive_cb(bContext *C,
+ void *poin,
+ void *poin2)
+{
+ LayerCollection *layer_collection = poin;
+ char *propname = poin2;
+ outliner_collection_set_flag_recursive_cb(C, layer_collection, NULL, propname);
+}
- if (depsgraph_changed) {
- BKE_main_collection_sync_remap(bmain);
- DEG_relations_tag_update(bmain);
- }
- WM_main_add_notifier(NC_SCENE | ND_LAYER_CONTENT, NULL);
+/**
+ * Collection properties called from the ViewLayer mode.
+ * Change the (non-excluded) collection children, and the objects nested to them all.
+ */
+static void view_layer__collection_set_flag_recursive_cb(bContext *C, void *poin, void *poin2)
+{
+ LayerCollection *layer_collection = poin;
+ char *propname = poin2;
+ outliner_collection_set_flag_recursive_cb(
+ C, layer_collection, layer_collection->collection, propname);
+}
+
+/**
+ * Collection properties called from the Scenes mode.
+ * Change the collection children but no objects.
+ */
+static void scenes__collection_set_flag_recursive_cb(bContext *C, void *poin, void *poin2)
+{
+ Collection *collection = poin;
+ char *propname = poin2;
+ outliner_collection_set_flag_recursive_cb(C, NULL, collection, propname);
}
static void namebutton_cb(bContext *C, void *tsep, char *oldname)
@@ -568,64 +854,197 @@ static void namebutton_cb(bContext *C, void *tsep, char *oldname)
}
}
+typedef struct RestrictProperties {
+ bool initialized;
+
+ PropertyRNA *object_hide_viewport, *object_hide_select, *object_hide_render;
+ PropertyRNA *base_hide_viewport;
+ PropertyRNA *collection_hide_viewport, *collection_hide_select, *collection_hide_render;
+ PropertyRNA *layer_collection_holdout, *layer_collection_indirect_only,
+ *layer_collection_hide_viewport;
+ PropertyRNA *modifier_show_viewport, *modifier_show_render;
+} RestrictProperties;
+
+/* We don't care about the value of the property
+ * but whether the property should be active or grayed out. */
+typedef struct RestrictPropertiesActive {
+ bool object_hide_viewport;
+ bool object_hide_select;
+ bool object_hide_render;
+ bool base_hide_viewport;
+ bool collection_hide_viewport;
+ bool collection_hide_select;
+ bool collection_hide_render;
+ bool layer_collection_holdout;
+ bool layer_collection_indirect_only;
+ bool layer_collection_hide_viewport;
+ bool modifier_show_viewport;
+ bool modifier_show_render;
+} RestrictPropertiesActive;
+
+static void outliner_restrict_properties_enable_collection_set(
+ PointerRNA *collection_ptr, RestrictProperties *props, RestrictPropertiesActive *props_active)
+{
+ if (props_active->collection_hide_render) {
+ props_active->collection_hide_render = !RNA_property_boolean_get(
+ collection_ptr, props->collection_hide_render);
+ if (!props_active->collection_hide_render) {
+ props_active->layer_collection_holdout = false;
+ props_active->layer_collection_indirect_only = false;
+ props_active->object_hide_render = false;
+ props_active->modifier_show_render = false;
+ }
+ }
+
+ if (props_active->collection_hide_viewport) {
+ props_active->collection_hide_viewport = !RNA_property_boolean_get(
+ collection_ptr, props->collection_hide_viewport);
+ if (!props_active->collection_hide_viewport) {
+ props_active->collection_hide_select = false;
+ props_active->object_hide_select = false;
+ props_active->layer_collection_hide_viewport = false;
+ props_active->object_hide_viewport = false;
+ props_active->base_hide_viewport = false;
+ props_active->modifier_show_viewport = false;
+ }
+ }
+
+ if (props_active->collection_hide_select) {
+ props_active->collection_hide_select = !RNA_property_boolean_get(
+ collection_ptr, props->collection_hide_select);
+ if (!props_active->collection_hide_select) {
+ props_active->object_hide_select = false;
+ }
+ }
+}
+
+static void outliner_restrict_properties_enable_layer_collection_set(
+ PointerRNA *layer_collection_ptr,
+ PointerRNA *collection_ptr,
+ RestrictProperties *props,
+ RestrictPropertiesActive *props_active)
+{
+ outliner_restrict_properties_enable_collection_set(collection_ptr, props, props_active);
+
+ if (props_active->layer_collection_holdout) {
+ props_active->layer_collection_holdout = RNA_property_boolean_get(
+ layer_collection_ptr, props->layer_collection_holdout);
+ }
+
+ if (props_active->layer_collection_indirect_only) {
+ props_active->layer_collection_indirect_only = RNA_property_boolean_get(
+ layer_collection_ptr, props->layer_collection_indirect_only);
+ }
+
+ if (props_active->layer_collection_hide_viewport) {
+ props_active->layer_collection_hide_viewport = !RNA_property_boolean_get(
+ layer_collection_ptr, props->layer_collection_hide_viewport);
+
+ if (!props_active->layer_collection_hide_viewport) {
+ props_active->base_hide_viewport = false;
+ props_active->collection_hide_select = false;
+ props_active->object_hide_select = false;
+ }
+ }
+}
+
static void outliner_draw_restrictbuts(uiBlock *block,
Scene *scene,
ViewLayer *view_layer,
ARegion *ar,
SpaceOutliner *soops,
- ListBase *lb)
+ ListBase *lb,
+ RestrictPropertiesActive props_active_parent)
{
/* Get RNA properties (once for speed). */
- static struct RestrictProperties {
- bool initialized;
-
- PropertyRNA *object_hide_viewport, *object_hide_select, *object_hide_render;
- PropertyRNA *collection_hide_viewport, *collection_hide_select, *collection_hide_render;
- PropertyRNA *modifier_show_viewport, *modifier_show_render;
- } props = {false};
-
+ static RestrictProperties props = {false};
if (!props.initialized) {
props.object_hide_viewport = RNA_struct_type_find_property(&RNA_Object, "hide_viewport");
props.object_hide_select = RNA_struct_type_find_property(&RNA_Object, "hide_select");
props.object_hide_render = RNA_struct_type_find_property(&RNA_Object, "hide_render");
- props.collection_hide_select = RNA_struct_type_find_property(&RNA_Collection, "hide_select");
+ props.base_hide_viewport = RNA_struct_type_find_property(&RNA_ObjectBase, "hide_viewport");
props.collection_hide_viewport = RNA_struct_type_find_property(&RNA_Collection,
"hide_viewport");
+ props.collection_hide_select = RNA_struct_type_find_property(&RNA_Collection, "hide_select");
props.collection_hide_render = RNA_struct_type_find_property(&RNA_Collection, "hide_render");
+ props.layer_collection_holdout = RNA_struct_type_find_property(&RNA_LayerCollection,
+ "holdout");
+ props.layer_collection_indirect_only = RNA_struct_type_find_property(&RNA_LayerCollection,
+ "indirect_only");
+ props.layer_collection_hide_viewport = RNA_struct_type_find_property(&RNA_LayerCollection,
+ "hide_viewport");
props.modifier_show_viewport = RNA_struct_type_find_property(&RNA_Modifier, "show_viewport");
props.modifier_show_render = RNA_struct_type_find_property(&RNA_Modifier, "show_render");
props.initialized = true;
}
+ struct {
+ int select;
+ int hide;
+ int viewport;
+ int render;
+ int indirect_only;
+ int holdout;
+ } restrict_offsets = {0};
+ int restrict_column_offset = 0;
+
+ /* This will determine the order of drawing from RIGHT to LEFT. */
+ if (soops->outlinevis == SO_VIEW_LAYER) {
+ if (soops->show_restrict_flags & SO_RESTRICT_INDIRECT_ONLY) {
+ restrict_offsets.indirect_only = (++restrict_column_offset) * UI_UNIT_X + V2D_SCROLL_WIDTH;
+ }
+ if (soops->show_restrict_flags & SO_RESTRICT_HOLDOUT) {
+ restrict_offsets.holdout = (++restrict_column_offset) * UI_UNIT_X + V2D_SCROLL_WIDTH;
+ }
+ }
+ if (soops->show_restrict_flags & SO_RESTRICT_RENDER) {
+ restrict_offsets.render = (++restrict_column_offset) * UI_UNIT_X + V2D_SCROLL_WIDTH;
+ }
+ if (soops->show_restrict_flags & SO_RESTRICT_VIEWPORT) {
+ restrict_offsets.viewport = (++restrict_column_offset) * UI_UNIT_X + V2D_SCROLL_WIDTH;
+ }
+ if (soops->show_restrict_flags & SO_RESTRICT_HIDE) {
+ restrict_offsets.hide = (++restrict_column_offset) * UI_UNIT_X + V2D_SCROLL_WIDTH;
+ }
+ if (soops->show_restrict_flags & SO_RESTRICT_SELECT) {
+ restrict_offsets.select = (++restrict_column_offset) * UI_UNIT_X + V2D_SCROLL_WIDTH;
+ }
+ BLI_assert((restrict_column_offset * UI_UNIT_X + V2D_SCROLL_WIDTH) ==
+ outliner_restrict_columns_width(soops));
+
/* Create buttons. */
uiBut *bt;
for (TreeElement *te = lb->first; te; te = te->next) {
TreeStoreElem *tselem = TREESTORE(te);
+ RestrictPropertiesActive props_active = props_active_parent;
+
if (te->ys + 2 * UI_UNIT_Y >= ar->v2d.cur.ymin && te->ys <= ar->v2d.cur.ymax) {
if (tselem->type == TSE_R_LAYER && (soops->outlinevis == SO_SCENES)) {
- /* View layer render toggle. */
- ViewLayer *layer = te->directdata;
+ if (soops->show_restrict_flags & SO_RESTRICT_RENDER) {
+ /* View layer render toggle. */
+ ViewLayer *layer = te->directdata;
- bt = uiDefIconButBitS(block,
- UI_BTYPE_ICON_TOGGLE_N,
- VIEW_LAYER_RENDER,
- 0,
- ICON_RESTRICT_RENDER_OFF,
- (int)(ar->v2d.cur.xmax - OL_TOG_RESTRICT_RENDERX),
- te->ys,
- UI_UNIT_X,
- UI_UNIT_Y,
- &layer->flag,
- 0,
- 0,
- 0,
- 0,
- TIP_("Use view layer for rendering"));
- UI_but_func_set(bt, restrictbutton_r_lay_cb, tselem->id, NULL);
- UI_but_flag_enable(bt, UI_BUT_DRAG_LOCK);
- UI_but_drawflag_enable(bt, UI_BUT_ICON_REVERSE);
+ bt = uiDefIconButBitS(block,
+ UI_BTYPE_ICON_TOGGLE_N,
+ VIEW_LAYER_RENDER,
+ 0,
+ ICON_RESTRICT_RENDER_OFF,
+ (int)(ar->v2d.cur.xmax - restrict_offsets.render),
+ te->ys,
+ UI_UNIT_X,
+ UI_UNIT_Y,
+ &layer->flag,
+ 0,
+ 0,
+ 0,
+ 0,
+ TIP_("Use view layer for rendering"));
+ UI_but_func_set(bt, restrictbutton_r_lay_cb, tselem->id, NULL);
+ UI_but_flag_enable(bt, UI_BUT_DRAG_LOCK);
+ UI_but_drawflag_enable(bt, UI_BUT_ICON_REVERSE);
+ }
}
else if ((tselem->type == 0 && te->idcode == ID_OB) &&
(te->flag & TE_CHILD_NOT_IN_COLLECTION)) {
@@ -634,40 +1053,71 @@ static void outliner_draw_restrictbuts(uiBlock *block,
else if (tselem->type == 0 && te->idcode == ID_OB) {
PointerRNA ptr;
Object *ob = (Object *)tselem->id;
- RNA_pointer_create(&ob->id, &RNA_Object, ob, &ptr);
- Base *base = BKE_view_layer_base_find(view_layer, ob);
-
- if (base) {
- int icon = ICON_RESTRICT_VIEW_ON;
- if ((ob->restrictflag & OB_RESTRICT_VIEW) == 0) {
- icon = (base->flag & BASE_HIDDEN) != 0 ? ICON_HIDE_ON : ICON_HIDE_OFF;
+ RNA_id_pointer_create(&ob->id, &ptr);
+
+ if (soops->show_restrict_flags & SO_RESTRICT_HIDE) {
+ Base *base = (te->directdata) ? (Base *)te->directdata :
+ BKE_view_layer_base_find(view_layer, ob);
+ if (base) {
+ PointerRNA base_ptr;
+ RNA_pointer_create(&ob->id, &RNA_ObjectBase, base, &base_ptr);
+ bt = uiDefIconButR_prop(block,
+ UI_BTYPE_ICON_TOGGLE,
+ 0,
+ 0,
+ (int)(ar->v2d.cur.xmax - restrict_offsets.hide),
+ te->ys,
+ UI_UNIT_X,
+ UI_UNIT_Y,
+ &base_ptr,
+ props.base_hide_viewport,
+ -1,
+ 0,
+ 0,
+ 0,
+ 0,
+ TIP_("Temporarly hide in viewport\n"
+ "* Shift to set children"));
+ UI_but_func_set(
+ bt, outliner__base_set_flag_recursive_cb, base, (void *)"hide_viewport");
+ UI_but_flag_enable(bt, UI_BUT_DRAG_LOCK);
+ if (!props_active.base_hide_viewport) {
+ UI_but_flag_enable(bt, UI_BUT_INACTIVE);
+ }
}
- bt = uiDefIconBut(block,
- UI_BTYPE_ICON_TOGGLE,
- 0,
- icon,
- (int)(ar->v2d.cur.xmax - OL_TOG_RESTRICT_VIEWX),
- te->ys,
- UI_UNIT_X,
- UI_UNIT_Y,
- NULL,
- 0,
- 0,
- 0,
- 0,
- TIP_("Hide object in viewport\n"
- "* Alt to disable for all viewports\n"
- "* Ctrl to isolate visibility"));
- UI_but_func_set(bt, hidebutton_base_flag_cb, view_layer, base);
- UI_but_func_pushed_state_set(bt, base_pushed_state_cb, base);
+ }
+
+ if (soops->show_restrict_flags & SO_RESTRICT_SELECT) {
+ bt = uiDefIconButR_prop(block,
+ UI_BTYPE_ICON_TOGGLE,
+ 0,
+ 0,
+ (int)(ar->v2d.cur.xmax - restrict_offsets.select),
+ te->ys,
+ UI_UNIT_X,
+ UI_UNIT_Y,
+ &ptr,
+ props.object_hide_select,
+ -1,
+ 0,
+ 0,
+ -1,
+ -1,
+ TIP_("Disable selection in viewport\n"
+ "* Shift to set children"));
+ UI_but_func_set(bt, outliner__object_set_flag_recursive_cb, ob, (char *)"hide_select");
UI_but_flag_enable(bt, UI_BUT_DRAG_LOCK);
+ if (!props_active.object_hide_select) {
+ UI_but_flag_enable(bt, UI_BUT_INACTIVE);
+ }
}
- else {
+
+ if (soops->show_restrict_flags & SO_RESTRICT_VIEWPORT) {
bt = uiDefIconButR_prop(block,
UI_BTYPE_ICON_TOGGLE,
0,
0,
- (int)(ar->v2d.cur.xmax - OL_TOG_RESTRICT_VIEWX),
+ (int)(ar->v2d.cur.xmax - restrict_offsets.viewport),
te->ys,
UI_UNIT_X,
UI_UNIT_Y,
@@ -678,256 +1128,352 @@ static void outliner_draw_restrictbuts(uiBlock *block,
0,
-1,
-1,
+ TIP_("Globally disable in viewports\n"
+ "* Shift to set children"));
+ UI_but_func_set(bt, outliner__object_set_flag_recursive_cb, ob, (void *)"hide_viewport");
+ UI_but_flag_enable(bt, UI_BUT_DRAG_LOCK);
+ if (!props_active.object_hide_viewport) {
+ UI_but_flag_enable(bt, UI_BUT_INACTIVE);
+ }
+ }
+
+ if (soops->show_restrict_flags & SO_RESTRICT_RENDER) {
+ bt = uiDefIconButR_prop(block,
+ UI_BTYPE_ICON_TOGGLE,
+ 0,
+ 0,
+ (int)(ar->v2d.cur.xmax - restrict_offsets.render),
+ te->ys,
+ UI_UNIT_X,
+ UI_UNIT_Y,
+ &ptr,
+ props.object_hide_render,
+ -1,
+ 0,
+ 0,
+ -1,
+ -1,
+ TIP_("Globally disable in renders\n"
+ "* Shift to set children"));
+ UI_but_func_set(bt, outliner__object_set_flag_recursive_cb, ob, (char *)"hide_render");
+ UI_but_flag_enable(bt, UI_BUT_DRAG_LOCK);
+ if (!props_active.object_hide_render) {
+ UI_but_flag_enable(bt, UI_BUT_INACTIVE);
+ }
+ }
+ }
+ else if (tselem->type == TSE_MODIFIER) {
+ ModifierData *md = (ModifierData *)te->directdata;
+
+ PointerRNA ptr;
+ RNA_pointer_create(tselem->id, &RNA_Modifier, md, &ptr);
+
+ if (soops->show_restrict_flags & SO_RESTRICT_VIEWPORT) {
+ bt = uiDefIconButR_prop(block,
+ UI_BTYPE_ICON_TOGGLE,
+ 0,
+ 0,
+ (int)(ar->v2d.cur.xmax - restrict_offsets.viewport),
+ te->ys,
+ UI_UNIT_X,
+ UI_UNIT_Y,
+ &ptr,
+ props.modifier_show_viewport,
+ -1,
+ 0,
+ 0,
+ -1,
+ -1,
+ NULL);
+ UI_but_flag_enable(bt, UI_BUT_DRAG_LOCK);
+ if (!props_active.modifier_show_viewport) {
+ UI_but_flag_enable(bt, UI_BUT_INACTIVE);
+ }
+ }
+
+ if (soops->show_restrict_flags & SO_RESTRICT_RENDER) {
+ bt = uiDefIconButR_prop(block,
+ UI_BTYPE_ICON_TOGGLE,
+ 0,
+ 0,
+ (int)(ar->v2d.cur.xmax - restrict_offsets.render),
+ te->ys,
+ UI_UNIT_X,
+ UI_UNIT_Y,
+ &ptr,
+ props.modifier_show_render,
+ -1,
+ 0,
+ 0,
+ -1,
+ -1,
NULL);
UI_but_flag_enable(bt, UI_BUT_DRAG_LOCK);
+ if (!props_active.modifier_show_render) {
+ UI_but_flag_enable(bt, UI_BUT_INACTIVE);
+ }
}
+ }
+ else if (tselem->type == TSE_POSE_CHANNEL) {
+ bPoseChannel *pchan = (bPoseChannel *)te->directdata;
+ Bone *bone = pchan->bone;
+ Object *ob = (Object *)tselem->id;
- bt = uiDefIconButR_prop(block,
+ if (soops->show_restrict_flags & SO_RESTRICT_VIEWPORT) {
+ bt = uiDefIconButBitI(block,
UI_BTYPE_ICON_TOGGLE,
+ BONE_HIDDEN_P,
0,
- 0,
- (int)(ar->v2d.cur.xmax - OL_TOG_RESTRICT_SELECTX),
+ ICON_HIDE_OFF,
+ (int)(ar->v2d.cur.xmax - restrict_offsets.viewport),
te->ys,
UI_UNIT_X,
UI_UNIT_Y,
- &ptr,
- props.object_hide_select,
- -1,
+ &(bone->flag),
+ 0,
0,
0,
- -1,
- -1,
- NULL);
- UI_but_flag_enable(bt, UI_BUT_DRAG_LOCK);
+ 0,
+ TIP_("Restrict visibility in the 3D View"));
+ UI_but_func_set(bt, restrictbutton_bone_visibility_cb, ob->data, bone);
+ UI_but_flag_enable(bt, UI_BUT_DRAG_LOCK);
+ UI_but_drawflag_enable(bt, UI_BUT_ICON_REVERSE);
+ }
- bt = uiDefIconButR_prop(block,
+ if (soops->show_restrict_flags & SO_RESTRICT_SELECT) {
+ bt = uiDefIconButBitI(block,
UI_BTYPE_ICON_TOGGLE,
+ BONE_UNSELECTABLE,
0,
- 0,
- (int)(ar->v2d.cur.xmax - OL_TOG_RESTRICT_RENDERX),
+ ICON_RESTRICT_SELECT_OFF,
+ (int)(ar->v2d.cur.xmax - restrict_offsets.select),
te->ys,
UI_UNIT_X,
UI_UNIT_Y,
- &ptr,
- props.object_hide_render,
- -1,
+ &(bone->flag),
+ 0,
+ 0,
0,
0,
- -1,
- -1,
- NULL);
- UI_but_flag_enable(bt, UI_BUT_DRAG_LOCK);
+ TIP_("Restrict selection in the 3D View"));
+ UI_but_func_set(bt, restrictbutton_bone_select_cb, ob->data, bone);
+ UI_but_flag_enable(bt, UI_BUT_DRAG_LOCK);
+ UI_but_drawflag_enable(bt, UI_BUT_ICON_REVERSE);
+ }
}
- else if (tselem->type == TSE_MODIFIER) {
- ModifierData *md = (ModifierData *)te->directdata;
-
- PointerRNA ptr;
- RNA_pointer_create(tselem->id, &RNA_Modifier, md, &ptr);
+ else if (tselem->type == TSE_EBONE) {
+ EditBone *ebone = (EditBone *)te->directdata;
- bt = uiDefIconButR_prop(block,
+ if (soops->show_restrict_flags & SO_RESTRICT_VIEWPORT) {
+ bt = uiDefIconButBitI(block,
UI_BTYPE_ICON_TOGGLE,
+ BONE_HIDDEN_A,
0,
- 0,
- (int)(ar->v2d.cur.xmax - OL_TOG_RESTRICT_VIEWX),
+ ICON_RESTRICT_VIEW_OFF,
+ (int)(ar->v2d.cur.xmax - restrict_offsets.viewport),
te->ys,
UI_UNIT_X,
UI_UNIT_Y,
- &ptr,
- props.modifier_show_viewport,
- -1,
+ &(ebone->flag),
+ 0,
+ 0,
0,
0,
- -1,
- -1,
- NULL);
- UI_but_flag_enable(bt, UI_BUT_DRAG_LOCK);
+ TIP_("Restrict visibility in the 3D View"));
+ UI_but_func_set(bt, restrictbutton_ebone_visibility_cb, NULL, ebone);
+ UI_but_flag_enable(bt, UI_BUT_DRAG_LOCK);
+ UI_but_drawflag_enable(bt, UI_BUT_ICON_REVERSE);
+ }
- bt = uiDefIconButR_prop(block,
+ if (soops->show_restrict_flags & SO_RESTRICT_SELECT) {
+ bt = uiDefIconButBitI(block,
UI_BTYPE_ICON_TOGGLE,
+ BONE_UNSELECTABLE,
0,
- 0,
- (int)(ar->v2d.cur.xmax - OL_TOG_RESTRICT_RENDERX),
+ ICON_RESTRICT_SELECT_OFF,
+ (int)(ar->v2d.cur.xmax - restrict_offsets.select),
te->ys,
UI_UNIT_X,
UI_UNIT_Y,
- &ptr,
- props.modifier_show_render,
- -1,
+ &(ebone->flag),
0,
0,
- -1,
- -1,
- NULL);
- UI_but_flag_enable(bt, UI_BUT_DRAG_LOCK);
- }
- else if (tselem->type == TSE_POSE_CHANNEL) {
- bPoseChannel *pchan = (bPoseChannel *)te->directdata;
- Bone *bone = pchan->bone;
- Object *ob = (Object *)tselem->id;
-
- bt = uiDefIconButBitI(block,
- UI_BTYPE_ICON_TOGGLE,
- BONE_HIDDEN_P,
- 0,
- ICON_HIDE_OFF,
- (int)(ar->v2d.cur.xmax - OL_TOG_RESTRICT_VIEWX),
- te->ys,
- UI_UNIT_X,
- UI_UNIT_Y,
- &(bone->flag),
- 0,
- 0,
- 0,
- 0,
- TIP_("Restrict/Allow visibility in the 3D View"));
- UI_but_func_set(bt, restrictbutton_bone_visibility_cb, ob->data, bone);
- UI_but_flag_enable(bt, UI_BUT_DRAG_LOCK);
- UI_but_drawflag_enable(bt, UI_BUT_ICON_REVERSE);
-
- bt = uiDefIconButBitI(block,
- UI_BTYPE_ICON_TOGGLE,
- BONE_UNSELECTABLE,
- 0,
- ICON_RESTRICT_SELECT_OFF,
- (int)(ar->v2d.cur.xmax - OL_TOG_RESTRICT_SELECTX),
- te->ys,
- UI_UNIT_X,
- UI_UNIT_Y,
- &(bone->flag),
- 0,
- 0,
- 0,
- 0,
- TIP_("Restrict/Allow selection in the 3D View"));
- UI_but_func_set(bt, restrictbutton_bone_select_cb, ob->data, bone);
- UI_but_flag_enable(bt, UI_BUT_DRAG_LOCK);
- UI_but_drawflag_enable(bt, UI_BUT_ICON_REVERSE);
- }
- else if (tselem->type == TSE_EBONE) {
- EditBone *ebone = (EditBone *)te->directdata;
-
- bt = uiDefIconButBitI(block,
- UI_BTYPE_ICON_TOGGLE,
- BONE_HIDDEN_A,
- 0,
- ICON_RESTRICT_VIEW_OFF,
- (int)(ar->v2d.cur.xmax - OL_TOG_RESTRICT_VIEWX),
- te->ys,
- UI_UNIT_X,
- UI_UNIT_Y,
- &(ebone->flag),
- 0,
- 0,
- 0,
- 0,
- TIP_("Restrict/Allow visibility in the 3D View"));
- UI_but_func_set(bt, restrictbutton_ebone_visibility_cb, NULL, ebone);
- UI_but_flag_enable(bt, UI_BUT_DRAG_LOCK);
- UI_but_drawflag_enable(bt, UI_BUT_ICON_REVERSE);
-
- bt = uiDefIconButBitI(block,
- UI_BTYPE_ICON_TOGGLE,
- BONE_UNSELECTABLE,
- 0,
- ICON_RESTRICT_SELECT_OFF,
- (int)(ar->v2d.cur.xmax - OL_TOG_RESTRICT_SELECTX),
- te->ys,
- UI_UNIT_X,
- UI_UNIT_Y,
- &(ebone->flag),
- 0,
- 0,
- 0,
- 0,
- TIP_("Restrict/Allow selection in the 3D View"));
- UI_but_func_set(bt, restrictbutton_ebone_select_cb, NULL, ebone);
- UI_but_flag_enable(bt, UI_BUT_DRAG_LOCK);
- UI_but_drawflag_enable(bt, UI_BUT_ICON_REVERSE);
+ 0,
+ 0,
+ TIP_("Restrict selection in the 3D View"));
+ UI_but_func_set(bt, restrictbutton_ebone_select_cb, NULL, ebone);
+ UI_but_flag_enable(bt, UI_BUT_DRAG_LOCK);
+ UI_but_drawflag_enable(bt, UI_BUT_ICON_REVERSE);
+ }
}
else if (tselem->type == TSE_GP_LAYER) {
ID *id = tselem->id;
bGPDlayer *gpl = (bGPDlayer *)te->directdata;
- bt = uiDefIconButBitS(block,
- UI_BTYPE_ICON_TOGGLE,
- GP_LAYER_HIDE,
- 0,
- ICON_HIDE_OFF,
- (int)(ar->v2d.cur.xmax - OL_TOG_RESTRICT_VIEWX),
- te->ys,
- UI_UNIT_X,
- UI_UNIT_Y,
- &gpl->flag,
- 0,
- 0,
- 0,
- 0,
- TIP_("Restrict/Allow visibility in the 3D View"));
- UI_but_func_set(bt, restrictbutton_gp_layer_flag_cb, id, gpl);
- UI_but_flag_enable(bt, UI_BUT_DRAG_LOCK);
- UI_but_drawflag_enable(bt, UI_BUT_ICON_REVERSE);
-
- bt = uiDefIconButBitS(
- block,
- UI_BTYPE_ICON_TOGGLE,
- GP_LAYER_LOCKED,
- 0,
- ICON_UNLOCKED,
- (int)(ar->v2d.cur.xmax - OL_TOG_RESTRICT_SELECTX),
- te->ys,
- UI_UNIT_X,
- UI_UNIT_Y,
- &gpl->flag,
- 0,
- 0,
- 0,
- 0,
- TIP_("Restrict/Allow editing of strokes and keyframes in this layer"));
- UI_but_func_set(bt, restrictbutton_gp_layer_flag_cb, id, gpl);
- UI_but_flag_enable(bt, UI_BUT_DRAG_LOCK);
+ if (soops->show_restrict_flags & SO_RESTRICT_VIEWPORT) {
+ bt = uiDefIconButBitS(block,
+ UI_BTYPE_ICON_TOGGLE,
+ GP_LAYER_HIDE,
+ 0,
+ ICON_HIDE_OFF,
+ (int)(ar->v2d.cur.xmax - restrict_offsets.viewport),
+ te->ys,
+ UI_UNIT_X,
+ UI_UNIT_Y,
+ &gpl->flag,
+ 0,
+ 0,
+ 0,
+ 0,
+ TIP_("Restrict visibility in the 3D View"));
+ UI_but_func_set(bt, restrictbutton_gp_layer_flag_cb, id, gpl);
+ UI_but_flag_enable(bt, UI_BUT_DRAG_LOCK);
+ UI_but_drawflag_enable(bt, UI_BUT_ICON_REVERSE);
+ }
+
+ if (soops->show_restrict_flags & SO_RESTRICT_SELECT) {
+ bt = uiDefIconButBitS(block,
+ UI_BTYPE_ICON_TOGGLE,
+ GP_LAYER_LOCKED,
+ 0,
+ ICON_UNLOCKED,
+ (int)(ar->v2d.cur.xmax - restrict_offsets.select),
+ te->ys,
+ UI_UNIT_X,
+ UI_UNIT_Y,
+ &gpl->flag,
+ 0,
+ 0,
+ 0,
+ 0,
+ TIP_("Restrict editing of strokes and keyframes in this layer"));
+ UI_but_func_set(bt, restrictbutton_gp_layer_flag_cb, id, gpl);
+ UI_but_flag_enable(bt, UI_BUT_DRAG_LOCK);
+ }
}
else if (outliner_is_collection_tree_element(te)) {
- LayerCollection *lc = (tselem->type == TSE_LAYER_COLLECTION) ? te->directdata : NULL;
+ LayerCollection *layer_collection = (tselem->type == TSE_LAYER_COLLECTION) ?
+ te->directdata :
+ NULL;
Collection *collection = outliner_collection_from_tree_element(te);
-
- if ((!lc || !(lc->flag & LAYER_COLLECTION_EXCLUDE)) &&
+ if ((!layer_collection || !(layer_collection->flag & LAYER_COLLECTION_EXCLUDE)) &&
!(collection->flag & COLLECTION_IS_MASTER)) {
+
PointerRNA collection_ptr;
+ PointerRNA layer_collection_ptr;
RNA_id_pointer_create(&collection->id, &collection_ptr);
+ if (layer_collection != NULL) {
+ RNA_pointer_create(
+ &scene->id, &RNA_LayerCollection, layer_collection, &layer_collection_ptr);
+ }
- if (lc != NULL) {
- int icon = ICON_RESTRICT_VIEW_ON;
- if ((collection->flag & COLLECTION_RESTRICT_VIEW) == 0) {
- icon = (lc->flag & LAYER_COLLECTION_RESTRICT_VIEW) != 0 ? ICON_HIDE_ON :
- ICON_HIDE_OFF;
- }
- bt = uiDefIconBut(block,
- UI_BTYPE_ICON_TOGGLE,
- 0,
- icon,
- (int)(ar->v2d.cur.xmax - OL_TOG_RESTRICT_VIEWX),
- te->ys,
- UI_UNIT_X,
- UI_UNIT_Y,
- NULL,
- 0,
- 0,
- 0,
- 0,
- TIP_("Hide collection in viewport\n"
- "* Alt to disable for all viewports\n"
- "* Ctrl to isolate visibility\n"
- "* Shift to hide inside objects and collections"));
- UI_but_func_set(bt, hidebutton_layer_collection_flag_cb, view_layer, lc);
- UI_but_func_pushed_state_set(bt, layer_collection_pushed_state_cb, lc);
- UI_but_flag_enable(bt, UI_BUT_DRAG_LOCK);
+ /* Update the restriction column values for the collection children. */
+ if (layer_collection) {
+ outliner_restrict_properties_enable_layer_collection_set(
+ &layer_collection_ptr, &collection_ptr, &props, &props_active);
}
else {
+ outliner_restrict_properties_enable_collection_set(
+ &collection_ptr, &props, &props_active);
+ }
+
+ if (layer_collection != NULL) {
+ if (soops->show_restrict_flags & SO_RESTRICT_HIDE) {
+ bt = uiDefIconButR_prop(block,
+ UI_BTYPE_ICON_TOGGLE,
+ 0,
+ 0,
+ (int)(ar->v2d.cur.xmax - restrict_offsets.hide),
+ te->ys,
+ UI_UNIT_X,
+ UI_UNIT_Y,
+ &layer_collection_ptr,
+ props.layer_collection_hide_viewport,
+ -1,
+ 0,
+ 0,
+ 0,
+ 0,
+ TIP_("Temporarily hide in viewport\n"
+ "* Ctrl to isolate collection\n"
+ "* Shift to set inside collections and objects"));
+ UI_but_func_set(bt,
+ view_layer__layer_collection_set_flag_recursive_cb,
+ layer_collection,
+ (char *)"hide_viewport");
+ UI_but_flag_enable(bt, UI_BUT_DRAG_LOCK);
+ if (!props_active.layer_collection_hide_viewport) {
+ UI_but_flag_enable(bt, UI_BUT_INACTIVE);
+ }
+ }
+
+ if (soops->show_restrict_flags & SO_RESTRICT_HOLDOUT) {
+ bt = uiDefIconButR_prop(block,
+ UI_BTYPE_ICON_TOGGLE,
+ 0,
+ 0,
+ (int)(ar->v2d.cur.xmax - restrict_offsets.holdout),
+ te->ys,
+ UI_UNIT_X,
+ UI_UNIT_Y,
+ &layer_collection_ptr,
+ props.layer_collection_holdout,
+ -1,
+ 0,
+ 0,
+ 0,
+ 0,
+ TIP_("Mask out objects in collection from view layer\n"
+ "* Ctrl to isolate collection\n"
+ "* Shift to set inside collections"));
+ UI_but_func_set(bt,
+ view_layer__layer_collection_set_flag_recursive_cb,
+ layer_collection,
+ (char *)"holdout");
+ UI_but_flag_enable(bt, UI_BUT_DRAG_LOCK);
+ if (!props_active.layer_collection_holdout) {
+ UI_but_flag_enable(bt, UI_BUT_INACTIVE);
+ }
+ }
+
+ if (soops->show_restrict_flags & SO_RESTRICT_INDIRECT_ONLY) {
+ bt = uiDefIconButR_prop(
+ block,
+ UI_BTYPE_ICON_TOGGLE,
+ 0,
+ 0,
+ (int)(ar->v2d.cur.xmax - restrict_offsets.indirect_only),
+ te->ys,
+ UI_UNIT_X,
+ UI_UNIT_Y,
+ &layer_collection_ptr,
+ props.layer_collection_indirect_only,
+ -1,
+ 0,
+ 0,
+ 0,
+ 0,
+ TIP_("Objects in collection only contribute indirectly (through shadows and "
+ "reflections) in the view layer\n"
+ "* Ctrl to isolate collection\n"
+ "* Shift to set inside collections"));
+ UI_but_func_set(bt,
+ view_layer__layer_collection_set_flag_recursive_cb,
+ layer_collection,
+ (char *)"indirect_only");
+ UI_but_flag_enable(bt, UI_BUT_DRAG_LOCK);
+ if (!props_active.layer_collection_indirect_only) {
+ UI_but_flag_enable(bt, UI_BUT_INACTIVE);
+ }
+ }
+ }
+
+ if (soops->show_restrict_flags & SO_RESTRICT_VIEWPORT) {
bt = uiDefIconButR_prop(block,
UI_BTYPE_ICON_TOGGLE,
0,
0,
- (int)(ar->v2d.cur.xmax - OL_TOG_RESTRICT_VIEWX),
+ (int)(ar->v2d.cur.xmax - restrict_offsets.viewport),
te->ys,
UI_UNIT_X,
UI_UNIT_Y,
@@ -938,51 +1484,102 @@ static void outliner_draw_restrictbuts(uiBlock *block,
0,
0,
0,
- NULL);
+ TIP_("Globally disable in viewports\n"
+ "* Ctrl to isolate collection\n"
+ "* Shift to set inside collections and objects"));
+ if (layer_collection != NULL) {
+ UI_but_func_set(bt,
+ view_layer__collection_set_flag_recursive_cb,
+ layer_collection,
+ (char *)"hide_viewport");
+ }
+ else {
+ UI_but_func_set(bt,
+ scenes__collection_set_flag_recursive_cb,
+ collection,
+ (char *)"hide_viewport");
+ }
UI_but_flag_enable(bt, UI_BUT_DRAG_LOCK);
+ if (!props_active.collection_hide_viewport) {
+ UI_but_flag_enable(bt, UI_BUT_INACTIVE);
+ }
}
- bt = uiDefIconButR_prop(block,
- UI_BTYPE_ICON_TOGGLE,
- 0,
- 0,
- (int)(ar->v2d.cur.xmax - OL_TOG_RESTRICT_RENDERX),
- te->ys,
- UI_UNIT_X,
- UI_UNIT_Y,
- &collection_ptr,
- props.collection_hide_render,
- -1,
- 0,
- 0,
- 0,
- 0,
- NULL);
- UI_but_flag_enable(bt, UI_BUT_DRAG_LOCK);
+ if (soops->show_restrict_flags & SO_RESTRICT_RENDER) {
+ bt = uiDefIconButR_prop(block,
+ UI_BTYPE_ICON_TOGGLE,
+ 0,
+ 0,
+ (int)(ar->v2d.cur.xmax - restrict_offsets.render),
+ te->ys,
+ UI_UNIT_X,
+ UI_UNIT_Y,
+ &collection_ptr,
+ props.collection_hide_render,
+ -1,
+ 0,
+ 0,
+ 0,
+ 0,
+ TIP_("Globally disable in renders\n"
+ "* Ctrl to isolate collection\n"
+ "* Shift to set inside collections and objects"));
+ if (layer_collection != NULL) {
+ UI_but_func_set(bt,
+ view_layer__collection_set_flag_recursive_cb,
+ layer_collection,
+ (char *)"hide_render");
+ }
+ else {
+ UI_but_func_set(
+ bt, scenes__collection_set_flag_recursive_cb, collection, (char *)"hide_render");
+ }
+ UI_but_flag_enable(bt, UI_BUT_DRAG_LOCK);
+ if (!props_active.collection_hide_render) {
+ UI_but_flag_enable(bt, UI_BUT_INACTIVE);
+ }
+ }
- bt = uiDefIconButR_prop(block,
- UI_BTYPE_ICON_TOGGLE,
- 0,
- 0,
- (int)(ar->v2d.cur.xmax - OL_TOG_RESTRICT_SELECTX),
- te->ys,
- UI_UNIT_X,
- UI_UNIT_Y,
- &collection_ptr,
- props.collection_hide_select,
- -1,
- 0,
- 0,
- 0,
- 0,
- NULL);
- UI_but_flag_enable(bt, UI_BUT_DRAG_LOCK);
+ if (soops->show_restrict_flags & SO_RESTRICT_SELECT) {
+ bt = uiDefIconButR_prop(block,
+ UI_BTYPE_ICON_TOGGLE,
+ 0,
+ 0,
+ (int)(ar->v2d.cur.xmax - restrict_offsets.select),
+ te->ys,
+ UI_UNIT_X,
+ UI_UNIT_Y,
+ &collection_ptr,
+ props.collection_hide_select,
+ -1,
+ 0,
+ 0,
+ 0,
+ 0,
+ TIP_("Disable selection in viewport\n"
+ "* Ctrl to isolate collection\n"
+ "* Shift to set inside collections and objects"));
+ if (layer_collection != NULL) {
+ UI_but_func_set(bt,
+ view_layer__collection_set_flag_recursive_cb,
+ layer_collection,
+ (char *)"hide_select");
+ }
+ else {
+ UI_but_func_set(
+ bt, scenes__collection_set_flag_recursive_cb, collection, (char *)"hide_select");
+ }
+ UI_but_flag_enable(bt, UI_BUT_DRAG_LOCK);
+ if (!props_active.collection_hide_select) {
+ UI_but_flag_enable(bt, UI_BUT_INACTIVE);
+ }
+ }
}
}
}
if (TSELEM_OPEN(tselem, soops)) {
- outliner_draw_restrictbuts(block, scene, view_layer, ar, soops, &te->subtree);
+ outliner_draw_restrictbuts(block, scene, view_layer, ar, soops, &te->subtree, props_active);
}
}
}
@@ -1005,6 +1602,23 @@ static void outliner_draw_userbuts(uiBlock *block, ARegion *ar, SpaceOutliner *s
but_flag |= UI_BUT_DISABLED;
}
+ BLI_str_format_int_grouped(buf, id->us);
+ bt = uiDefBut(block,
+ UI_BTYPE_BUT,
+ 1,
+ buf,
+ (int)(ar->v2d.cur.xmax - OL_TOG_USER_BUTS_USERS),
+ te->ys,
+ UI_UNIT_X,
+ UI_UNIT_Y,
+ NULL,
+ 0.0,
+ 0.0,
+ 0,
+ 0,
+ TIP_("Number of users of this data-block"));
+ UI_but_flag_enable(bt, but_flag);
+
if (id->flag & LIB_FAKEUSER) {
icon = ICON_FILE_TICK;
tip = TIP_("Data-block will be retained using a fake user");
@@ -1018,7 +1632,7 @@ static void outliner_draw_userbuts(uiBlock *block, ARegion *ar, SpaceOutliner *s
LIB_FAKEUSER,
1,
icon,
- (int)(ar->v2d.cur.xmax - OL_TOG_RESTRICT_VIEWX),
+ (int)(ar->v2d.cur.xmax - OL_TOG_USER_BUTS_STATUS),
te->ys,
UI_UNIT_X,
UI_UNIT_Y,
@@ -1031,29 +1645,12 @@ static void outliner_draw_userbuts(uiBlock *block, ARegion *ar, SpaceOutliner *s
UI_but_func_set(bt, restrictbutton_id_user_toggle, id, NULL);
UI_but_flag_enable(bt, but_flag);
- BLI_str_format_int_grouped(buf, id->us);
- bt = uiDefBut(block,
- UI_BTYPE_BUT,
- 1,
- buf,
- (int)(ar->v2d.cur.xmax - OL_TOG_RESTRICT_SELECTX),
- te->ys,
- UI_UNIT_X,
- UI_UNIT_Y,
- NULL,
- 0.0,
- 0.0,
- 0,
- 0,
- TIP_("Number of users of this data-block"));
- UI_but_flag_enable(bt, but_flag);
-
bt = uiDefButBitS(block,
UI_BTYPE_ICON_TOGGLE,
LIB_FAKEUSER,
1,
(id->flag & LIB_FAKEUSER) ? "F" : " ",
- (int)(ar->v2d.cur.xmax - OL_TOG_RESTRICT_RENDERX),
+ (int)(ar->v2d.cur.xmax - OL_TOG_USER_BUTS_FAKEUSER),
te->ys,
UI_UNIT_X,
UI_UNIT_Y,
@@ -1179,8 +1776,13 @@ static void outliner_draw_rnabuts(
}
}
-static void outliner_buttons(const bContext *C, uiBlock *block, ARegion *ar, TreeElement *te)
+static void outliner_buttons(const bContext *C,
+ uiBlock *block,
+ ARegion *ar,
+ const float restrict_column_width,
+ TreeElement *te)
{
+ SpaceOutliner *soops = CTX_wm_space_outliner(C);
uiBut *bt;
TreeStoreElem *tselem;
int spx, dx, len;
@@ -1206,7 +1808,11 @@ static void outliner_buttons(const bContext *C, uiBlock *block, ARegion *ar, Tre
}
spx = te->xs + 1.8f * UI_UNIT_X;
- dx = ar->v2d.cur.xmax - (spx + 3.2f * UI_UNIT_X);
+ if ((tselem->type == TSE_LAYER_COLLECTION) &&
+ (soops->show_restrict_flags & SO_RESTRICT_ENABLE)) {
+ spx += UI_UNIT_X;
+ }
+ dx = ar->v2d.cur.xmax - (spx + restrict_column_width + 0.2f * UI_UNIT_X);
bt = uiDefBut(block,
UI_BTYPE_TEXT,
@@ -1778,6 +2384,60 @@ TreeElementIcon tree_element_get_icon(TreeStoreElem *tselem, TreeElement *te)
return data;
}
+static void tselem_draw_layer_collection_enable_icon(
+ Scene *scene, uiBlock *block, int xmax, float x, float y, TreeElement *te, float alpha)
+{
+ /* Get RNA property (once for speed). */
+ static PropertyRNA *exclude_prop = NULL;
+ if (exclude_prop == NULL) {
+ exclude_prop = RNA_struct_type_find_property(&RNA_LayerCollection, "exclude");
+ }
+
+ if (x >= xmax) {
+ /* Placement of icons, copied from interface_widgets.c. */
+ float aspect = (0.8f * UI_UNIT_Y) / ICON_DEFAULT_HEIGHT;
+ x += 2.0f * aspect;
+ y += 2.0f * aspect;
+
+ /* restrict column clip... it has been coded by simply overdrawing,
+ * doesn't work for buttons */
+ char color[4];
+ int icon = RNA_property_ui_icon(exclude_prop);
+ if (UI_icon_get_theme_color(icon, (uchar *)color)) {
+ UI_icon_draw_ex(x, y, icon, U.inv_dpi_fac, alpha, 0.0f, color, true);
+ }
+ else {
+ UI_icon_draw_ex(x, y, icon, U.inv_dpi_fac, alpha, 0.0f, NULL, false);
+ }
+ }
+ else {
+ LayerCollection *layer_collection = te->directdata;
+ PointerRNA layer_collection_ptr;
+ RNA_pointer_create(&scene->id, &RNA_LayerCollection, layer_collection, &layer_collection_ptr);
+
+ char emboss = UI_block_emboss_get(block);
+ UI_block_emboss_set(block, UI_EMBOSS_NONE);
+ uiBut *bt = uiDefIconButR_prop(block,
+ UI_BTYPE_ICON_TOGGLE,
+ 0,
+ 0,
+ x,
+ y,
+ UI_UNIT_X,
+ UI_UNIT_Y,
+ &layer_collection_ptr,
+ exclude_prop,
+ -1,
+ 0,
+ 0,
+ 0,
+ 0,
+ NULL);
+ UI_but_flag_enable(bt, UI_BUT_DRAG_LOCK);
+ UI_block_emboss_set(block, emboss);
+ }
+}
+
static void tselem_draw_icon(uiBlock *block,
int xmax,
float x,
@@ -1801,7 +2461,13 @@ static void tselem_draw_icon(uiBlock *block,
/* restrict column clip... it has been coded by simply overdrawing,
* doesn't work for buttons */
- UI_icon_draw_alpha(x, y, data.icon, alpha);
+ char color[4];
+ if (UI_icon_get_theme_color(data.icon, (uchar *)color)) {
+ UI_icon_draw_ex(x, y, data.icon, U.inv_dpi_fac, alpha, 0.0f, color, true);
+ }
+ else {
+ UI_icon_draw_ex(x, y, data.icon, U.inv_dpi_fac, alpha, 0.0f, NULL, false);
+ }
}
else {
uiDefIconBut(block,
@@ -1868,6 +2534,17 @@ static void outliner_draw_iconrow_number(const uiFontStyle *fstyle,
GPU_blend(true); /* Roundbox and text drawing disables. */
}
+static void outliner_icon_background_colors(float icon_color[4], float icon_border[4])
+{
+ float text[4];
+ UI_GetThemeColor4fv(TH_TEXT, text);
+
+ copy_v3_v3(icon_color, text);
+ icon_color[3] = 0.4f;
+ copy_v3_v3(icon_border, text);
+ icon_border[3] = 0.2f;
+}
+
static void outliner_draw_iconrow_doit(uiBlock *block,
TreeElement *te,
const uiFontStyle *fstyle,
@@ -1882,23 +2559,34 @@ static void outliner_draw_iconrow_doit(uiBlock *block,
if (active != OL_DRAWSEL_NONE) {
float ufac = UI_UNIT_X / 20.0f;
- float color[4] = {1.0f, 1.0f, 1.0f, 0.2f};
-
+ float icon_color[4], icon_border[4];
+ outliner_icon_background_colors(icon_color, icon_border);
+ icon_color[3] *= alpha_fac;
+ if (active == OL_DRAWSEL_ACTIVE) {
+ UI_GetThemeColor4fv(TH_EDITED_OBJECT, icon_color);
+ icon_border[3] = 0.3f;
+ }
UI_draw_roundbox_corner_set(UI_CNR_ALL);
- color[3] *= alpha_fac;
UI_draw_roundbox_aa(true,
- (float)*offsx + 1.0f * ufac,
- (float)ys + 1.0f * ufac,
- (float)*offsx + UI_UNIT_X - 1.0f * ufac,
+ (float)*offsx,
+ (float)ys + ufac,
+ (float)*offsx + UI_UNIT_X,
+ (float)ys + UI_UNIT_Y - ufac,
+ (float)UI_UNIT_Y / 4.0f,
+ icon_color);
+ /* border around it */
+ UI_draw_roundbox_aa(false,
+ (float)*offsx,
+ (float)ys + ufac,
+ (float)*offsx + UI_UNIT_X,
(float)ys + UI_UNIT_Y - ufac,
- (float)UI_UNIT_Y / 2.0f - ufac,
- color);
+ (float)UI_UNIT_Y / 4.0f,
+ icon_border);
GPU_blend(true); /* Roundbox disables. */
}
- /* No inlined icon should be clickable. */
- tselem_draw_icon(block, xmax, (float)*offsx, (float)ys, tselem, te, 0.8f * alpha_fac, false);
+ tselem_draw_icon(block, xmax, (float)*offsx, (float)ys, tselem, te, alpha_fac, false);
te->xs = *offsx;
te->ys = ys;
te->xend = (short)*offsx + UI_UNIT_X;
@@ -1952,7 +2640,7 @@ static void outliner_draw_iconrow(bContext *C,
float alpha_fac,
MergedIconRow *merged)
{
- eOLDrawState active;
+ eOLDrawState active = OL_DRAWSEL_NONE;
const Object *obact = OBACT(view_layer);
for (TreeElement *te = lb->first; te; te = te->next) {
@@ -1972,7 +2660,7 @@ static void outliner_draw_iconrow(bContext *C,
OL_DRAWSEL_NONE;
}
else if (is_object_data_in_editmode(tselem->id, obact)) {
- active = OL_DRAWSEL_NORMAL;
+ active = OL_DRAWSEL_ACTIVE;
}
else {
active = tree_element_active(C, scene, view_layer, soops, te, OL_SETSEL_NONE, false);
@@ -2068,21 +2756,23 @@ static void outliner_draw_tree_element(bContext *C,
bool draw_grayed_out,
int startx,
int *starty,
+ const float restrict_column_width,
TreeElement **te_edit)
{
- TreeStoreElem *tselem;
+ TreeStoreElem *tselem = TREESTORE(te);
float ufac = UI_UNIT_X / 20.0f;
int offsx = 0;
eOLDrawState active = OL_DRAWSEL_NONE;
- float color[4];
- tselem = TREESTORE(te);
+ unsigned char text_color[4];
+ UI_GetThemeColor4ubv(TH_TEXT, text_color);
+ float icon_bgcolor[4], icon_border[4];
+ outliner_icon_background_colors(icon_bgcolor, icon_border);
if (*starty + 2 * UI_UNIT_Y >= ar->v2d.cur.ymin && *starty <= ar->v2d.cur.ymax) {
const float alpha_fac = ((te->flag & TE_DISABLED) || (te->flag & TE_CHILD_NOT_IN_COLLECTION) ||
draw_grayed_out) ?
0.5f :
1.0f;
- const float alpha = 0.5f * alpha_fac;
int xmax = ar->v2d.cur.xmax;
if ((tselem->flag & TSE_TEXTBUT) && (*te_edit == NULL)) {
@@ -2090,8 +2780,8 @@ static void outliner_draw_tree_element(bContext *C,
}
/* icons can be ui buts, we don't want it to overlap with restrict */
- if ((soops->flag & SO_HIDE_RESTRICTCOLS) == 0) {
- xmax -= OL_TOGW + UI_UNIT_X;
+ if (restrict_column_width > 0) {
+ xmax -= restrict_column_width + UI_UNIT_X;
}
GPU_blend(true);
@@ -2101,7 +2791,8 @@ static void outliner_draw_tree_element(bContext *C,
const Object *obact = OBACT(view_layer);
if (te->idcode == ID_SCE) {
if (tselem->id == (ID *)scene) {
- rgba_float_args_set(color, 1.0f, 1.0f, 1.0f, alpha);
+ /* active scene */
+ icon_bgcolor[3] = 0.2f;
active = OL_DRAWSEL_ACTIVE;
}
}
@@ -2111,35 +2802,33 @@ 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) {
- uchar col[4] = {0, 0, 0, 0};
-
- /* outliner active ob: always white text, circle color now similar to view3d */
-
+ if (ob == obact) {
active = OL_DRAWSEL_ACTIVE;
- if (ob == obact) {
- if (is_selected) {
- UI_GetThemeColorType4ubv(TH_ACTIVE, SPACE_VIEW3D, col);
- col[3] = alpha;
- }
+ }
- active = OL_DRAWSEL_NORMAL;
+ if (is_selected) {
+ if (ob == obact) {
+ /* active selected object */
+ UI_GetThemeColor3ubv(TH_ACTIVE_OBJECT, text_color);
+ text_color[3] = 255;
}
- else if (is_selected) {
- UI_GetThemeColorType4ubv(TH_SELECT, SPACE_VIEW3D, col);
- col[3] = alpha;
+ else {
+ /* other selected objects */
+ UI_GetThemeColor3ubv(TH_SELECTED_OBJECT, text_color);
+ text_color[3] = 255;
}
- rgba_float_args_set(
- color, (float)col[0] / 255, (float)col[1] / 255, (float)col[2] / 255, alpha);
}
}
else if (is_object_data_in_editmode(tselem->id, obact)) {
- rgba_float_args_set(color, 1.0f, 1.0f, 1.0f, alpha);
+ /* objects being edited */
+ UI_GetThemeColor4fv(TH_EDITED_OBJECT, icon_bgcolor);
+ icon_border[3] = 0.3f;
active = OL_DRAWSEL_ACTIVE;
}
else {
if (tree_element_active(C, scene, view_layer, soops, te, OL_SETSEL_NONE, false)) {
- rgba_float_args_set(color, 0.85f, 0.85f, 1.0f, alpha);
+ /* active items like camera or material */
+ icon_bgcolor[3] = 0.2f;
active = OL_DRAWSEL_ACTIVE;
}
}
@@ -2147,19 +2836,36 @@ static void outliner_draw_tree_element(bContext *C,
else {
active = tree_element_type_active(
C, scene, view_layer, soops, te, tselem, OL_SETSEL_NONE, false);
- rgba_float_args_set(color, 0.85f, 0.85f, 1.0f, alpha);
+ /* active collection*/
+ icon_bgcolor[3] = 0.2f;
+ }
+
+ /* Checkbox to enable collections. */
+ if ((tselem->type == TSE_LAYER_COLLECTION) &&
+ (soops->show_restrict_flags & SO_RESTRICT_ENABLE)) {
+ tselem_draw_layer_collection_enable_icon(
+ scene, block, xmax, (float)startx + offsx + UI_UNIT_X, (float)*starty, te, 0.8f);
+ offsx += UI_UNIT_X;
}
/* active circle */
if (active != OL_DRAWSEL_NONE) {
UI_draw_roundbox_corner_set(UI_CNR_ALL);
UI_draw_roundbox_aa(true,
- (float)startx + UI_UNIT_X + 1.0f * ufac,
- (float)*starty + 1.0f * ufac,
- (float)startx + 2.0f * UI_UNIT_X - 1.0f * ufac,
- (float)*starty + UI_UNIT_Y - 1.0f * ufac,
- UI_UNIT_Y / 2.0f - 1.0f * ufac,
- color);
+ (float)startx + offsx + UI_UNIT_X,
+ (float)*starty + ufac,
+ (float)startx + offsx + 2.0f * UI_UNIT_X,
+ (float)*starty + UI_UNIT_Y - ufac,
+ UI_UNIT_Y / 4.0f,
+ icon_bgcolor);
+ /* border around it */
+ UI_draw_roundbox_aa(false,
+ (float)startx + offsx + UI_UNIT_X,
+ (float)*starty + ufac,
+ (float)startx + offsx + 2.0f * UI_UNIT_X,
+ (float)*starty + UI_UNIT_Y - ufac,
+ UI_UNIT_Y / 4.0f,
+ icon_border);
GPU_blend(true); /* roundbox disables it */
te->flag |= TE_ACTIVE; // for lookup in display hierarchies
@@ -2190,7 +2896,6 @@ static void outliner_draw_tree_element(bContext *C,
offsx += UI_UNIT_X;
/* datatype icon */
-
if (!(ELEM(tselem->type, TSE_RNA_PROPERTY, TSE_RNA_ARRAY_ELEM, TSE_ID_BASE))) {
tselem_draw_icon(
block, xmax, (float)startx + offsx, (float)*starty, tselem, te, alpha_fac, true);
@@ -2232,21 +2937,12 @@ static void outliner_draw_tree_element(bContext *C,
/* name */
if ((tselem->flag & TSE_TEXTBUT) == 0) {
- unsigned char text_col[4];
-
- if (active == OL_DRAWSEL_NORMAL) {
- UI_GetThemeColor4ubv(TH_TEXT_HI, text_col);
- }
- else if (ELEM(tselem->type, TSE_RNA_PROPERTY, TSE_RNA_ARRAY_ELEM)) {
- UI_GetThemeColorBlend3ubv(TH_BACK, TH_TEXT, 0.75f, text_col);
- text_col[3] = 255;
- }
- else {
- UI_GetThemeColor4ubv(TH_TEXT, text_col);
+ if (ELEM(tselem->type, TSE_RNA_PROPERTY, TSE_RNA_ARRAY_ELEM)) {
+ UI_GetThemeColorBlend3ubv(TH_BACK, TH_TEXT, 0.75f, text_color);
+ text_color[3] = 255;
}
- text_col[3] *= alpha_fac;
-
- UI_fontstyle_draw_simple(fstyle, startx + offsx, *starty + 5 * ufac, te->name, text_col);
+ text_color[3] *= alpha_fac;
+ UI_fontstyle_draw_simple(fstyle, startx + offsx, *starty + 5 * ufac, te->name, text_color);
}
offsx += (int)(UI_UNIT_X + UI_fontstyle_string_width(fstyle, te->name));
@@ -2306,6 +3002,7 @@ static void outliner_draw_tree_element(bContext *C,
draw_childs_grayed_out,
startx + UI_UNIT_X,
starty,
+ restrict_column_width,
te_edit);
}
}
@@ -2513,11 +3210,15 @@ static void outliner_draw_highlights_recursive(unsigned pos,
if (tselem->flag & TSE_DRAG_BEFORE) {
immUniformColor4fv(col);
- immRecti(pos, start_x, start_y + UI_UNIT_Y, end_x, start_y + UI_UNIT_Y);
+ immRecti(pos,
+ start_x,
+ start_y + UI_UNIT_Y - U.pixelsize,
+ end_x,
+ start_y + UI_UNIT_Y + U.pixelsize);
}
else if (tselem->flag & TSE_DRAG_AFTER) {
immUniformColor4fv(col);
- immRecti(pos, start_x, start_y, end_x, start_y);
+ immRecti(pos, start_x, start_y - U.pixelsize, end_x, start_y + U.pixelsize);
}
else {
immUniformColor3fvAlpha(col, col[3] * 0.5f);
@@ -2581,7 +3282,7 @@ static void outliner_draw_tree(bContext *C,
ViewLayer *view_layer,
ARegion *ar,
SpaceOutliner *soops,
- const bool has_restrict_icons,
+ const float restrict_column_width,
TreeElement **te_edit)
{
const uiFontStyle *fstyle = UI_FSTYLE_WIDGET;
@@ -2603,8 +3304,8 @@ static void outliner_draw_tree(bContext *C,
/* set scissor so tree elements or lines can't overlap restriction icons */
float scissor[4] = {0};
- if (has_restrict_icons) {
- int mask_x = BLI_rcti_size_x(&ar->v2d.mask) - (int)OL_TOGW + 1;
+ if (restrict_column_width > 0.0f) {
+ int mask_x = BLI_rcti_size_x(&ar->v2d.mask) - (int)restrict_column_width + 1;
CLAMP_MIN(mask_x, 0);
GPU_scissor_get_f(scissor);
@@ -2632,10 +3333,11 @@ static void outliner_draw_tree(bContext *C,
(te->flag & TE_DRAGGING) != 0,
startx,
&starty,
+ restrict_column_width,
te_edit);
}
- if (has_restrict_icons) {
+ if (restrict_column_width > 0.0f) {
/* reset scissor */
GPU_scissor(UNPACK4(scissor));
}
@@ -2652,7 +3354,10 @@ static void outliner_back(ARegion *ar)
uint pos = GPU_vertformat_attr_add(format, "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
- immUniformThemeColorShade(TH_BACK, 6);
+
+ float col_alternating[4];
+ UI_GetThemeColor4fv(TH_ROW_ALTERNATE, col_alternating);
+ immUniformThemeColorBlend(TH_BACK, TH_ROW_ALTERNATE, col_alternating[3]);
const float x1 = 0.0f, x2 = ar->v2d.cur.xmax;
float y1 = ystart, y2;
@@ -2690,7 +3395,6 @@ void draw_outliner(const bContext *C)
uiBlock *block;
int sizey = 0, sizex = 0, sizex_rna = 0;
TreeElement *te_edit = NULL;
- bool has_restrict_icons;
outliner_build_tree(mainvar, scene, view_layer, soops, ar); // always
@@ -2700,6 +3404,7 @@ void draw_outliner(const bContext *C)
/* extend size to allow for horizontal scrollbar */
sizey += V2D_SCROLL_HEIGHT;
+ const float restrict_column_width = outliner_restrict_columns_width(soops);
if (soops->outlinevis == SO_DATA_API) {
/* RNA has two columns:
* - column 1 is (max_width + OL_RNA_COL_SPACEX) or
@@ -2715,7 +3420,6 @@ void draw_outliner(const bContext *C)
/* get width of data (for setting 'tot' rect, this is column 1 + column 2 + a bit extra) */
sizex = sizex_rna + OL_RNA_COL_SIZEX + 50;
- has_restrict_icons = false;
}
else {
/* width must take into account restriction columns (if visible)
@@ -2724,13 +3428,8 @@ void draw_outliner(const bContext *C)
// XXX should use outliner_width instead when te->xend will be set correctly...
outliner_rna_width(soops, &soops->tree, &sizex, 0);
- /* constant offset for restriction columns */
- // XXX this isn't that great yet...
- if ((soops->flag & SO_HIDE_RESTRICTCOLS) == 0) {
- sizex += OL_TOGW * 3;
- }
-
- has_restrict_icons = !(soops->flag & SO_HIDE_RESTRICTCOLS);
+ /* Constant offset for restriction columns */
+ sizex += restrict_column_width;
}
/* adds vertical offset */
@@ -2748,7 +3447,7 @@ void draw_outliner(const bContext *C)
outliner_back(ar);
block = UI_block_begin(C, ar, __func__, UI_EMBOSS);
outliner_draw_tree(
- (bContext *)C, block, scene, view_layer, ar, soops, has_restrict_icons, &te_edit);
+ (bContext *)C, block, scene, view_layer, ar, soops, restrict_column_width, &te_edit);
/* Default to no emboss for outliner UI. */
UI_block_emboss_set(block, UI_EMBOSS_NONE);
@@ -2761,20 +3460,22 @@ void draw_outliner(const bContext *C)
outliner_draw_rnabuts(block, ar, soops, sizex_rna, &soops->tree);
UI_block_emboss_set(block, UI_EMBOSS_NONE);
}
- else if ((soops->outlinevis == SO_ID_ORPHANS) && has_restrict_icons) {
+ else if (soops->outlinevis == SO_ID_ORPHANS) {
/* draw user toggle columns */
outliner_draw_userbuts(block, ar, soops, &soops->tree);
}
- else if (has_restrict_icons) {
+ else if (restrict_column_width > 0.0f) {
/* draw restriction columns */
- outliner_draw_restrictbuts(block, scene, view_layer, ar, soops, &soops->tree);
+ RestrictPropertiesActive props_active;
+ memset(&props_active, 1, sizeof(RestrictPropertiesActive));
+ outliner_draw_restrictbuts(block, scene, view_layer, ar, soops, &soops->tree, props_active);
}
UI_block_emboss_set(block, UI_EMBOSS);
- /* draw edit buttons if nessecery */
+ /* Draw edit buttons if necessary. */
if (te_edit) {
- outliner_buttons(C, block, ar, te_edit);
+ outliner_buttons(C, block, ar, restrict_column_width, te_edit);
}
UI_block_end(C, block);
diff --git a/source/blender/editors/space_outliner/outliner_edit.c b/source/blender/editors/space_outliner/outliner_edit.c
index a943e972cf5..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) {
@@ -1025,8 +1030,8 @@ int common_restrict_check(bContext *C, Object *ob)
Object *obedit = CTX_data_edit_object(C);
if (obedit && obedit == ob) {
/* found object is hidden, reset */
- if (ob->restrictflag & OB_RESTRICT_VIEW) {
- ob->restrictflag &= ~OB_RESTRICT_VIEW;
+ if (ob->restrictflag & OB_RESTRICT_VIEWPORT) {
+ ob->restrictflag &= ~OB_RESTRICT_VIEWPORT;
}
/* found object is unselectable, reset */
if (ob->restrictflag & OB_RESTRICT_SELECT) {
diff --git a/source/blender/editors/space_outliner/outliner_intern.h b/source/blender/editors/space_outliner/outliner_intern.h
index 8211e3005c7..15489c61230 100644
--- a/source/blender/editors/space_outliner/outliner_intern.h
+++ b/source/blender/editors/space_outliner/outliner_intern.h
@@ -156,11 +156,9 @@ typedef enum {
/* size constants */
#define OL_Y_OFFSET 2
-#define OL_TOG_RESTRICT_SELECTX (UI_UNIT_X * 3.0f + V2D_SCROLL_WIDTH)
-#define OL_TOG_RESTRICT_VIEWX (UI_UNIT_X * 2.0f + V2D_SCROLL_WIDTH)
-#define OL_TOG_RESTRICT_RENDERX (UI_UNIT_X + V2D_SCROLL_WIDTH)
-
-#define OL_TOGW OL_TOG_RESTRICT_SELECTX
+#define OL_TOG_USER_BUTS_USERS (UI_UNIT_X * 2.0f + V2D_SCROLL_WIDTH)
+#define OL_TOG_USER_BUTS_STATUS (UI_UNIT_X * 3.0f + V2D_SCROLL_WIDTH)
+#define OL_TOG_USER_BUTS_FAKEUSER (UI_UNIT_X + V2D_SCROLL_WIDTH)
#define OL_RNA_COLX (UI_UNIT_X * 15)
#define OL_RNA_COL_SIZEX (UI_UNIT_X * 7.5f)
@@ -449,5 +447,6 @@ bool outliner_tree_traverse(const SpaceOutliner *soops,
int filter_tselem_flag,
TreeTraversalFunc func,
void *customdata);
+float outliner_restrict_columns_width(const struct SpaceOutliner *soops);
#endif /* __OUTLINER_INTERN_H__ */
diff --git a/source/blender/editors/space_outliner/outliner_select.c b/source/blender/editors/space_outliner/outliner_select.c
index 995f41382cd..ae17158829c 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:
@@ -1271,8 +1243,7 @@ static bool outliner_is_co_within_restrict_columns(const SpaceOutliner *soops,
const ARegion *ar,
float view_co_x)
{
- return ((soops->outlinevis != SO_DATA_API) && !(soops->flag & SO_HIDE_RESTRICTCOLS) &&
- (view_co_x > ar->v2d.cur.xmax - OL_TOG_RESTRICT_VIEWX));
+ return (view_co_x > ar->v2d.cur.xmax - outliner_restrict_columns_width(soops));
}
/**
diff --git a/source/blender/editors/space_outliner/outliner_tree.c b/source/blender/editors/space_outliner/outliner_tree.c
index 4e3fd6037bb..80424f021e2 100644
--- a/source/blender/editors/space_outliner/outliner_tree.c
+++ b/source/blender/editors/space_outliner/outliner_tree.c
@@ -302,6 +302,9 @@ static void outliner_add_scene_contents(SpaceOutliner *soops,
tenlay->directdata = view_layer;
}
+ /* World */
+ outliner_add_element(soops, lb, sce->world, te, 0, 0);
+
/* Collections */
ten = outliner_add_element(soops, lb, &sce->id, te, TSE_SCENE_COLLECTION_BASE, 0);
ten->name = IFACE_("Scene Collection");
@@ -1370,6 +1373,12 @@ static void outliner_add_layer_collections_recursive(SpaceOutliner *soops,
const bool show_objects)
{
for (LayerCollection *lc = layer_collections->first; lc; lc = lc->next) {
+ const bool exclude = (lc->flag & LAYER_COLLECTION_EXCLUDE) != 0;
+
+ if (exclude && ((soops->show_restrict_flags & SO_RESTRICT_ENABLE) == 0)) {
+ continue;
+ }
+
ID *id = &lc->collection->id;
TreeElement *ten = outliner_add_element(soops, tree, id, parent_ten, TSE_LAYER_COLLECTION, 0);
@@ -1382,8 +1391,7 @@ static void outliner_add_layer_collections_recursive(SpaceOutliner *soops,
tselem->flag &= ~TSE_CLOSED;
}
- const bool exclude = (lc->flag & LAYER_COLLECTION_EXCLUDE) != 0;
- if (exclude || ((lc->runtime_flag & LAYER_COLLECTION_VISIBLE) == 0)) {
+ if (exclude || (lc->runtime_flag & LAYER_COLLECTION_VISIBLE) == 0) {
ten->flag |= TE_DISABLED;
}
diff --git a/source/blender/editors/space_outliner/outliner_utils.c b/source/blender/editors/space_outliner/outliner_utils.c
index 03d15088380..f57dce97b38 100644
--- a/source/blender/editors/space_outliner/outliner_utils.c
+++ b/source/blender/editors/space_outliner/outliner_utils.c
@@ -31,6 +31,7 @@
#include "ED_armature.h"
#include "UI_interface.h"
+#include "UI_view2d.h"
#include "outliner_intern.h"
@@ -261,3 +262,41 @@ bool outliner_tree_traverse(const SpaceOutliner *soops,
return true;
}
+
+float outliner_restrict_columns_width(const SpaceOutliner *soops)
+{
+ int num_columns = 0;
+
+ switch (soops->outlinevis) {
+ case SO_DATA_API:
+ case SO_SEQUENCE:
+ case SO_LIBRARIES:
+ return 0.0f;
+ case SO_ID_ORPHANS:
+ num_columns = 3;
+ break;
+ case SO_VIEW_LAYER:
+ if (soops->show_restrict_flags & SO_RESTRICT_HOLDOUT) {
+ num_columns++;
+ }
+ if (soops->show_restrict_flags & SO_RESTRICT_INDIRECT_ONLY) {
+ num_columns++;
+ }
+ ATTR_FALLTHROUGH;
+ case SO_SCENES:
+ if (soops->show_restrict_flags & SO_RESTRICT_SELECT) {
+ num_columns++;
+ }
+ if (soops->show_restrict_flags & SO_RESTRICT_HIDE) {
+ num_columns++;
+ }
+ if (soops->show_restrict_flags & SO_RESTRICT_VIEWPORT) {
+ num_columns++;
+ }
+ if (soops->show_restrict_flags & SO_RESTRICT_RENDER) {
+ num_columns++;
+ }
+ break;
+ }
+ return (num_columns * UI_UNIT_X + V2D_SCROLL_WIDTH);
+}
diff --git a/source/blender/editors/space_outliner/space_outliner.c b/source/blender/editors/space_outliner/space_outliner.c
index a8e3129b5b4..313e6014b88 100644
--- a/source/blender/editors/space_outliner/space_outliner.c
+++ b/source/blender/editors/space_outliner/space_outliner.c
@@ -302,6 +302,7 @@ static SpaceLink *outliner_new(const ScrArea *UNUSED(area), const Scene *UNUSED(
soutliner = MEM_callocN(sizeof(SpaceOutliner), "initoutliner");
soutliner->spacetype = SPACE_OUTLINER;
soutliner->filter_id_type = ID_GR;
+ soutliner->show_restrict_flags = SO_RESTRICT_ENABLE | SO_RESTRICT_HIDE;
/* header */
ar = MEM_callocN(sizeof(ARegion), "header for outliner");
@@ -383,6 +384,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)
{
@@ -400,6 +409,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 86bc315b994..fb875c8c4a4 100644
--- a/source/blender/editors/space_sequencer/sequencer_draw.c
+++ b/source/blender/editors/space_sequencer/sequencer_draw.c
@@ -60,6 +60,7 @@
#include "ED_mask.h"
#include "ED_sequencer.h"
#include "ED_screen.h"
+#include "ED_time_scrub_ui.h"
#include "ED_space_api.h"
#include "BIF_glutil.h"
@@ -960,7 +961,7 @@ static void draw_seq_strip(const bContext *C,
x1 = seq->startdisp + handsize_clamped;
x2 = seq->enddisp - handsize_clamped;
- float scroller_vert_xoffs = (V2D_SCROLL_WIDTH_TEXT + SEQ_SCROLLER_TEXT_OFFSET) * pixelx;
+ float scroller_vert_xoffs = (V2D_SCROLL_WIDTH_HANDLES + SEQ_SCROLLER_TEXT_OFFSET) * pixelx;
/* info text on the strip */
if (x1 < v2d->cur.xmin + scroller_vert_xoffs) {
@@ -1120,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)
@@ -1821,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;
@@ -1847,8 +1847,7 @@ static bool draw_cache_view_cb(
color[2] = 0.2f;
stripe_ht = UI_view2d_region_to_view_y(v2d, 4.0f * UI_DPI_FAC * U.pixelsize) -
v2d->cur.ymin;
- ;
- stripe_bot = UI_view2d_region_to_view_y(v2d, V2D_SCROLL_HEIGHT_TEXT);
+ stripe_bot = UI_view2d_region_to_view_y(v2d, V2D_SCROLL_HEIGHT_HANDLES);
stripe_top = stripe_bot + stripe_ht;
break;
}
@@ -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);
@@ -1922,12 +1922,16 @@ static void draw_cache_view(const bContext *C)
uint pos = GPU_vertformat_attr_add(immVertexFormat(), "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
- float stripe_bot, stripe_top, stripe_offs;
+ float stripe_bot, stripe_top;
+ float stripe_offs = UI_view2d_region_to_view_y(v2d, 1.0f) - v2d->cur.ymin;
float stripe_ht = UI_view2d_region_to_view_y(v2d, 4.0f * UI_DPI_FAC * U.pixelsize) -
v2d->cur.ymin;
+ CLAMP_MAX(stripe_ht, 0.2f);
+ CLAMP_MIN(stripe_offs, stripe_ht / 2);
+
if (scene->ed->cache_flag & SEQ_CACHE_VIEW_FINAL_OUT) {
- stripe_bot = UI_view2d_region_to_view_y(v2d, V2D_SCROLL_HEIGHT_TEXT);
+ stripe_bot = UI_view2d_region_to_view_y(v2d, V2D_SCROLL_HEIGHT_HANDLES);
stripe_top = stripe_bot + stripe_ht;
float bg_color[4] = {1.0f, 0.4f, 0.2f, 0.1f};
@@ -1944,10 +1948,6 @@ static void draw_cache_view(const bContext *C)
continue;
}
- CLAMP_MAX(stripe_ht, 0.2f);
- stripe_offs = UI_view2d_region_to_view_y(v2d, 1.0f) - v2d->cur.ymin;
- CLAMP_MIN(stripe_offs, stripe_ht / 2);
-
stripe_bot = seq->machine + SEQ_STRIP_OFSBOTTOM + stripe_offs;
stripe_top = stripe_bot + stripe_ht;
@@ -2086,19 +2086,22 @@ void draw_timeline_seq(const bContext *C, ARegion *ar)
/* reset view matrix */
UI_view2d_view_restore(C);
+ /* scrubbing region */
+ ED_scrubbing_draw(ar, scene, !(sseq->flag & SEQ_DRAWFRAMES), true);
+
/* scrollers */
scrollers = UI_view2d_scrollers_calc(v2d, NULL);
UI_view2d_scrollers_draw(v2d, scrollers);
UI_view2d_scrollers_free(scrollers);
- /* scale numbers */
- UI_view2d_draw_scale_x__discrete_frames_or_seconds(
- ar, v2d, &v2d->hor, scene, !(sseq->flag & SEQ_DRAWFRAMES));
- UI_view2d_draw_scale_y__block(ar, v2d, &v2d->vert);
-
- /* draw current frame number-indicator on top of scrollers */
- if ((sseq->flag & SEQ_NO_DRAW_CFRANUM) == 0) {
- UI_view2d_view_orthoSpecial(ar, v2d, 1);
- ANIM_draw_cfra_number(C, v2d, cfra_flag);
+ /* channel numbers */
+ {
+ rcti rect;
+ BLI_rcti_init(&rect,
+ 0,
+ 15 * UI_DPI_FAC,
+ 15 * UI_DPI_FAC,
+ UI_DPI_FAC * ar->sizey - UI_SCRUBBING_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 94437d4871a..a3030153e6c 100644
--- a/source/blender/editors/space_sequencer/sequencer_edit.c
+++ b/source/blender/editors/space_sequencer/sequencer_edit.c
@@ -1343,7 +1343,7 @@ static int sequencer_snap_invoke(bContext *C, wmOperator *op, const wmEvent *UNU
void SEQUENCER_OT_snap(struct wmOperatorType *ot)
{
/* identifiers */
- ot->name = "Snap Strips to Frame";
+ ot->name = "Snap Strips to Playhead";
ot->idname = "SEQUENCER_OT_snap";
ot->description = "Frame where selected strips will be snapped";
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 2b0c29a02ad..6ab44ded046 100644
--- a/source/blender/editors/space_sequencer/space_sequencer.c
+++ b/source/blender/editors/space_sequencer/space_sequencer.c
@@ -157,8 +157,8 @@ static SpaceLink *sequencer_new(const ScrArea *UNUSED(sa), const Scene *scene)
ar->v2d.minzoom = 0.01f;
ar->v2d.maxzoom = 100.0f;
- ar->v2d.scroll |= (V2D_SCROLL_BOTTOM | V2D_SCROLL_SCALE_HORIZONTAL);
- ar->v2d.scroll |= (V2D_SCROLL_LEFT | V2D_SCROLL_SCALE_VERTICAL);
+ ar->v2d.scroll |= (V2D_SCROLL_BOTTOM | V2D_SCROLL_HORIZONTAL_HANDLES);
+ ar->v2d.scroll |= (V2D_SCROLL_RIGHT | V2D_SCROLL_VERTICAL_HANDLES);
ar->v2d.keepzoom = 0;
ar->v2d.keeptot = 0;
ar->v2d.align = V2D_ALIGN_NO_NEG_Y;
@@ -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);
}
@@ -816,7 +817,7 @@ void ED_spacetype_sequencer(void)
art->draw = sequencer_main_region_draw;
art->listener = sequencer_main_region_listener;
art->message_subscribe = sequencer_main_region_message_subscribe;
- art->keymapflag = ED_KEYMAP_VIEW2D | ED_KEYMAP_MARKERS | ED_KEYMAP_FRAMES | ED_KEYMAP_ANIMATION;
+ art->keymapflag = ED_KEYMAP_VIEW2D | ED_KEYMAP_FRAMES | ED_KEYMAP_ANIMATION;
BLI_addhead(&st->regiontypes, art);
@@ -832,7 +833,7 @@ void ED_spacetype_sequencer(void)
/* regions: listview/buttons */
art = MEM_callocN(sizeof(ARegionType), "spacetype sequencer region");
art->regionid = RGN_TYPE_UI;
- art->prefsizex = 220; // XXX
+ art->prefsizex = UI_SIDEBAR_PANEL_WIDTH;
art->keymapflag = ED_KEYMAP_UI | ED_KEYMAP_FRAMES;
art->listener = sequencer_buttons_region_listener;
art->init = sequencer_buttons_region_init;
diff --git a/source/blender/editors/space_text/text_autocomplete.c b/source/blender/editors/space_text/text_autocomplete.c
index 243642b2e8c..c36175489b3 100644
--- a/source/blender/editors/space_text/text_autocomplete.c
+++ b/source/blender/editors/space_text/text_autocomplete.c
@@ -74,7 +74,7 @@ int text_do_suggest_select(SpaceText *st, ARegion *ar)
/* Count the visible lines to the cursor */
for (tmp = st->text->curl, l = -st->top; tmp; tmp = tmp->prev, l++) {
- ;
+ /* pass */
}
if (l < 0) {
return 0;
@@ -101,7 +101,7 @@ int text_do_suggest_select(SpaceText *st, ARegion *ar)
/* Work out which of the items is at the top of the visible list */
for (i = 0, item = first; i < *top && item->next; i++, item = item->next) {
- ;
+ /* pass */
}
/* Work out the target item index in the visible list */
@@ -111,7 +111,7 @@ int text_do_suggest_select(SpaceText *st, ARegion *ar)
}
for (i = tgti; i > 0 && item->next; i--, item = item->next) {
- ;
+ /* pass */
}
if (item) {
texttool_suggest_select(item);
diff --git a/source/blender/editors/space_text/text_draw.c b/source/blender/editors/space_text/text_draw.c
index cdd691fe879..ac1fb4af1c2 100644
--- a/source/blender/editors/space_text/text_draw.c
+++ b/source/blender/editors/space_text/text_draw.c
@@ -1186,7 +1186,7 @@ static void draw_suggestion_list(const SpaceText *st, const TextDrawContext *tdc
/* Set the top 'item' of the visible list */
for (i = 0, item = first; i < *top && item->next; i++, item = item->next) {
- ;
+ /* pass */
}
for (i = 0; i < SUGG_LIST_SIZE && item; i++, item = item->next) {
@@ -1665,12 +1665,14 @@ void draw_text_main(SpaceText *st, ARegion *ar)
immBindBuiltinProgram(GPU_SHADER_2D_LINE_DASHED_UNIFORM_COLOR);
+ GPU_line_width(2.0f);
+
float viewport_size[4];
GPU_viewport_size_get_f(viewport_size);
immUniform2f("viewport_size", viewport_size[2] / UI_DPI_FAC, viewport_size[3] / UI_DPI_FAC);
- immUniform1i("colors_len", 0); /* "simple" mode */
- immUniformThemeColor(TH_GRID); /* same color as line number background */
+ immUniform1i("colors_len", 0); /* "simple" mode */
+ immUniformThemeColor3(TH_GRID); /* same color as line number background */
immUniform1f("dash_width", 2.0f);
immUniform1f("dash_factor", 0.5f);
diff --git a/source/blender/editors/space_text/text_ops.c b/source/blender/editors/space_text/text_ops.c
index 7b6e0ff8771..2593571d9a3 100644
--- a/source/blender/editors/space_text/text_ops.c
+++ b/source/blender/editors/space_text/text_ops.c
@@ -101,7 +101,7 @@ static char *buf_tabs_to_spaces(const char *in_buf, const int tab_size)
}
/* Allocate output before with extra space for expanded tabs. */
- const int out_size = strlen(in_buf) + num_tabs * (tab_size - 1);
+ const int out_size = strlen(in_buf) + num_tabs * (tab_size - 1) + 1;
char *out_buf = MEM_mallocN(out_size * sizeof(char), __func__);
/* Fill output buffer. */
@@ -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(&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(&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) {
@@ -1268,7 +1268,7 @@ static int text_convert_whitespace_exec(bContext *C, wmOperator *op)
for (j = 1;
(j < tab_len) && (a + j < text_check_line_len) && (text_check_line[a + j] == ' ');
j++) {
- ;
+ /* pass */
}
if (j == tab_len) {
diff --git a/source/blender/editors/space_topbar/space_topbar.c b/source/blender/editors/space_topbar/space_topbar.c
index 8b290009a97..725a49e417e 100644
--- a/source/blender/editors/space_topbar/space_topbar.c
+++ b/source/blender/editors/space_topbar/space_topbar.c
@@ -213,12 +213,15 @@ static void recent_files_menu_draw(const bContext *UNUSED(C), Menu *menu)
{
struct RecentFile *recent;
uiLayout *layout = menu->layout;
- uiLayoutSetOperatorContext(layout, WM_OP_EXEC_REGION_WIN);
+ uiLayoutSetOperatorContext(layout, WM_OP_INVOKE_DEFAULT);
if (!BLI_listbase_is_empty(&G.recent_files)) {
for (recent = G.recent_files.first; (recent); recent = recent->next) {
const char *file = BLI_path_basename(recent->filepath);
const int icon = BLO_has_bfile_extension(file) ? ICON_FILE_BLEND : ICON_FILE_BACKUP;
- uiItemStringO(layout, file, icon, "WM_OT_open_mainfile", "filepath", recent->filepath);
+ PointerRNA ptr;
+ uiItemFullO(layout, "WM_OT_open_mainfile", file, icon, NULL, WM_OP_INVOKE_DEFAULT, 0, &ptr);
+ RNA_string_set(&ptr, "filepath", recent->filepath);
+ RNA_boolean_set(&ptr, "display_file_selector", false);
}
}
else {
diff --git a/source/blender/editors/space_userpref/space_userpref.c b/source/blender/editors/space_userpref/space_userpref.c
index 2237e8b02bc..4c6f2231cc1 100644
--- a/source/blender/editors/space_userpref/space_userpref.c
+++ b/source/blender/editors/space_userpref/space_userpref.c
@@ -249,7 +249,7 @@ void ED_spacetype_userpref(void)
art->init = userpref_navigation_region_init;
art->draw = userpref_navigation_region_draw;
art->listener = userpref_navigation_region_listener;
- art->keymapflag = ED_KEYMAP_UI;
+ art->keymapflag = ED_KEYMAP_UI | ED_KEYMAP_NAVBAR;
BLI_addhead(&st->regiontypes, art);
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/drawobject.c b/source/blender/editors/space_view3d/drawobject.c
index 638c77fc3cb..cc76c151a29 100644
--- a/source/blender/editors/space_view3d/drawobject.c
+++ b/source/blender/editors/space_view3d/drawobject.c
@@ -41,7 +41,6 @@
#include "GPU_batch.h"
#include "GPU_matrix.h"
#include "GPU_state.h"
-#include "GPU_framebuffer.h"
#include "ED_mesh.h"
@@ -51,8 +50,6 @@
#include "view3d_intern.h" /* bad level include */
-#include "../../draw/intern/draw_cache_impl.h" /* bad level include (temporary) */
-
int view3d_effective_drawtype(const struct View3D *v3d)
{
if (v3d->shading.type == OB_RENDER) {
@@ -61,24 +58,6 @@ int view3d_effective_drawtype(const struct View3D *v3d)
return v3d->shading.type;
}
-static bool check_ob_drawface_dot(Scene *sce, View3D *vd, char dt)
-{
- if ((sce->toolsettings->selectmode & SCE_SELECT_FACE) == 0) {
- return false;
- }
-
- if (G.f & G_FLAG_BACKBUFSEL) {
- return false;
- }
-
- /* if its drawing textures with zbuf sel, then don't draw dots */
- if (dt == OB_TEXTURE && vd->shading.type == OB_TEXTURE) {
- return false;
- }
-
- return true;
-}
-
/* OpenGL Circle Drawing - Tables for Optimized Drawing Speed */
/* 32 values of sin function (still same result!) */
#define CIRCLE_RESOL 32
@@ -138,216 +117,6 @@ bool view3d_camera_border_hack_test = false;
/* ***************** BACKBUF SEL (BBS) ********* */
-/** See #DRW_shgroup_world_clip_planes_from_rv3d, same function for draw manager. */
-static void bbs_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]);
-}
-
-static void bbs_mesh_verts(GPUBatch *batch, int offset, const float world_clip_planes[6][4])
-{
- GPU_point_size(UI_GetThemeValuef(TH_VERTEX_SIZE));
-
- const eGPUShaderConfig sh_cfg = world_clip_planes ? GPU_SHADER_CFG_CLIPPED :
- GPU_SHADER_CFG_DEFAULT;
- GPU_batch_program_set_builtin_with_config(batch, GPU_SHADER_3D_FLAT_SELECT_ID, sh_cfg);
- GPU_batch_uniform_1ui(batch, "offset", offset);
- if (world_clip_planes != NULL) {
- bbs_world_clip_planes_from_rv3d(batch, world_clip_planes);
- }
- GPU_batch_draw(batch);
-}
-
-static void bbs_mesh_wire(GPUBatch *batch, int offset, const float world_clip_planes[6][4])
-{
- GPU_line_width(1.0f);
- glProvokingVertex(GL_FIRST_VERTEX_CONVENTION);
-
- const eGPUShaderConfig sh_cfg = world_clip_planes ? GPU_SHADER_CFG_CLIPPED :
- GPU_SHADER_CFG_DEFAULT;
- GPU_batch_program_set_builtin_with_config(batch, GPU_SHADER_3D_FLAT_SELECT_ID, sh_cfg);
- GPU_batch_uniform_1ui(batch, "offset", offset);
- if (world_clip_planes != NULL) {
- bbs_world_clip_planes_from_rv3d(batch, world_clip_planes);
- }
- GPU_batch_draw(batch);
-
- glProvokingVertex(GL_LAST_VERTEX_CONVENTION);
-}
-
-/* two options, facecolors or black */
-static void bbs_mesh_face(GPUBatch *batch,
- const bool use_select,
- const float world_clip_planes[6][4])
-{
- if (use_select) {
- const eGPUShaderConfig sh_cfg = world_clip_planes ? GPU_SHADER_CFG_CLIPPED :
- GPU_SHADER_CFG_DEFAULT;
- GPU_batch_program_set_builtin_with_config(batch, GPU_SHADER_3D_FLAT_SELECT_ID, sh_cfg);
- GPU_batch_uniform_1ui(batch, "offset", 1);
- if (world_clip_planes != NULL) {
- bbs_world_clip_planes_from_rv3d(batch, world_clip_planes);
- }
- GPU_batch_draw(batch);
- }
- else {
- const eGPUShaderConfig sh_cfg = world_clip_planes ? GPU_SHADER_CFG_CLIPPED :
- GPU_SHADER_CFG_DEFAULT;
- GPU_batch_program_set_builtin_with_config(batch, GPU_SHADER_3D_UNIFORM_SELECT_ID, sh_cfg);
- GPU_batch_uniform_1ui(batch, "id", 0);
- if (world_clip_planes != NULL) {
- bbs_world_clip_planes_from_rv3d(batch, world_clip_planes);
- }
- GPU_batch_draw(batch);
- }
-}
-
-static void bbs_mesh_face_dot(GPUBatch *batch, const float world_clip_planes[6][4])
-{
- const eGPUShaderConfig sh_cfg = world_clip_planes ? GPU_SHADER_CFG_CLIPPED :
- GPU_SHADER_CFG_DEFAULT;
- GPU_batch_program_set_builtin_with_config(batch, GPU_SHADER_3D_FLAT_SELECT_ID, sh_cfg);
- GPU_batch_uniform_1ui(batch, "offset", 1);
- if (world_clip_planes != NULL) {
- bbs_world_clip_planes_from_rv3d(batch, world_clip_planes);
- }
- GPU_batch_draw(batch);
-}
-
-static void bbs_mesh_solid_verts(Depsgraph *UNUSED(depsgraph),
- Scene *UNUSED(scene),
- Object *ob,
- const float world_clip_planes[6][4])
-{
- Mesh *me = ob->data;
-
- GPUBatch *geom_faces = DRW_mesh_batch_cache_get_triangles_with_select_id(me);
- GPUBatch *geom_verts = DRW_mesh_batch_cache_get_verts_with_select_id(me);
- DRW_mesh_batch_cache_create_requested(ob, me, NULL, false, true);
-
- /* Only draw faces to mask out verts, we don't want their selection ID's. */
- bbs_mesh_face(geom_faces, false, world_clip_planes);
- bbs_mesh_verts(geom_verts, 1, world_clip_planes);
-
- bm_vertoffs = me->totvert + 1;
-}
-
-static void bbs_mesh_solid_faces(Scene *UNUSED(scene),
- Object *ob,
- const float world_clip_planes[6][4])
-{
- Mesh *me = ob->data;
- Mesh *me_orig = DEG_get_original_object(ob)->data;
-
- const bool use_hide = (me_orig->editflag & ME_EDIT_PAINT_FACE_SEL);
- GPUBatch *geom_faces = DRW_mesh_batch_cache_get_triangles_with_select_id(me);
- DRW_mesh_batch_cache_create_requested(ob, me, NULL, false, use_hide);
-
- bbs_mesh_face(geom_faces, true, world_clip_planes);
-}
-
-void draw_object_select_id(Depsgraph *depsgraph,
- Scene *scene,
- View3D *v3d,
- RegionView3D *rv3d,
- Object *ob,
- short select_mode)
-{
- ToolSettings *ts = scene->toolsettings;
- if (select_mode == -1) {
- select_mode = ts->selectmode;
- }
-
- GPU_matrix_mul(ob->obmat);
- GPU_depth_test(true);
-
- const float(*world_clip_planes)[4] = NULL;
- if (rv3d->rflag & RV3D_CLIPPING) {
- ED_view3d_clipping_local(rv3d, ob->obmat);
- world_clip_planes = rv3d->clip_local;
- }
-
- switch (ob->type) {
- case OB_MESH:
- if (ob->mode & OB_MODE_EDIT) {
- Mesh *me = ob->data;
- BMEditMesh *em = me->edit_mesh;
- const bool draw_facedot = check_ob_drawface_dot(scene, v3d, ob->dt);
- const bool use_faceselect = (select_mode & SCE_SELECT_FACE) != 0;
-
- BM_mesh_elem_table_ensure(em->bm, BM_VERT | BM_EDGE | BM_FACE);
-
- GPUBatch *geom_faces, *geom_edges, *geom_verts, *geom_facedots;
- geom_faces = DRW_mesh_batch_cache_get_triangles_with_select_id(me);
- if (select_mode & SCE_SELECT_EDGE) {
- geom_edges = DRW_mesh_batch_cache_get_edges_with_select_id(me);
- }
- if (select_mode & SCE_SELECT_VERTEX) {
- geom_verts = DRW_mesh_batch_cache_get_verts_with_select_id(me);
- }
- if (draw_facedot) {
- geom_facedots = DRW_mesh_batch_cache_get_facedots_with_select_id(me);
- }
- DRW_mesh_batch_cache_create_requested(ob, me, NULL, false, true);
-
- bbs_mesh_face(geom_faces, use_faceselect, world_clip_planes);
-
- if (use_faceselect && draw_facedot) {
- bbs_mesh_face_dot(geom_facedots, world_clip_planes);
- }
-
- if (select_mode & SCE_SELECT_FACE) {
- bm_solidoffs = 1 + em->bm->totface;
- }
- else {
- bm_solidoffs = 1;
- }
-
- ED_view3d_polygon_offset(rv3d, 1.0);
-
- /* we draw edges if edge select mode */
- if (select_mode & SCE_SELECT_EDGE) {
- bbs_mesh_wire(geom_edges, bm_solidoffs, world_clip_planes);
- bm_wireoffs = bm_solidoffs + em->bm->totedge;
- }
- else {
- /* `bm_vertoffs` is calculated from `bm_wireoffs`. (otherwise see T53512) */
- bm_wireoffs = bm_solidoffs;
- }
-
- ED_view3d_polygon_offset(rv3d, 1.1);
-
- /* we draw verts if vert select mode. */
- if (select_mode & SCE_SELECT_VERTEX) {
- bbs_mesh_verts(geom_verts, bm_wireoffs, world_clip_planes);
- bm_vertoffs = bm_wireoffs + em->bm->totvert;
- }
- else {
- bm_vertoffs = bm_wireoffs;
- }
-
- ED_view3d_polygon_offset(rv3d, 0.0);
- }
- else {
- Mesh *me = DEG_get_original_object(ob)->data;
- if ((me->editflag & ME_EDIT_PAINT_VERT_SEL) &&
- /* currently vertex select supports weight paint and vertex paint*/
- ((ob->mode & OB_MODE_WEIGHT_PAINT) || (ob->mode & OB_MODE_VERTEX_PAINT))) {
- bbs_mesh_solid_verts(depsgraph, scene, ob, world_clip_planes);
- }
- else {
- bbs_mesh_solid_faces(scene, ob, world_clip_planes);
- }
- }
- break;
- case OB_CURVE:
- case OB_SURF:
- break;
- }
-
- GPU_matrix_set(rv3d->viewmat);
-}
-
void ED_draw_object_facemap(Depsgraph *depsgraph,
Object *ob,
const float col[4],
diff --git a/source/blender/editors/space_view3d/space_view3d.c b/source/blender/editors/space_view3d/space_view3d.c
index 9ee7bb3066d..c1891865d6d 100644
--- a/source/blender/editors/space_view3d/space_view3d.c
+++ b/source/blender/editors/space_view3d/space_view3d.c
@@ -1131,6 +1131,9 @@ static void view3d_header_region_listener(wmWindow *UNUSED(win),
ED_region_tag_redraw(ar);
}
break;
+ case NC_BRUSH:
+ ED_region_tag_redraw(ar);
+ break;
}
/* From topbar, which ones are needed? split per header? */
@@ -1200,9 +1203,106 @@ static void view3d_buttons_region_init(wmWindowManager *wm, ARegion *ar)
WM_event_add_keymap_handler(&ar->handlers, keymap);
}
-static void view3d_buttons_region_draw(const bContext *C, ARegion *ar)
+void ED_view3d_buttons_region_layout_ex(const bContext *C,
+ ARegion *ar,
+ const char *category_override)
{
- ED_region_panels_ex(C, ar, (const char *[]){CTX_data_mode_string(C), NULL}, -1, true);
+ const enum eContextObjectMode mode = CTX_data_mode_enum(C);
+
+ const char *contexts_base[4] = {NULL};
+ contexts_base[0] = CTX_data_mode_string(C);
+
+ const char **contexts = &contexts_base[1];
+
+ switch (mode) {
+ case CTX_MODE_EDIT_MESH:
+ ARRAY_SET_ITEMS(contexts, ".mesh_edit");
+ break;
+ case CTX_MODE_EDIT_CURVE:
+ ARRAY_SET_ITEMS(contexts, ".curve_edit");
+ break;
+ case CTX_MODE_EDIT_SURFACE:
+ ARRAY_SET_ITEMS(contexts, ".curve_edit");
+ break;
+ case CTX_MODE_EDIT_TEXT:
+ ARRAY_SET_ITEMS(contexts, ".text_edit");
+ break;
+ case CTX_MODE_EDIT_ARMATURE:
+ ARRAY_SET_ITEMS(contexts, ".armature_edit");
+ break;
+ case CTX_MODE_EDIT_METABALL:
+ ARRAY_SET_ITEMS(contexts, ".mball_edit");
+ break;
+ case CTX_MODE_EDIT_LATTICE:
+ ARRAY_SET_ITEMS(contexts, ".lattice_edit");
+ break;
+ case CTX_MODE_POSE:
+ ARRAY_SET_ITEMS(contexts, ".posemode");
+ break;
+ case CTX_MODE_SCULPT:
+ ARRAY_SET_ITEMS(contexts, ".paint_common", ".sculpt_mode");
+ break;
+ case CTX_MODE_PAINT_WEIGHT:
+ ARRAY_SET_ITEMS(contexts, ".paint_common", ".weightpaint");
+ break;
+ case CTX_MODE_PAINT_VERTEX:
+ ARRAY_SET_ITEMS(contexts, ".paint_common", ".vertexpaint");
+ break;
+ case CTX_MODE_PAINT_TEXTURE:
+ ARRAY_SET_ITEMS(contexts, ".paint_common", ".imagepaint");
+ break;
+ case CTX_MODE_PARTICLE:
+ ARRAY_SET_ITEMS(contexts, ".paint_common", ".particlemode");
+ break;
+ case CTX_MODE_OBJECT:
+ ARRAY_SET_ITEMS(contexts, ".objectmode");
+ break;
+ case CTX_MODE_PAINT_GPENCIL:
+ ARRAY_SET_ITEMS(contexts, ".greasepencil_paint");
+ break;
+ case CTX_MODE_SCULPT_GPENCIL:
+ ARRAY_SET_ITEMS(contexts, ".greasepencil_sculpt");
+ break;
+ case CTX_MODE_WEIGHT_GPENCIL:
+ ARRAY_SET_ITEMS(contexts, ".greasepencil_weight");
+ break;
+ default:
+ break;
+ }
+
+ switch (mode) {
+ case CTX_MODE_PAINT_GPENCIL:
+ ARRAY_SET_ITEMS(contexts, ".greasepencil_paint");
+ break;
+ case CTX_MODE_SCULPT_GPENCIL:
+ ARRAY_SET_ITEMS(contexts, ".greasepencil_sculpt");
+ break;
+ case CTX_MODE_WEIGHT_GPENCIL:
+ ARRAY_SET_ITEMS(contexts, ".greasepencil_weight");
+ break;
+ case CTX_MODE_EDIT_GPENCIL:
+ ARRAY_SET_ITEMS(contexts, ".greasepencil_edit");
+ break;
+ default:
+ break;
+ }
+
+ ListBase *paneltypes = &ar->type->paneltypes;
+
+ /* Allow drawing 3D view toolbar from non 3D view space type. */
+ if (category_override != NULL) {
+ SpaceType *st = BKE_spacetype_from_id(SPACE_VIEW3D);
+ ARegionType *art = BKE_regiontype_from_id(st, RGN_TYPE_UI);
+ paneltypes = &art->paneltypes;
+ }
+
+ const bool vertical = true;
+ ED_region_panels_layout_ex(C, ar, paneltypes, contexts_base, -1, vertical, category_override);
+}
+
+static void view3d_buttons_region_layout(const bContext *C, ARegion *ar)
+{
+ ED_view3d_buttons_region_layout_ex(C, ar, NULL);
}
static void view3d_buttons_region_listener(wmWindow *UNUSED(win),
@@ -1507,11 +1607,13 @@ void ED_spacetype_view3d(void)
/* regions: listview/buttons */
art = MEM_callocN(sizeof(ARegionType), "spacetype view3d buttons region");
art->regionid = RGN_TYPE_UI;
- art->prefsizex = 180; /* XXX */
+ art->prefsizex = UI_SIDEBAR_PANEL_WIDTH;
art->keymapflag = ED_KEYMAP_UI | ED_KEYMAP_FRAMES;
art->listener = view3d_buttons_region_listener;
+ art->message_subscribe = ED_area_do_mgs_subscribe_for_tool_ui;
art->init = view3d_buttons_region_init;
- art->draw = view3d_buttons_region_draw;
+ art->layout = view3d_buttons_region_layout;
+ art->draw = ED_region_panels_draw;
BLI_addhead(&st->regiontypes, art);
view3d_buttons_register(art);
@@ -1535,9 +1637,9 @@ void ED_spacetype_view3d(void)
art->prefsizey = HEADERY;
art->keymapflag = ED_KEYMAP_UI | ED_KEYMAP_VIEW2D | ED_KEYMAP_FRAMES | ED_KEYMAP_HEADER;
art->listener = view3d_header_region_listener;
+ art->message_subscribe = ED_area_do_mgs_subscribe_for_tool_header;
art->init = view3d_header_region_init;
art->draw = view3d_header_region_draw;
- art->message_subscribe = view3d_header_region_message_subscribe;
BLI_addhead(&st->regiontypes, art);
/* regions: header */
@@ -1546,9 +1648,9 @@ void ED_spacetype_view3d(void)
art->prefsizey = HEADERY;
art->keymapflag = ED_KEYMAP_UI | ED_KEYMAP_VIEW2D | ED_KEYMAP_FRAMES | ED_KEYMAP_HEADER;
art->listener = view3d_header_region_listener;
+ art->message_subscribe = view3d_header_region_message_subscribe;
art->init = view3d_header_region_init;
art->draw = view3d_header_region_draw;
- art->message_subscribe = ED_area_do_mgs_subscribe_for_tool_header;
BLI_addhead(&st->regiontypes, art);
/* regions: hud */
diff --git a/source/blender/editors/space_view3d/view3d_draw.c b/source/blender/editors/space_view3d/view3d_draw.c
index 8c5f1c16438..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);
}
}
@@ -1503,7 +1519,6 @@ void ED_view3d_draw_offscreen(Depsgraph *depsgraph,
bool do_sky,
bool UNUSED(is_persp),
const char *viewname,
- GPUFXSettings *UNUSED(fx_settings),
const bool do_color_management,
GPUOffScreen *ofs,
GPUViewport *viewport)
@@ -1546,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 */
@@ -1580,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,
@@ -1590,10 +1604,8 @@ 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 */
- GPUFXSettings fx_settings = v3d->fx_settings;
bool is_ortho = false;
float winmat[4][4];
@@ -1613,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;
@@ -1640,8 +1652,6 @@ ImBuf *ED_view3d_draw_offscreen_imbuf(Depsgraph *depsgraph,
BKE_camera_params_compute_viewplane(&params, sizex, sizey, scene->r.xasp, scene->r.yasp);
BKE_camera_params_compute_matrix(&params);
- BKE_camera_to_gpu_dof(camera, &fx_settings);
-
is_ortho = params.is_ortho;
copy_m4_m4(winmat, params.winmat);
}
@@ -1671,123 +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,
- &fx_settings,
- 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,
- &fx_settings,
- 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,
- &fx_settings,
- 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);
- }
-
- 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);
- }
- }
+ 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);
- 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 */
@@ -1896,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 b0cee18f8e3..755852a2e18 100644
--- a/source/blender/editors/space_view3d/view3d_draw_legacy.c
+++ b/source/blender/editors/space_view3d/view3d_draw_legacy.c
@@ -77,6 +77,7 @@
#include "ED_armature.h"
#include "ED_keyframing.h"
#include "ED_gpencil.h"
+#include "ED_mesh.h"
#include "ED_screen.h"
#include "ED_space_api.h"
#include "ED_screen_types.h"
@@ -151,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);
@@ -177,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;
@@ -189,34 +185,25 @@ 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);
- draw_object_select_id(depsgraph, scene_eval, v3d, rv3d, obact_eval, select_mode);
+ DRW_draw_select_id_object(scene_eval,
+ rv3d,
+ obact_eval,
+ scene->toolsettings->selectmode,
+ false,
+ 1,
+ &dummy_vert_ofs,
+ &dummy_edge_ofs,
+ &dummy_face_ofs);
+
DRW_framebuffer_select_id_release(ar);
}
/* 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.
@@ -241,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) {
@@ -271,10 +252,8 @@ void ED_view3d_backbuf_depth_validate(ViewContext *vc)
}
}
-uint *ED_view3d_select_id_read_rect(ViewContext *vc, const rcti *clip, uint *r_buf_len)
+uint *ED_view3d_select_id_read_rect(const rcti *clip, uint *r_buf_len)
{
- ED_view3d_select_id_validate(vc);
-
uint width = BLI_rcti_size_x(clip);
uint height = BLI_rcti_size_y(clip);
uint buf_len = width * height;
@@ -298,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;
@@ -330,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;
@@ -339,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_camera.c b/source/blender/editors/space_view3d/view3d_gizmo_camera.c
index 0b8c3b8cd28..5fe62a74d4b 100644
--- a/source/blender/editors/space_view3d/view3d_gizmo_camera.c
+++ b/source/blender/editors/space_view3d/view3d_gizmo_camera.c
@@ -154,7 +154,7 @@ static void WIDGETGROUP_camera_refresh(const bContext *C, wmGizmoGroup *gzgroup)
/* need to set property here for undo. TODO would prefer to do this in _init */
WM_gizmo_target_property_def_rna(
- cagzgroup->dop_dist, "offset", &camera_ptr, "dof_distance", -1);
+ cagzgroup->dop_dist, "offset", &camera_ptr, "dof.focus_distance", -1);
}
else {
WM_gizmo_set_flag(cagzgroup->dop_dist, WM_GIZMO_HIDDEN, true);
@@ -262,7 +262,7 @@ static void WIDGETGROUP_camera_message_subscribe(const bContext *C,
};
{
- extern PropertyRNA rna_Camera_dof_distance;
+ extern PropertyRNA rna_CameraDOFSettings_focus_distance;
extern PropertyRNA rna_Camera_display_size;
extern PropertyRNA rna_Camera_ortho_scale;
extern PropertyRNA rna_Camera_sensor_fit;
@@ -273,7 +273,7 @@ static void WIDGETGROUP_camera_message_subscribe(const bContext *C,
extern PropertyRNA rna_Camera_type;
extern PropertyRNA rna_Camera_lens;
const PropertyRNA *props[] = {
- &rna_Camera_dof_distance,
+ &rna_CameraDOFSettings_focus_distance,
&rna_Camera_display_size,
&rna_Camera_ortho_scale,
&rna_Camera_sensor_fit,
diff --git a/source/blender/editors/space_view3d/view3d_gizmo_preselect_type.c b/source/blender/editors/space_view3d/view3d_gizmo_preselect_type.c
index 6f35c0aa748..9cbf179ab49 100644
--- a/source/blender/editors/space_view3d/view3d_gizmo_preselect_type.c
+++ b/source/blender/editors/space_view3d/view3d_gizmo_preselect_type.c
@@ -304,15 +304,14 @@ static int gizmo_preselect_edgering_test_select(bContext *C, wmGizmo *gz, const
em_setup_viewcontext(C, &vc);
copy_v2_v2_int(vc.mval, mval);
- for (uint base_index = 0; base_index < gz_ring->bases_len; base_index++) {
- Object *ob_iter = gz_ring->bases[base_index]->object;
- ED_view3d_viewcontext_init_object(&vc, ob_iter);
- BMEdge *eed_test = EDBM_edge_find_nearest_ex(&vc, &best.dist, NULL, false, false, NULL);
- if (eed_test) {
- best.ob = ob_iter;
- best.eed = eed_test;
- best.base_index = base_index;
- }
+ uint base_index;
+ BMEdge *eed_test = EDBM_edge_find_nearest_ex(
+ &vc, &best.dist, NULL, false, false, NULL, gz_ring->bases, gz_ring->bases_len, &base_index);
+
+ if (eed_test) {
+ best.ob = gz_ring->bases[base_index]->object;
+ best.eed = eed_test;
+ best.base_index = base_index;
}
BMesh *bm = NULL;
diff --git a/source/blender/editors/space_view3d/view3d_intern.h b/source/blender/editors/space_view3d/view3d_intern.h
index 9075909a6fe..e499672acc1 100644
--- a/source/blender/editors/space_view3d/view3d_intern.h
+++ b/source/blender/editors/space_view3d/view3d_intern.h
@@ -127,13 +127,6 @@ void VIEW3D_OT_fly(struct wmOperatorType *ot);
void VIEW3D_OT_walk(struct wmOperatorType *ot);
/* drawobject.c */
-void draw_object_select_id(struct Depsgraph *depsgraph,
- Scene *scene,
- View3D *v3d,
- RegionView3D *rv3d,
- struct Object *ob,
- short select_mode);
-
int view3d_effective_drawtype(const struct View3D *v3d);
/* view3d_draw.c */
diff --git a/source/blender/editors/space_view3d/view3d_select.c b/source/blender/editors/space_view3d/view3d_select.c
index 2ce23486476..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"
@@ -57,6 +58,7 @@
#include "IMB_imbuf_types.h"
#include "IMB_imbuf.h"
#include "BKE_global.h"
+#include "BKE_main.h"
#include "BKE_armature.h"
#include "BKE_context.h"
@@ -87,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"
@@ -134,9 +137,6 @@ void ED_view3d_viewcontext_init_object(ViewContext *vc, Object *obact)
if (vc->obedit) {
BLI_assert(BKE_object_is_in_editmode(obact));
vc->obedit = obact;
- /* previous selections are now invalid. */
- vc->v3d->flag |= V3D_INVALID_BACKBUF;
-
if (vc->em) {
vc->em = BKE_editmesh_from_object(vc->obedit);
}
@@ -181,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);
@@ -206,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);
@@ -228,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);
@@ -251,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);
@@ -274,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);
@@ -623,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);
@@ -640,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);
@@ -674,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)
@@ -681,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);
@@ -701,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(
@@ -714,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(
@@ -733,8 +868,6 @@ static bool do_lasso_select_mesh(ViewContext *vc,
}
}
- EDBM_backbuf_free();
-
if (data.is_changed) {
EDBM_selectmode_flush(vc->em);
}
@@ -975,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)
@@ -996,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;
@@ -1025,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)
@@ -1040,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);
@@ -1100,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))) {
@@ -1122,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:
@@ -1157,6 +1307,9 @@ static bool view3d_lasso_select(
}
FOREACH_OBJECT_IN_MODE_END;
}
+
+ WM_generic_user_data_free(wm_userdata);
+
return changed_multi;
}
@@ -1170,6 +1323,7 @@ static int view3d_lasso_select_exec(bContext *C, wmOperator *op)
if (mcords) {
view3d_operator_needs_opengl(C);
+ BKE_object_update_select_id(CTX_data_main(C));
/* setup view context for argument to callbacks */
ED_view3d_viewcontext_init(C, &vc);
@@ -1337,7 +1491,7 @@ static Base *object_mouse_select_menu(
if (buffer) {
for (int a = 0; a < hits; a++) {
/* index was converted */
- if (base->object->select_id == (buffer[(4 * a) + 3] & ~0xFFFF0000)) {
+ if (base->object->runtime.select_id == (buffer[(4 * a) + 3] & ~0xFFFF0000)) {
ok = true;
break;
}
@@ -1609,7 +1763,7 @@ static Base *mouse_select_eval_buffer(ViewContext *vc,
else {
/* only exclude active object when it is selected... */
if (BASACT(view_layer) && (BASACT(view_layer)->flag & BASE_SELECTED) && hits > 1) {
- notcol = BASACT(view_layer)->object->select_id;
+ notcol = BASACT(view_layer)->object->runtime.select_id;
}
for (a = 0; a < hits; a++) {
@@ -1623,7 +1777,7 @@ static Base *mouse_select_eval_buffer(ViewContext *vc,
base = FIRSTBASE(view_layer);
while (base) {
if (BASE_SELECTABLE(v3d, base)) {
- if (base->object->select_id == selcol) {
+ if (base->object->runtime.select_id == selcol) {
break;
}
}
@@ -1654,13 +1808,13 @@ static Base *mouse_select_eval_buffer(ViewContext *vc,
if (has_bones) {
/* skip non-bone objects */
if ((buffer[4 * a + 3] & 0xFFFF0000)) {
- if (base->object->select_id == (buffer[(4 * a) + 3] & 0xFFFF)) {
+ if (base->object->runtime.select_id == (buffer[(4 * a) + 3] & 0xFFFF)) {
basact = base;
}
}
}
else {
- if (base->object->select_id == (buffer[(4 * a) + 3] & 0xFFFF)) {
+ if (base->object->runtime.select_id == (buffer[(4 * a) + 3] & 0xFFFF)) {
basact = base;
}
}
@@ -1693,6 +1847,7 @@ Base *ED_view3d_give_base_under_cursor(bContext *C, const int mval[2])
/* setup view context for argument to callbacks */
view3d_operator_needs_opengl(C);
+ BKE_object_update_select_id(CTX_data_main(C));
ED_view3d_viewcontext_init(C, &vc);
@@ -1878,7 +2033,7 @@ static bool ed_object_select_pick(bContext *C,
/* if there's bundles in buffer select bundles first,
* so non-camera elements should be ignored in buffer */
- if (basact->object->select_id != (hitresult & 0xFFFF)) {
+ if (basact->object->runtime.select_id != (hitresult & 0xFFFF)) {
continue;
}
@@ -2129,6 +2284,7 @@ static int view3d_select_exec(bContext *C, wmOperator *op)
RNA_int_get_array(op->ptr, "location", location);
view3d_operator_needs_opengl(C);
+ BKE_object_update_select_id(CTX_data_main(C));
if (object) {
obedit = NULL;
@@ -2335,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;
@@ -2354,48 +2514,16 @@ static bool do_paintvert_box_select(ViewContext *vc, const rcti *rect, const eSe
/* pass */
}
else if (use_zbuf) {
- MVert *mvert;
- unsigned int *rt;
- int a, index;
- char *selar;
-
- selar = MEM_callocN(me->totvert + 1, "selar");
-
- uint buf_len;
- uint *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;
@@ -2419,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,
@@ -2519,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) {
@@ -2536,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);
@@ -2560,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);
@@ -2579,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(
@@ -2591,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(
@@ -2610,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);
}
@@ -2652,7 +2853,7 @@ static bool do_meta_box_select(ViewContext *vc, const rcti *rect, const eSelectO
}
const uint hit_object = hitresult & 0xFFFF;
- if (vc->obedit->select_id != hit_object) {
+ if (vc->obedit->runtime.select_id != hit_object) {
continue;
}
@@ -2803,7 +3004,7 @@ static bool do_object_box_select(bContext *C, ViewContext *vc, rcti *rect, const
for (Base *base = vc->view_layer->object_bases.first; base; base = base->next) {
if (BASE_SELECTABLE(v3d, base)) {
- if ((base->object->select_id & 0x0000FFFF) != 0) {
+ if ((base->object->runtime.select_id & 0x0000FFFF) != 0) {
BLI_array_append(bases, base);
}
}
@@ -2893,7 +3094,7 @@ static bool do_pose_box_select(bContext *C, ViewContext *vc, rcti *rect, const e
/* Select the next bone if we're not switching bases. */
if (col + 4 != col_end) {
- if ((base->object->select_id & 0x0000FFFF) != (col[4] & 0x0000FFFF)) {
+ if ((base->object->runtime.select_id & 0x0000FFFF) != (col[4] & 0x0000FFFF)) {
break;
}
if (base->object->pose != NULL) {
@@ -2929,7 +3130,11 @@ 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));
/* setup view context for argument to callbacks */
ED_view3d_viewcontext_init(C, &vc);
@@ -2938,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);
@@ -2947,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);
@@ -2997,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);
@@ -3013,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;
}
@@ -3118,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);
@@ -3134,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);
@@ -3149,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);
@@ -3158,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);
@@ -3177,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)
@@ -3184,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)) {
@@ -3192,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);
}
@@ -3218,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)
@@ -3226,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;
@@ -3238,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 {
@@ -3591,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,
@@ -3660,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);
@@ -3670,6 +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);
+ 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);
@@ -3678,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);
@@ -3714,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_utils.c b/source/blender/editors/space_view3d/view3d_utils.c
index 91313657f59..bb8c1a40a05 100644
--- a/source/blender/editors/space_view3d/view3d_utils.c
+++ b/source/blender/editors/space_view3d/view3d_utils.c
@@ -86,21 +86,6 @@ void ED_view3d_background_color_get(const Scene *scene, const View3D *v3d, float
UI_GetThemeColor3fv(TH_BACK, r_color);
}
-void ED_view3d_cursor3d_calc_mat3(const Scene *scene, float mat[3][3])
-{
- const View3DCursor *cursor = &scene->cursor;
- BKE_scene_cursor_rot_to_mat3(cursor, mat);
-}
-
-void ED_view3d_cursor3d_calc_mat4(const Scene *scene, float mat[4][4])
-{
- const View3DCursor *cursor = &scene->cursor;
- float mat3[3][3];
- BKE_scene_cursor_rot_to_mat3(cursor, mat3);
- copy_m4_m3(mat, mat3);
- copy_v3_v3(mat[3], cursor->location);
-}
-
Camera *ED_view3d_camera_data_get(View3D *v3d, RegionView3D *rv3d)
{
/* establish the camera object,
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 81405b55ac2..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);
@@ -4917,8 +4918,7 @@ static void initSnapSpatial(TransInfo *t, float r_snap[3])
}
else if (t->spacetype == SPACE_NODE) {
r_snap[0] = 0.0f;
- r_snap[1] = ED_node_grid_size();
- r_snap[2] = ED_node_grid_size();
+ r_snap[1] = r_snap[2] = ED_node_grid_size();
}
else if (t->spacetype == SPACE_GRAPH) {
r_snap[0] = 0.0f;
diff --git a/source/blender/editors/transform/transform.h b/source/blender/editors/transform/transform.h
index 50fc1a276b9..b0f720bfdf7 100644
--- a/source/blender/editors/transform/transform.h
+++ b/source/blender/editors/transform/transform.h
@@ -383,6 +383,30 @@ typedef struct BoneInitData {
float zwidth;
} BoneInitData;
+typedef struct PoseInitData_Mirror {
+ /** Points to the bone which this info is initialized & restored to.
+ * A NULL value is used to terminate the array. */
+ struct bPoseChannel *pchan;
+ struct {
+ float loc[3];
+ float size[3];
+ union {
+ float eul[3];
+ float quat[4];
+ float axis_angle[4];
+ };
+ float curve_in_x;
+ float curve_out_x;
+ float roll1;
+ float roll2;
+ } orig;
+ /**
+ * An extra offset to apply after mirroring.
+ * Use with #POSE_MIRROR_RELATIVE.
+ */
+ float offset_mtx[4][4];
+} PoseInitData_Mirror;
+
typedef struct TransData {
/** Distance needed to affect element (for Proportionnal Editing). */
float dist;
@@ -501,7 +525,7 @@ typedef struct TransDataContainer {
struct Object *obedit;
/**
- * Use when #T_LOCAL_MATRIX is set.
+ * Store matrix, this avoids having to have duplicate check all over
* Typically: 'obedit->obmat' or 'poseobj->obmat', but may be used elsewhere too.
*/
bool use_local_mat;
@@ -715,10 +739,8 @@ enum {
T_CURSOR = 1 << 5,
/** Transform points, having no rotation/scale. */
T_POINTS = 1 << 6,
- /**
- * Apply matrix #TransDataContainer.matrix, this avoids having to have duplicate check all over
- * that happen to apply to specific modes (edit & pose for eg). */
- T_LOCAL_MATRIX = 1 << 7,
+
+ /* empty slot - (1 << 7) */
/** restrictions flags */
T_NO_CONSTRAINT = 1 << 8,
@@ -892,6 +914,7 @@ void flushTransSeq(TransInfo *t);
void flushTransTracking(TransInfo *t);
void flushTransMasking(TransInfo *t);
void flushTransPaintCurve(TransInfo *t);
+void restoreMirrorPoseBones(TransDataContainer *tc);
void restoreBones(TransDataContainer *tc);
/*********************** transform_gizmo.c ********** */
diff --git a/source/blender/editors/transform/transform_conversions.c b/source/blender/editors/transform/transform_conversions.c
index 6c1da5ae825..4037fab2b68 100644
--- a/source/blender/editors/transform/transform_conversions.c
+++ b/source/blender/editors/transform/transform_conversions.c
@@ -198,7 +198,10 @@ void sort_trans_data_dist(TransInfo *t)
}
}
-static void sort_trans_data_container(TransDataContainer *tc)
+/**
+ * Make #TD_SELECTED first in the array.
+ */
+static void sort_trans_data_selected_first_container(TransDataContainer *tc)
{
TransData *sel, *unsel;
TransData temp;
@@ -225,10 +228,10 @@ static void sort_trans_data_container(TransDataContainer *tc)
unsel++;
}
}
-static void sort_trans_data(TransInfo *t)
+static void sort_trans_data_selected_first(TransInfo *t)
{
FOREACH_TRANS_DATA_CONTAINER (t, tc) {
- sort_trans_data_container(tc);
+ sort_trans_data_selected_first_container(tc);
}
}
@@ -1201,6 +1204,74 @@ static short pose_grab_with_ik(Main *bmain, Object *ob)
return (tot_ik) ? 1 : 0;
}
+static void pose_mirror_info_init(PoseInitData_Mirror *pid,
+ bPoseChannel *pchan,
+ bPoseChannel *pchan_orig,
+ bool is_mirror_relative)
+{
+ pid->pchan = pchan;
+ copy_v3_v3(pid->orig.loc, pchan->loc);
+ copy_v3_v3(pid->orig.size, pchan->size);
+ pid->orig.curve_in_x = pchan->curve_in_x;
+ pid->orig.curve_out_x = pchan->curve_out_x;
+ pid->orig.roll1 = pchan->roll1;
+ pid->orig.roll2 = pchan->roll2;
+
+ if (pchan->rotmode > 0) {
+ copy_v3_v3(pid->orig.eul, pchan->eul);
+ }
+ else if (pchan->rotmode == ROT_MODE_AXISANGLE) {
+ copy_v3_v3(pid->orig.axis_angle, pchan->rotAxis);
+ pid->orig.axis_angle[3] = pchan->rotAngle;
+ }
+ else {
+ copy_qt_qt(pid->orig.quat, pchan->quat);
+ }
+
+ if (is_mirror_relative) {
+ float pchan_mtx[4][4];
+ float pchan_mtx_mirror[4][4];
+
+ float flip_mtx[4][4];
+ unit_m4(flip_mtx);
+ flip_mtx[0][0] = -1;
+
+ BKE_pchan_to_mat4(pchan_orig, pchan_mtx_mirror);
+ BKE_pchan_to_mat4(pchan, pchan_mtx);
+
+ mul_m4_m4m4(pchan_mtx_mirror, pchan_mtx_mirror, flip_mtx);
+ mul_m4_m4m4(pchan_mtx_mirror, flip_mtx, pchan_mtx_mirror);
+
+ invert_m4(pchan_mtx_mirror);
+ mul_m4_m4m4(pid->offset_mtx, pchan_mtx, pchan_mtx_mirror);
+ }
+ else {
+ unit_m4(pid->offset_mtx);
+ }
+}
+
+static void pose_mirror_info_restore(const PoseInitData_Mirror *pid)
+{
+ bPoseChannel *pchan = pid->pchan;
+ copy_v3_v3(pchan->loc, pid->orig.loc);
+ copy_v3_v3(pchan->size, pid->orig.size);
+ pchan->curve_in_x = pid->orig.curve_in_x;
+ pchan->curve_out_x = pid->orig.curve_out_x;
+ pchan->roll1 = pid->orig.roll1;
+ pchan->roll2 = pid->orig.roll2;
+
+ if (pchan->rotmode > 0) {
+ copy_v3_v3(pchan->eul, pid->orig.eul);
+ }
+ else if (pchan->rotmode == ROT_MODE_AXISANGLE) {
+ copy_v3_v3(pchan->rotAxis, pid->orig.axis_angle);
+ pchan->rotAngle = pid->orig.axis_angle[3];
+ }
+ else {
+ copy_qt_qt(pchan->quat, pid->orig.quat);
+ }
+}
+
/**
* When objects array is NULL, use 't->data_container' as is.
*/
@@ -1215,16 +1286,19 @@ static void createTransPose(TransInfo *t)
FOREACH_TRANS_DATA_CONTAINER (t, tc) {
Object *ob = tc->poseobj;
+ bPose *pose = ob->pose;
bArmature *arm;
short ik_on = 0;
/* check validity of state */
arm = BKE_armature_from_object(tc->poseobj);
- if ((arm == NULL) || (ob->pose == NULL)) {
+ if ((arm == NULL) || (pose == NULL)) {
continue;
}
+ const bool mirror = ((pose->flag & POSE_MIRROR_EDIT) != 0);
+
/* set flags and count total */
tc->data_len = count_set_pose_transflags(ob, t->mode, t->around, has_translate_rotate);
if (tc->data_len == 0) {
@@ -1240,13 +1314,32 @@ static void createTransPose(TransInfo *t)
}
/* do we need to add temporal IK chains? */
- if ((arm->flag & ARM_AUTO_IK) && t->mode == TFM_TRANSLATION) {
+ if ((pose->flag & POSE_AUTO_IK) && t->mode == TFM_TRANSLATION) {
ik_on = pose_grab_with_ik(bmain, ob);
if (ik_on) {
t->flag |= T_AUTOIK;
has_translate_rotate[0] = true;
}
}
+
+ if (mirror) {
+ int total_mirrored = 0;
+ for (bPoseChannel *pchan = ob->pose->chanbase.first; pchan; pchan = pchan->next) {
+ if ((pchan->bone->flag & BONE_TRANSFORM) &&
+ BKE_pose_channel_get_mirrored(ob->pose, pchan->name)) {
+ total_mirrored++;
+ }
+ }
+
+ PoseInitData_Mirror *pid = MEM_mallocN((total_mirrored + 1) * sizeof(PoseInitData_Mirror),
+ "PoseInitData_Mirror");
+
+ /* Trick to terminate iteration. */
+ pid[total_mirrored].pchan = NULL;
+
+ tc->custom.type.data = pid;
+ tc->custom.type.use_free = true;
+ }
}
/* if there are no translatable bones, do rotation */
@@ -1269,6 +1362,17 @@ static void createTransPose(TransInfo *t)
short ik_on = 0;
int i;
+ PoseInitData_Mirror *pid = tc->custom.type.data;
+ int pid_index = 0;
+ bPose *pose = ob->pose;
+
+ if (pose == NULL) {
+ continue;
+ }
+
+ const bool mirror = ((pose->flag & POSE_MIRROR_EDIT) != 0);
+ const bool is_mirror_relative = ((pose->flag & POSE_MIRROR_RELATIVE) != 0);
+
tc->poseobj = ob; /* we also allow non-active objects to be transformed, in weightpaint */
/* init trans data */
@@ -1285,6 +1389,15 @@ static void createTransPose(TransInfo *t)
for (bPoseChannel *pchan = ob->pose->chanbase.first; pchan; pchan = pchan->next) {
if (pchan->bone->flag & BONE_TRANSFORM) {
add_pose_transdata(t, pchan, ob, tc, td);
+
+ if (mirror) {
+ bPoseChannel *pchan_mirror = BKE_pose_channel_get_mirrored(ob->pose, pchan->name);
+ if (pchan_mirror) {
+ pose_mirror_info_init(&pid[pid_index], pchan_mirror, pchan, is_mirror_relative);
+ pid_index++;
+ }
+ }
+
td++;
}
}
@@ -1304,6 +1417,19 @@ static void createTransPose(TransInfo *t)
t->flag &= ~T_PROP_EDIT_ALL;
}
+void restoreMirrorPoseBones(TransDataContainer *tc)
+{
+ bPose *pose = tc->poseobj->pose;
+
+ if (!(pose->flag & POSE_MIRROR_EDIT)) {
+ return;
+ }
+
+ for (PoseInitData_Mirror *pid = tc->custom.type.data; pid->pchan; pid++) {
+ pose_mirror_info_restore(pid);
+ }
+}
+
void restoreBones(TransDataContainer *tc)
{
bArmature *arm;
@@ -9253,7 +9379,7 @@ void createTransData(bContext *C, TransInfo *t)
countAndCleanTransDataContainer(t);
if (t->data_len_all && t->flag & T_PROP_EDIT) {
- sort_trans_data(t); // makes selected become first in array
+ sort_trans_data_selected_first(t);
set_prop_dist(t, 1);
sort_trans_data_dist(t);
}
@@ -9267,7 +9393,7 @@ void createTransData(bContext *C, TransInfo *t)
countAndCleanTransDataContainer(t);
if (t->data_len_all && (t->flag & T_PROP_EDIT)) {
- sort_trans_data(t); // makes selected become first in array
+ sort_trans_data_selected_first(t);
set_prop_dist(t, 1);
sort_trans_data_dist(t);
}
@@ -9281,7 +9407,7 @@ void createTransData(bContext *C, TransInfo *t)
countAndCleanTransDataContainer(t);
if (t->data_len_all && (t->flag & T_PROP_EDIT)) {
- sort_trans_data(t); // makes selected become first in array
+ sort_trans_data_selected_first(t);
set_prop_dist(t, true);
sort_trans_data_dist(t);
}
@@ -9304,7 +9430,7 @@ void createTransData(bContext *C, TransInfo *t)
t->flag |= T_EDIT;
if (t->data_len_all && (t->flag & T_PROP_EDIT)) {
- sort_trans_data(t); // makes selected become first in array
+ sort_trans_data_selected_first(t);
set_prop_dist(t, 1);
sort_trans_data_dist(t);
}
@@ -9321,7 +9447,7 @@ void createTransData(bContext *C, TransInfo *t)
countAndCleanTransDataContainer(t);
if (t->data_len_all && (t->flag & T_PROP_EDIT)) {
- sort_trans_data(t); // makes selected become first in array
+ sort_trans_data_selected_first(t);
/* don't do that, distance has been set in createTransActionData already */
// set_prop_dist(t, false);
sort_trans_data_dist(t);
@@ -9351,7 +9477,7 @@ void createTransData(bContext *C, TransInfo *t)
if (t->data_len_all && (t->flag & T_PROP_EDIT)) {
/* makes selected become first in array */
- sort_trans_data(t);
+ sort_trans_data_selected_first(t);
/* don't do that, distance has been set in createTransGraphEditData already */
set_prop_dist(t, false);
@@ -9367,7 +9493,7 @@ void createTransData(bContext *C, TransInfo *t)
countAndCleanTransDataContainer(t);
if (t->data_len_all && (t->flag & T_PROP_EDIT)) {
- sort_trans_data(t); // makes selected become first in array
+ sort_trans_data_selected_first(t);
set_prop_dist(t, 1);
sort_trans_data_dist(t);
}
@@ -9386,7 +9512,7 @@ void createTransData(bContext *C, TransInfo *t)
countAndCleanTransDataContainer(t);
if (t->data_len_all && (t->flag & T_PROP_EDIT)) {
- sort_trans_data(t); // makes selected become first in array
+ sort_trans_data_selected_first(t);
set_prop_dist(t, true);
sort_trans_data_dist(t);
}
@@ -9426,21 +9552,30 @@ void createTransData(bContext *C, TransInfo *t)
t->flag |= T_EDIT | T_POINTS;
- if (t->data_len_all && t->flag & T_PROP_EDIT) {
- if (ELEM(t->obedit_type, OB_CURVE, OB_MESH)) {
- sort_trans_data(t); // makes selected become first in array
- if ((t->obedit_type == OB_MESH) && (t->flag & T_PROP_CONNECTED)) {
- /* already calculated by editmesh_set_connectivity_distance */
+ if (t->data_len_all) {
+ if (t->flag & T_PROP_EDIT) {
+ if (ELEM(t->obedit_type, OB_CURVE, OB_MESH)) {
+ sort_trans_data_selected_first(t);
+ if ((t->obedit_type == OB_MESH) && (t->flag & T_PROP_CONNECTED)) {
+ /* already calculated by editmesh_set_connectivity_distance */
+ }
+ else {
+ set_prop_dist(t, 0);
+ }
+ sort_trans_data_dist(t);
}
else {
- set_prop_dist(t, 0);
+ sort_trans_data_selected_first(t);
+ set_prop_dist(t, 1);
+ sort_trans_data_dist(t);
}
- sort_trans_data_dist(t);
}
else {
- sort_trans_data(t); // makes selected become first in array
- set_prop_dist(t, 1);
- sort_trans_data_dist(t);
+ if (ELEM(t->obedit_type, OB_CURVE)) {
+ /* Needed because bezier handles can be partially selected
+ * and are still added into transform data. */
+ sort_trans_data_selected_first(t);
+ }
}
}
@@ -9494,7 +9629,7 @@ void createTransData(bContext *C, TransInfo *t)
t->flag |= T_POINTS;
if (t->data_len_all && t->flag & T_PROP_EDIT) {
- sort_trans_data(t); // makes selected become first in array
+ sort_trans_data_selected_first(t);
set_prop_dist(t, 1);
sort_trans_data_dist(t);
}
diff --git a/source/blender/editors/transform/transform_generics.c b/source/blender/editors/transform/transform_generics.c
index 8ddc5461e9a..758551be0b5 100644
--- a/source/blender/editors/transform/transform_generics.c
+++ b/source/blender/editors/transform/transform_generics.c
@@ -781,6 +781,49 @@ static void recalcData_spaceclip(TransInfo *t)
}
}
+/**
+ * if pose bone (partial) selected, copy data.
+ * context; posemode armature, with mirror editing enabled.
+ *
+ * \param pid: Optional, apply relative transform when set.
+ */
+static void pose_transform_mirror_update(Object *ob, PoseInitData_Mirror *pid)
+{
+ float flip_mtx[4][4];
+ unit_m4(flip_mtx);
+ flip_mtx[0][0] = -1;
+
+ for (bPoseChannel *pchan_orig = ob->pose->chanbase.first; pchan_orig;
+ pchan_orig = pchan_orig->next) {
+ /* no layer check, correct mirror is more important */
+ if (pchan_orig->bone->flag & BONE_TRANSFORM) {
+ bPoseChannel *pchan = BKE_pose_channel_get_mirrored(ob->pose, pchan_orig->name);
+
+ if (pchan) {
+ /* also do bbone scaling */
+ pchan->bone->xwidth = pchan_orig->bone->xwidth;
+ pchan->bone->zwidth = pchan_orig->bone->zwidth;
+
+ /* we assume X-axis flipping for now */
+ pchan->curve_in_x = pchan_orig->curve_in_x * -1;
+ pchan->curve_out_x = pchan_orig->curve_out_x * -1;
+ pchan->roll1 = pchan_orig->roll1 * -1; // XXX?
+ pchan->roll2 = pchan_orig->roll2 * -1; // XXX?
+
+ float pchan_mtx_final[4][4];
+ BKE_pchan_to_mat4(pchan_orig, pchan_mtx_final);
+ mul_m4_m4m4(pchan_mtx_final, pchan_mtx_final, flip_mtx);
+ mul_m4_m4m4(pchan_mtx_final, flip_mtx, pchan_mtx_final);
+ if (pid) {
+ mul_m4_m4m4(pchan_mtx_final, pid->offset_mtx, pchan_mtx_final);
+ pid++;
+ }
+ BKE_pchan_apply_mat4(pchan, pchan_mtx_final, false);
+ }
+ }
+ }
+}
+
/* helper for recalcData() - for object transforms, typically in the 3D view */
static void recalcData_objects(TransInfo *t)
{
@@ -975,12 +1018,22 @@ static void recalcData_objects(TransInfo *t)
FOREACH_TRANS_DATA_CONTAINER (t, tc) {
Object *ob = tc->poseobj;
bArmature *arm = ob->data;
- if (arm->flag & ARM_MIRROR_EDIT) {
- if (t->state != TRANS_CANCEL) {
- ED_armature_edit_transform_mirror_update(ob);
+ if (ob->mode == OB_MODE_EDIT) {
+ if (arm->flag & ARM_MIRROR_EDIT) {
+ if (t->state != TRANS_CANCEL) {
+ ED_armature_edit_transform_mirror_update(ob);
+ }
+ else {
+ restoreBones(tc);
+ }
}
- else {
- restoreBones(tc);
+ }
+ else if (ob->mode == OB_MODE_POSE) {
+ /* actually support TFM_BONESIZE in posemode as well */
+ DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY);
+ bPose *pose = ob->pose;
+ if (arm->flag & ARM_MIRROR_EDIT || pose->flag & POSE_MIRROR_EDIT) {
+ pose_transform_mirror_update(ob, NULL);
}
}
}
@@ -991,6 +1044,20 @@ static void recalcData_objects(TransInfo *t)
FOREACH_TRANS_DATA_CONTAINER (t, tc) {
Object *ob = tc->poseobj;
bArmature *arm = ob->data;
+ bPose *pose = ob->pose;
+
+ if (pose->flag & POSE_MIRROR_EDIT) {
+ if (t->state != TRANS_CANCEL) {
+ PoseInitData_Mirror *pid = NULL;
+ if (pose->flag & POSE_MIRROR_RELATIVE) {
+ pid = tc->custom.type.data;
+ }
+ pose_transform_mirror_update(ob, pid);
+ }
+ else {
+ restoreMirrorPoseBones(tc);
+ }
+ }
/* if animtimer is running, and the object already has animation data,
* check if the auto-record feature means that we should record 'samples'
@@ -1309,7 +1376,9 @@ void initTransDataContainers_FromObjectData(TransInfo *t,
BLI_assert((t->flag & T_2D_EDIT) == 0);
copy_m4_m4(tc->mat, objects[i]->obmat);
copy_m3_m4(tc->mat3, tc->mat);
- invert_m4_m4(tc->imat, tc->mat);
+ /* for non-invertible scale matrices, invert_m4_m4_fallback()
+ * can still provide a valid pivot */
+ invert_m4_m4_fallback(tc->imat, tc->mat);
invert_m3_m3(tc->imat3, tc->mat3);
normalize_m3_m3(tc->mat3_unit, tc->mat3);
}
diff --git a/source/blender/editors/transform/transform_gizmo_3d.c b/source/blender/editors/transform/transform_gizmo_3d.c
index 50610f1b3da..e43379dc358 100644
--- a/source/blender/editors/transform/transform_gizmo_3d.c
+++ b/source/blender/editors/transform/transform_gizmo_3d.c
@@ -703,7 +703,7 @@ void ED_transform_calc_orientation_from_type_ex(const bContext *C,
break;
}
case V3D_ORIENT_CURSOR: {
- ED_view3d_cursor3d_calc_mat3(scene, r_mat);
+ BKE_scene_cursor_rot_to_mat3(&scene->cursor, r_mat);
ok = true;
break;
}
@@ -1762,6 +1762,15 @@ static void WIDGETGROUP_gizmo_refresh(const bContext *C, wmGizmoGroup *gzgroup)
}
}
MAN_ITER_AXES_END;
+
+ /* Ensure rotate disks don't overlap scale arrows, especially in ortho view. */
+ float rotate_select_bias = 0.0f;
+ if ((ggd->twtype & V3D_GIZMO_SHOW_OBJECT_SCALE) && ggd->twtype & V3D_GIZMO_SHOW_OBJECT_ROTATE) {
+ rotate_select_bias = -2.0f;
+ }
+ for (int i = MAN_AXIS_RANGE_ROT_START; i < MAN_AXIS_RANGE_ROT_END; i++) {
+ ggd->gizmos[i]->select_bias = rotate_select_bias;
+ }
}
static void WIDGETGROUP_gizmo_message_subscribe(const bContext *C,
diff --git a/source/blender/editors/transform/transform_ops.c b/source/blender/editors/transform/transform_ops.c
index 8606cd19c96..cdd0896ab66 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);
diff --git a/source/blender/editors/transform/transform_orientations.c b/source/blender/editors/transform/transform_orientations.c
index e16579aba64..70bb2bf98a6 100644
--- a/source/blender/editors/transform/transform_orientations.c
+++ b/source/blender/editors/transform/transform_orientations.c
@@ -485,7 +485,7 @@ void initTransformOrientation(bContext *C, TransInfo *t)
break;
case V3D_ORIENT_CURSOR: {
BLI_strncpy(t->spacename, IFACE_("cursor"), sizeof(t->spacename));
- ED_view3d_cursor3d_calc_mat3(t->scene, t->spacemtx);
+ BKE_scene_cursor_rot_to_mat3(&t->scene->cursor, t->spacemtx);
break;
}
case V3D_ORIENT_CUSTOM_MATRIX:
diff --git a/source/blender/editors/undo/ed_undo.c b/source/blender/editors/undo/ed_undo.c
index 49b5cada04a..99143cd71f9 100644
--- a/source/blender/editors/undo/ed_undo.c
+++ b/source/blender/editors/undo/ed_undo.c
@@ -392,6 +392,15 @@ static bool ed_undo_redo_poll(bContext *C)
WM_operator_check_ui_enabled(C, last_op->type->name));
}
+static bool ed_undo_poll(bContext *C)
+{
+ if (!ed_undo_is_init_and_screenactive_poll(C)) {
+ return false;
+ }
+ UndoStack *undo_stack = CTX_wm_manager(C)->undo_stack;
+ return (undo_stack->step_active != NULL) && (undo_stack->step_active->prev != NULL);
+}
+
void ED_OT_undo(wmOperatorType *ot)
{
/* identifiers */
@@ -401,7 +410,7 @@ void ED_OT_undo(wmOperatorType *ot)
/* api callbacks */
ot->exec = ed_undo_exec;
- ot->poll = ed_undo_is_init_and_screenactive_poll;
+ ot->poll = ed_undo_poll;
}
void ED_OT_undo_push(wmOperatorType *ot)
@@ -426,6 +435,15 @@ void ED_OT_undo_push(wmOperatorType *ot)
"");
}
+static bool ed_redo_poll(bContext *C)
+{
+ if (!ed_undo_is_init_and_screenactive_poll(C)) {
+ return false;
+ }
+ UndoStack *undo_stack = CTX_wm_manager(C)->undo_stack;
+ return (undo_stack->step_active != NULL) && (undo_stack->step_active->next != NULL);
+}
+
void ED_OT_redo(wmOperatorType *ot)
{
/* identifiers */
@@ -435,7 +453,7 @@ void ED_OT_redo(wmOperatorType *ot)
/* api callbacks */
ot->exec = ed_redo_exec;
- ot->poll = ed_undo_is_init_and_screenactive_poll;
+ ot->poll = ed_redo_poll;
}
void ED_OT_undo_redo(wmOperatorType *ot)
@@ -569,7 +587,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;
@@ -633,6 +651,16 @@ static int undo_history_exec(bContext *C, wmOperator *op)
return OPERATOR_CANCELLED;
}
+static bool undo_history_poll(bContext *C)
+{
+ if (!ed_undo_is_init_and_screenactive_poll(C)) {
+ return false;
+ }
+ UndoStack *undo_stack = CTX_wm_manager(C)->undo_stack;
+ /* more than just original state entry */
+ return BLI_listbase_count_at_most(&undo_stack->steps, 2) > 1;
+}
+
void ED_OT_undo_history(wmOperatorType *ot)
{
/* identifiers */
@@ -643,7 +671,7 @@ void ED_OT_undo_history(wmOperatorType *ot)
/* api callbacks */
ot->invoke = undo_history_invoke;
ot->exec = undo_history_exec;
- ot->poll = ed_undo_is_init_and_screenactive_poll;
+ ot->poll = undo_history_poll;
RNA_def_int(ot->srna, "item", 0, 0, INT_MAX, "Item", "", 0, INT_MAX);
}
diff --git a/source/blender/editors/util/CMakeLists.txt b/source/blender/editors/util/CMakeLists.txt
index 3b49784d5eb..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,11 +80,13 @@ 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
../include/ED_space_api.h
../include/ED_text.h
+ ../include/ED_time_scrub_ui.h
../include/ED_transform.h
../include/ED_transform_snap_object_context.h
../include/ED_transverts.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 804b9c22104..7f9b90f4496 100644
--- a/source/blender/editors/uvedit/uvedit_draw.c
+++ b/source/blender/editors/uvedit/uvedit_draw.c
@@ -170,6 +170,7 @@ static void uvedit_get_batches(Object *ob,
const bool draw_stretch = (sima->flag & SI_DRAW_STRETCH) != 0;
const bool draw_faces = (sima->flag & SI_NO_DRAWFACES) == 0;
+ DRW_mesh_batch_cache_validate(ob->data);
*edges = DRW_mesh_batch_cache_get_edituv_edges(ob->data);
*verts = DRW_mesh_batch_cache_get_edituv_verts(ob->data);
@@ -206,6 +207,7 @@ static void draw_uvs_shadow(SpaceImage *UNUSED(sima),
float col[4];
UI_GetThemeColor4fv(TH_UV_SHADOW, col);
+ DRW_mesh_batch_cache_validate(me);
GPUBatch *edges = DRW_mesh_batch_cache_get_uv_edges(me);
DRW_mesh_batch_cache_create_requested(eval_ob, me, scene->toolsettings, false, false);
@@ -228,6 +230,7 @@ static void draw_uvs_texpaint(Scene *scene, Object *ob, Depsgraph *depsgraph)
return;
}
+ DRW_mesh_batch_cache_validate(me);
GPUBatch *geom = DRW_mesh_batch_cache_get_uv_edges(me);
DRW_mesh_batch_cache_create_requested(eval_ob, me, scene->toolsettings, false, false);
@@ -243,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.
@@ -251,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;
@@ -261,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/editors/uvedit/uvedit_unwrap_ops.c b/source/blender/editors/uvedit/uvedit_unwrap_ops.c
index 85393925802..717bc347cf7 100644
--- a/source/blender/editors/uvedit/uvedit_unwrap_ops.c
+++ b/source/blender/editors/uvedit/uvedit_unwrap_ops.c
@@ -386,6 +386,10 @@ static ParamHandle *construct_param_handle_multi(Scene *scene,
const int cd_loop_uv_offset = CustomData_get_offset(&bm->ldata, CD_MLOOPUV);
+ if (cd_loop_uv_offset == -1) {
+ continue;
+ }
+
BM_ITER_MESH_INDEX (efa, &iter, bm, BM_FACES_OF_MESH, i) {
if ((BM_elem_flag_test(efa, BM_ELEM_HIDDEN)) ||
diff --git a/source/blender/freestyle/intern/blender_interface/BlenderFileLoader.cpp b/source/blender/freestyle/intern/blender_interface/BlenderFileLoader.cpp
index 06a356dd232..ee13583e67a 100644
--- a/source/blender/freestyle/intern/blender_interface/BlenderFileLoader.cpp
+++ b/source/blender/freestyle/intern/blender_interface/BlenderFileLoader.cpp
@@ -23,6 +23,7 @@
#include "BLI_utildefines.h"
#include "BKE_global.h"
+#include "BKE_object.h"
#include <sstream>
@@ -98,14 +99,11 @@ NodeGroup *BlenderFileLoader::Load()
continue;
}
- bool apply_modifiers = false;
- bool calc_undeformed = false;
- Mesh *mesh = BKE_mesh_new_from_object(
- _depsgraph, _re->main, _re->scene, ob, apply_modifiers, calc_undeformed);
+ Mesh *mesh = BKE_object_to_mesh(ob);
if (mesh) {
insertShapeNode(ob, mesh, ++id);
- BKE_id_free_ex(_re->main, &mesh->id, LIB_ID_FREE_NO_UI_USER, true);
+ BKE_object_to_mesh_clear(ob);
}
}
DEG_OBJECT_ITER_END;
diff --git a/source/blender/freestyle/intern/blender_interface/BlenderStrokeRenderer.cpp b/source/blender/freestyle/intern/blender_interface/BlenderStrokeRenderer.cpp
index 082ed34c353..8a3cdd575fe 100644
--- a/source/blender/freestyle/intern/blender_interface/BlenderStrokeRenderer.cpp
+++ b/source/blender/freestyle/intern/blender_interface/BlenderStrokeRenderer.cpp
@@ -125,13 +125,6 @@ BlenderStrokeRenderer::BlenderStrokeRenderer(Render *re, int render_count) : Str
/* Render with transparent background. */
freestyle_scene->r.alphamode = R_ALPHAPREMUL;
- if (STREQ(freestyle_scene->r.engine, RE_engine_id_CYCLES)) {
- PointerRNA freestyle_scene_ptr;
- RNA_id_pointer_create(&freestyle_scene->id, &freestyle_scene_ptr);
- PointerRNA freestyle_cycles_ptr = RNA_pointer_get(&freestyle_scene_ptr, "cycles");
- RNA_boolean_set(&freestyle_cycles_ptr, "film_transparent", 1);
- }
-
if (G.debug & G_DEBUG_FREESTYLE) {
printf("%s: %d thread(s)\n", __func__, BKE_render_num_threads(&freestyle_scene->r));
}
@@ -270,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/freestyle/intern/geometry/Noise.cpp b/source/blender/freestyle/intern/geometry/Noise.cpp
index 09c29025d15..8b81660fd58 100644
--- a/source/blender/freestyle/intern/geometry/Noise.cpp
+++ b/source/blender/freestyle/intern/geometry/Noise.cpp
@@ -24,6 +24,9 @@
#include <stdlib.h>
#include <time.h>
+#include "BLI_compiler_attrs.h"
+#include "BLI_rand.h"
+
#include "Noise.h"
namespace Freestyle {
@@ -40,9 +43,7 @@ namespace Freestyle {
((s) * (RTable[m] * 0.5 + RTable[m + 1] * (x) + RTable[m + 2] * (y) + RTable[m + 3] * (z)))
# define MAXSIZE 500
-# define NRAND() ((float)rand() / (float)RAND_MAX)
#endif
-#define SEEDNRAND(x) (srand(x * RAND_MAX))
#define BM 0xff
#define N 0x1000
@@ -236,25 +237,26 @@ float Noise::smoothNoise3(Vec3f &vec)
Noise::Noise(long seed)
{
+ /* Use Blender RNG for repeatable results across platforms. */
+ RNG *rng = BLI_rng_new(seed);
int i, j, k;
- SEEDNRAND((seed < 0) ? time(NULL) : seed);
for (i = 0; i < _NOISE_B; i++) {
p[i] = i;
- g1[i] = (float)((rand() % (_NOISE_B + _NOISE_B)) - _NOISE_B) / _NOISE_B;
+ g1[i] = (float)((BLI_rng_get_int(rng) % (_NOISE_B + _NOISE_B)) - _NOISE_B) / _NOISE_B;
for (j = 0; j < 2; j++)
- g2[i][j] = (float)((rand() % (_NOISE_B + _NOISE_B)) - _NOISE_B) / _NOISE_B;
+ g2[i][j] = (float)((BLI_rng_get_int(rng) % (_NOISE_B + _NOISE_B)) - _NOISE_B) / _NOISE_B;
normalize2(g2[i]);
for (j = 0; j < 3; j++)
- g3[i][j] = (float)((rand() % (_NOISE_B + _NOISE_B)) - _NOISE_B) / _NOISE_B;
+ g3[i][j] = (float)((BLI_rng_get_int(rng) % (_NOISE_B + _NOISE_B)) - _NOISE_B) / _NOISE_B;
normalize3(g3[i]);
}
while (--i) {
k = p[i];
- p[i] = p[j = rand() % _NOISE_B];
+ p[i] = p[j = BLI_rng_get_int(rng) % _NOISE_B];
p[j] = k;
}
@@ -268,6 +270,8 @@ Noise::Noise(long seed)
for (j = 0; j < 3; j++)
g3[_NOISE_B + i][j] = g3[i][j];
}
+
+ BLI_rng_free(rng);
}
} /* namespace Freestyle */
diff --git a/source/blender/freestyle/intern/system/RandGen.cpp b/source/blender/freestyle/intern/system/RandGen.cpp
index 77eb9a8c10a..719287b102f 100644
--- a/source/blender/freestyle/intern/system/RandGen.cpp
+++ b/source/blender/freestyle/intern/system/RandGen.cpp
@@ -49,7 +49,8 @@ namespace Freestyle {
long l = (long)(x) * (long)(y); \
(z)[0] = LOW(l); \
(z)[1] = HIGH(l); \
- }
+ } \
+ ((void)0)
#define CARRY(x, y) ((unsigned long)((long)(x) + (long)(y)) > MASK)
#define ADDEQU(x, y, z) (z = CARRY(x, (y)), x = LOW(x + (y)))
diff --git a/source/blender/gpu/CMakeLists.txt b/source/blender/gpu/CMakeLists.txt
index 5a42c4d3d1b..f30eff1484b 100644
--- a/source/blender/gpu/CMakeLists.txt
+++ b/source/blender/gpu/CMakeLists.txt
@@ -178,7 +178,6 @@ data_to_c_simple(shaders/gpu_shader_3D_image_vert.glsl SRC)
data_to_c_simple(shaders/gpu_shader_3D_vert.glsl SRC)
data_to_c_simple(shaders/gpu_shader_3D_normal_vert.glsl SRC)
data_to_c_simple(shaders/gpu_shader_3D_flat_color_vert.glsl SRC)
-data_to_c_simple(shaders/gpu_shader_3D_line_dashed_uniform_color_legacy_vert.glsl SRC)
data_to_c_simple(shaders/gpu_shader_3D_line_dashed_uniform_color_vert.glsl SRC)
data_to_c_simple(shaders/gpu_shader_3D_smooth_color_vert.glsl SRC)
data_to_c_simple(shaders/gpu_shader_3D_normal_smooth_color_vert.glsl SRC)
@@ -225,14 +224,6 @@ data_to_c_simple(shaders/gpu_shader_2D_edituvs_stretch_vert.glsl SRC)
data_to_c_simple(shaders/gpu_shader_3D_selection_id_vert.glsl SRC)
data_to_c_simple(shaders/gpu_shader_selection_id_frag.glsl SRC)
-data_to_c_simple(shaders/gpu_shader_edges_front_back_persp_vert.glsl SRC)
-data_to_c_simple(shaders/gpu_shader_edges_front_back_persp_geom.glsl SRC)
-data_to_c_simple(shaders/gpu_shader_edges_front_back_persp_legacy_vert.glsl SRC)
-data_to_c_simple(shaders/gpu_shader_edges_front_back_ortho_vert.glsl SRC)
-data_to_c_simple(shaders/gpu_shader_edges_overlay_vert.glsl SRC)
-data_to_c_simple(shaders/gpu_shader_edges_overlay_geom.glsl SRC)
-data_to_c_simple(shaders/gpu_shader_edges_overlay_simple_geom.glsl SRC)
-data_to_c_simple(shaders/gpu_shader_edges_overlay_frag.glsl SRC)
data_to_c_simple(shaders/gpu_shader_text_simple_vert.glsl SRC)
data_to_c_simple(shaders/gpu_shader_text_simple_geom.glsl SRC)
data_to_c_simple(shaders/gpu_shader_text_vert.glsl SRC)
diff --git a/source/blender/gpu/GPU_batch.h b/source/blender/gpu/GPU_batch.h
index 856148563f2..3b0d72831c0 100644
--- a/source/blender/gpu/GPU_batch.h
+++ b/source/blender/gpu/GPU_batch.h
@@ -33,6 +33,7 @@
#include "GPU_shader.h"
typedef enum {
+ GPU_BATCH_UNUSED,
GPU_BATCH_READY_TO_FORMAT,
GPU_BATCH_READY_TO_BUILD,
GPU_BATCH_BUILDING,
@@ -131,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);
@@ -147,8 +148,10 @@ 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_buffers.h b/source/blender/gpu/GPU_buffers.h
index 20047174bb1..9009c134837 100644
--- a/source/blender/gpu/GPU_buffers.h
+++ b/source/blender/gpu/GPU_buffers.h
@@ -32,10 +32,10 @@ struct CCGKey;
struct DMFlagMat;
struct GSet;
struct MLoop;
+struct MLoopCol;
struct MLoopTri;
struct MPoly;
struct MVert;
-struct MLoopCol;
struct PBVH;
/* Buffers for drawing from PBVH grids. */
@@ -88,10 +88,9 @@ void GPU_pbvh_grid_buffers_update(GPU_PBVH_Buffers *buffers,
/* draw */
struct GPUBatch *GPU_pbvh_buffers_batch_get(GPU_PBVH_Buffers *buffers, bool fast, bool wires);
-bool GPU_pbvh_buffers_has_mask(GPU_PBVH_Buffers *buffers);
+short GPU_pbvh_buffers_material_index_get(GPU_PBVH_Buffers *buffers);
-/* debug PBVH draw */
-void GPU_pbvh_BB_draw(float min[3], float max[3], bool leaf, unsigned int pos);
+bool GPU_pbvh_buffers_has_mask(GPU_PBVH_Buffers *buffers);
void GPU_pbvh_buffers_free(GPU_PBVH_Buffers *buffers);
diff --git a/source/blender/gpu/GPU_draw.h b/source/blender/gpu/GPU_draw.h
index 300fc7c65a2..8b830aadbba 100644
--- a/source/blender/gpu/GPU_draw.h
+++ b/source/blender/gpu/GPU_draw.h
@@ -84,17 +84,13 @@ void GPU_create_gl_tex(unsigned int *bind,
int recth,
int textarget,
bool mipmap,
- bool use_hight_bit_depth,
+ bool use_srgb,
struct Image *ima);
void GPU_create_gl_tex_compressed(unsigned int *bind,
- unsigned int *pix,
- int x,
- int y,
- int mipmap,
int textarget,
struct Image *ima,
struct ImBuf *ibuf);
-bool GPU_upload_dxt_texture(struct ImBuf *ibuf);
+bool GPU_upload_dxt_texture(struct ImBuf *ibuf, bool use_srgb);
void GPU_free_image(struct Image *ima);
void GPU_free_images(struct Main *bmain);
void GPU_free_images_anim(struct Main *bmain);
diff --git a/source/blender/gpu/GPU_material.h b/source/blender/gpu/GPU_material.h
index da61dc76422..dd5292d9c58 100644
--- a/source/blender/gpu/GPU_material.h
+++ b/source/blender/gpu/GPU_material.h
@@ -107,7 +107,7 @@ typedef enum eGPUBuiltin {
GPU_VOLUME_TEMPERATURE = (1 << 18),
GPU_BARYCENTRIC_TEXCO = (1 << 19),
GPU_BARYCENTRIC_DIST = (1 << 20),
- GPU_INVERSE_NORMAL_MATRIX = (1 << 21),
+ GPU_WORLD_NORMAL = (1 << 21),
} eGPUBuiltin;
typedef enum eGPUMatFlag {
@@ -145,7 +145,7 @@ typedef enum eGPUMaterialStatus {
GPUNodeLink *GPU_attribute(CustomDataType type, const char *name);
GPUNodeLink *GPU_constant(float *num);
GPUNodeLink *GPU_uniform(float *num);
-GPUNodeLink *GPU_image(struct Image *ima, struct ImageUser *iuser, bool is_data);
+GPUNodeLink *GPU_image(struct Image *ima, struct ImageUser *iuser);
GPUNodeLink *GPU_color_band(GPUMaterial *mat, int size, float *pixels, float *layer);
GPUNodeLink *GPU_builtin(eGPUBuiltin builtin);
@@ -177,6 +177,7 @@ GPUMaterial *GPU_material_from_nodetree_find(struct ListBase *gpumaterials,
const void *engine_type,
int options);
GPUMaterial *GPU_material_from_nodetree(struct Scene *scene,
+ struct Material *ma,
struct bNodeTree *ntree,
struct ListBase *gpumaterials,
const void *engine_type,
@@ -194,6 +195,7 @@ void GPU_materials_free(struct Main *bmain);
struct Scene *GPU_material_scene(GPUMaterial *material);
struct GPUPass *GPU_material_get_pass(GPUMaterial *material);
struct ListBase *GPU_material_get_inputs(GPUMaterial *material);
+struct Material *GPU_material_get_material(GPUMaterial *material);
eGPUMaterialStatus GPU_material_status(GPUMaterial *mat);
struct GPUUniformBuffer *GPU_material_uniform_buffer_get(GPUMaterial *material);
@@ -202,7 +204,6 @@ struct GPUUniformBuffer *GPU_material_create_sss_profile_ubo(void);
void GPU_material_vertex_attrs(GPUMaterial *material, struct GPUVertAttrLayers *attrs);
-bool GPU_material_do_color_management(GPUMaterial *mat);
bool GPU_material_use_domain_surface(GPUMaterial *mat);
bool GPU_material_use_domain_volume(GPUMaterial *mat);
diff --git a/source/blender/gpu/GPU_matrix.h b/source/blender/gpu/GPU_matrix.h
index 67fb2bb2bd4..6f7d25dafa7 100644
--- a/source/blender/gpu/GPU_matrix.h
+++ b/source/blender/gpu/GPU_matrix.h
@@ -106,6 +106,11 @@ bool GPU_matrix_unproject(const float win[3],
const float proj[4][4],
const int view[4],
float world[3]);
+void GPU_matrix_unproject_model_inverted(const float win[3],
+ const float model_inverted[4][4],
+ const float proj[4][4],
+ const int view[4],
+ float world[3]);
/* 2D Projection Matrix */
diff --git a/source/blender/gpu/GPU_shader.h b/source/blender/gpu/GPU_shader.h
index d174aafacce..00570bd7ebc 100644
--- a/source/blender/gpu/GPU_shader.h
+++ b/source/blender/gpu/GPU_shader.h
@@ -100,10 +100,6 @@ typedef enum eGPUBuiltinShader {
/* specialized drawing */
GPU_SHADER_TEXT,
GPU_SHADER_TEXT_SIMPLE,
- GPU_SHADER_EDGES_FRONT_BACK_PERSP,
- GPU_SHADER_EDGES_FRONT_BACK_ORTHO,
- GPU_SHADER_EDGES_OVERLAY_SIMPLE,
- GPU_SHADER_EDGES_OVERLAY,
GPU_SHADER_KEYFRAME_DIAMOND,
GPU_SHADER_SIMPLE_LIGHTING,
GPU_SHADER_SIMPLE_LIGHTING_FLAT_COLOR,
@@ -402,10 +398,7 @@ void GPU_shader_free_builtin_shaders(void);
typedef struct GPUVertAttrLayers {
struct {
- int type;
- int glindex;
- int glinfoindoex;
- int gltexco;
+ int type; /* CustomDataType */
int attr_id;
char name[64]; /* MAX_CUSTOMDATA_LAYER_NAME */
} layer[GPU_MAX_ATTR];
diff --git a/source/blender/gpu/GPU_shader_interface.h b/source/blender/gpu/GPU_shader_interface.h
index ace8832303b..441f7290cc5 100644
--- a/source/blender/gpu/GPU_shader_interface.h
+++ b/source/blender/gpu/GPU_shader_interface.h
@@ -44,14 +44,10 @@ typedef enum {
GPU_UNIFORM_PROJECTION_INV, /* mat4 ProjectionMatrixInverse */
GPU_UNIFORM_VIEWPROJECTION_INV, /* mat4 ViewProjectionMatrixInverse */
- GPU_UNIFORM_NORMAL, /* mat3 NormalMatrix */
- GPU_UNIFORM_NORMAL_INV, /* mat3 NormalMatrixInverse */
- GPU_UNIFORM_WORLDNORMAL, /* mat3 WorldNormalMatrix */
- GPU_UNIFORM_CAMERATEXCO, /* vec4 CameraTexCoFactors */
- GPU_UNIFORM_ORCO, /* vec3 OrcoTexCoFactors[] */
+ GPU_UNIFORM_NORMAL, /* mat3 NormalMatrix */
+ GPU_UNIFORM_ORCO, /* vec3 OrcoTexCoFactors[] */
GPU_UNIFORM_COLOR, /* vec4 color */
- GPU_UNIFORM_EYE, /* vec3 eye */
GPU_UNIFORM_CALLID, /* int callId */
GPU_UNIFORM_OBJECT_INFO, /* vec3 objectInfo */
diff --git a/source/blender/gpu/GPU_texture.h b/source/blender/gpu/GPU_texture.h
index 3527398a396..3fb7dfc6331 100644
--- a/source/blender/gpu/GPU_texture.h
+++ b/source/blender/gpu/GPU_texture.h
@@ -186,10 +186,7 @@ GPUTexture *GPU_texture_create_from_vertbuf(struct GPUVertBuf *vert);
GPUTexture *GPU_texture_create_buffer(eGPUTextureFormat data_type, const uint buffer);
GPUTexture *GPU_texture_from_bindcode(int textarget, int bindcode);
-GPUTexture *GPU_texture_from_blender(struct Image *ima,
- struct ImageUser *iuser,
- int textarget,
- bool is_data);
+GPUTexture *GPU_texture_from_blender(struct Image *ima, struct ImageUser *iuser, int textarget);
GPUTexture *GPU_texture_from_preview(struct PreviewImage *prv, int mipmap);
void GPU_texture_add_mipmap(GPUTexture *tex,
diff --git a/source/blender/gpu/GPU_vertex_buffer.h b/source/blender/gpu/GPU_vertex_buffer.h
index 6d88460964d..3e178e193dc 100644
--- a/source/blender/gpu/GPU_vertex_buffer.h
+++ b/source/blender/gpu/GPU_vertex_buffer.h
@@ -48,12 +48,17 @@ typedef enum {
typedef struct GPUVertBuf {
GPUVertFormat format;
- uint vertex_len; /* number of verts we want to draw */
- uint vertex_alloc; /* number of verts data */
- bool dirty;
+ /** Number of verts we want to draw. */
+ uint vertex_len;
+ /** Number of verts data. */
+ uint vertex_alloc;
+ /** 0 indicates not yet allocated. */
+ uint32_t vbo_id;
+ /** Usage hint for GL optimisation. */
+ uint usage : 2;
+ /** Data has been touched and need to be reuploaded to GPU. */
+ uint dirty : 1;
unsigned char *data; /* NULL indicates data in VRAM (unmapped) */
- uint32_t vbo_id; /* 0 indicates not yet allocated */
- GPUUsageType usage; /* usage hint for GL optimisation */
} GPUVertBuf;
GPUVertBuf *GPU_vertbuf_create(GPUUsageType);
@@ -62,6 +67,7 @@ GPUVertBuf *GPU_vertbuf_create_with_format_ex(const GPUVertFormat *, GPUUsageTyp
#define GPU_vertbuf_create_with_format(format) \
GPU_vertbuf_create_with_format_ex(format, GPU_USAGE_STATIC)
+void GPU_vertbuf_clear(GPUVertBuf *verts);
void GPU_vertbuf_discard(GPUVertBuf *);
void GPU_vertbuf_init(GPUVertBuf *, GPUUsageType);
diff --git a/source/blender/gpu/GPU_vertex_format.h b/source/blender/gpu/GPU_vertex_format.h
index 7f1934431cf..43eec55bca2 100644
--- a/source/blender/gpu/GPU_vertex_format.h
+++ b/source/blender/gpu/GPU_vertex_format.h
@@ -27,6 +27,8 @@
#define __GPU_VERTEX_FORMAT_H__
#include "GPU_common.h"
+#include "BLI_compiler_compat.h"
+#include "BLI_assert.h"
#define GPU_VERT_ATTR_MAX_LEN 16
#define GPU_VERT_ATTR_MAX_NAMES 4
@@ -54,28 +56,41 @@ typedef enum {
} GPUVertFetchMode;
typedef struct GPUVertAttr {
- GPUVertFetchMode fetch_mode;
- GPUVertCompType comp_type;
+ uint fetch_mode : 2;
+ uint comp_type : 3;
+ /* 1 to 4 or 8 or 12 or 16 */
+ uint comp_len : 5;
+ /* size in bytes, 1 to 64 */
+ uint sz : 7;
+ /* from beginning of vertex, in bytes */
+ uint offset : 11;
+ /* up to GPU_VERT_ATTR_MAX_NAMES */
+ uint name_len : 3;
uint gl_comp_type;
- uint comp_len; /* 1 to 4 or 8 or 12 or 16 */
- uint sz; /* size in bytes, 1 to 64 */
- uint offset; /* from beginning of vertex, in bytes */
- uint name_len; /* up to GPU_VERT_ATTR_MAX_NAMES */
- const char *name[GPU_VERT_ATTR_MAX_NAMES];
+ /* -- 8 Bytes -- */
+ uchar names[GPU_VERT_ATTR_MAX_NAMES];
} GPUVertAttr;
+BLI_STATIC_ASSERT(GPU_VERT_ATTR_NAMES_BUF_LEN <= 256,
+ "We use uchar as index inside the name buffer "
+ "so GPU_VERT_ATTR_NAMES_BUF_LEN needs to be be "
+ "smaller than GPUVertFormat->name_offset and "
+ "GPUVertAttr->names maximum value");
+
typedef struct GPUVertFormat {
/** 0 to 16 (GPU_VERT_ATTR_MAX_LEN). */
- uint attr_len;
+ uint attr_len : 5;
/** Total count of active vertex attribute. */
- uint name_len;
- /** Stride in bytes, 1 to 256. */
- uint stride;
- uint name_offset;
- bool packed;
- char names[GPU_VERT_ATTR_NAMES_BUF_LEN];
- /** TODO: variable-size array */
+ uint name_len : 5;
+ /** Stride in bytes, 1 to 1024. */
+ uint stride : 11;
+ /** Has the format been packed. */
+ uint packed : 1;
+ /** Current offset in names[]. */
+ uint name_offset : 8;
+
GPUVertAttr attrs[GPU_VERT_ATTR_MAX_LEN];
+ char names[GPU_VERT_ATTR_NAMES_BUF_LEN];
} GPUVertFormat;
struct GPUShaderInterface;
@@ -88,18 +103,15 @@ void GPU_vertformat_from_interface(GPUVertFormat *format,
uint GPU_vertformat_attr_add(
GPUVertFormat *, const char *name, GPUVertCompType, uint comp_len, GPUVertFetchMode);
void GPU_vertformat_alias_add(GPUVertFormat *, const char *alias);
+
int GPU_vertformat_attr_id_get(const GPUVertFormat *, const char *name);
-/**
- * This makes the "virtual" attributes with suffixes "0", "1", "2"
- * to access triangle data in the vertex shader.
- *
- * IMPORTANT:
- * - Call this before creating the vertex buffer and after creating all attributes
- * - Only first vertex out of 3 has the correct information.
- * Use flat output with #GL_FIRST_VERTEX_CONVENTION.
- */
-void GPU_vertformat_triple_load(GPUVertFormat *format);
+BLI_INLINE const char *GPU_vertformat_attr_name_get(const GPUVertFormat *format,
+ const GPUVertAttr *attr,
+ uint n_idx)
+{
+ return format->names + attr->names[n_idx];
+}
/* format conversion */
diff --git a/source/blender/gpu/GPU_viewport.h b/source/blender/gpu/GPU_viewport.h
index 198a9ec98e2..e7600279d6f 100644
--- a/source/blender/gpu/GPU_viewport.h
+++ b/source/blender/gpu/GPU_viewport.h
@@ -37,12 +37,14 @@ typedef struct GPUViewport GPUViewport;
/* Contains memory pools information */
typedef struct ViewportMemoryPool {
- struct BLI_mempool *calls;
- struct BLI_mempool *states;
- struct BLI_mempool *shgroups;
- struct BLI_mempool *uniforms;
- struct BLI_mempool *passes;
- struct BLI_mempool *images;
+ 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;
/* All FramebufferLists are just the same pointers with different names */
@@ -118,7 +120,7 @@ GPUTexture *GPU_viewport_color_texture(GPUViewport *viewport);
GPUTexture *GPU_viewport_texture_pool_query(
GPUViewport *viewport, void *engine, int width, int height, int format);
-bool GPU_viewport_engines_data_validate(GPUViewport *viewport, unsigned int hash);
+bool GPU_viewport_engines_data_validate(GPUViewport *viewport, void **engine_handle_array);
void GPU_viewport_cache_release(GPUViewport *viewport);
#endif // __GPU_VIEWPORT_H__
diff --git a/source/blender/gpu/intern/gpu_attr_binding.c b/source/blender/gpu/intern/gpu_attr_binding.c
index e280b77f661..802b15a0c4e 100644
--- a/source/blender/gpu/intern/gpu_attr_binding.c
+++ b/source/blender/gpu/intern/gpu_attr_binding.c
@@ -70,7 +70,8 @@ void get_attr_locations(const GPUVertFormat *format,
for (uint a_idx = 0; a_idx < format->attr_len; ++a_idx) {
const GPUVertAttr *a = &format->attrs[a_idx];
for (uint n_idx = 0; n_idx < a->name_len; ++n_idx) {
- const GPUShaderInput *input = GPU_shaderinterface_attr(shaderface, a->name[n_idx]);
+ const char *name = GPU_vertformat_attr_name_get(format, a, n_idx);
+ const GPUShaderInput *input = GPU_shaderinterface_attr(shaderface, name);
#if TRUST_NO_ONE
assert(input != NULL);
/* TODO: make this a recoverable runtime error?
diff --git a/source/blender/gpu/intern/gpu_batch.c b/source/blender/gpu/intern/gpu_batch.c
index f179f9ef22c..933bcb2ed8e 100644
--- a/source/blender/gpu/intern/gpu_batch.c
+++ b/source/blender/gpu/intern/gpu_batch.c
@@ -139,6 +139,7 @@ void GPU_batch_clear(GPUBatch *batch)
}
}
GPU_batch_vao_cache_clear(batch);
+ batch->phase = GPU_BATCH_UNUSED;
}
void GPU_batch_discard(GPUBatch *batch)
@@ -369,7 +370,8 @@ static void create_bindings(GPUVertBuf *verts,
const GLvoid *pointer = (const GLubyte *)0 + a->offset + v_first * stride;
for (uint n_idx = 0; n_idx < a->name_len; ++n_idx) {
- const GPUShaderInput *input = GPU_shaderinterface_attr(interface, a->name[n_idx]);
+ const char *name = GPU_vertformat_attr_name_get(format, a, n_idx);
+ const GPUShaderInput *input = GPU_shaderinterface_attr(interface, name);
if (input == NULL) {
continue;
@@ -459,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);
@@ -575,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)
@@ -590,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, v_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_buffers.c b/source/blender/gpu/intern/gpu_buffers.c
index 9290d073295..e30fccbf29d 100644
--- a/source/blender/gpu/intern/gpu_buffers.c
+++ b/source/blender/gpu/intern/gpu_buffers.c
@@ -83,6 +83,8 @@ struct GPU_PBVH_Buffers {
uint tot_tri, tot_quad;
+ short material_index;
+
/* The PBVH ensures that either all faces in the node are
* smooth-shaded or all faces are flat-shaded */
bool smooth;
@@ -289,6 +291,11 @@ void GPU_pbvh_mesh_buffers_update(GPU_PBVH_Buffers *buffers,
}
}
+ /* Get material index from the first face of this buffer. */
+ const MLoopTri *lt = &buffers->looptri[buffers->face_indices[0]];
+ const MPoly *mp = &buffers->mpoly[lt->poly];
+ buffers->material_index = mp->mat_nr;
+
buffers->show_mask = !empty_mask;
buffers->mvert = mvert;
}
@@ -538,7 +545,6 @@ void GPU_pbvh_grid_buffers_update(GPU_PBVH_Buffers *buffers,
int i, j, k, x, y;
const bool smooth = grid_flag_mats[grid_indices[0]].flag & ME_SMOOTH;
- static char vcol[4] = {255, 255, 255, 255};
/* Build VBO */
const int has_mask = key->has_mask;
@@ -603,6 +609,7 @@ void GPU_pbvh_grid_buffers_update(GPU_PBVH_Buffers *buffers,
}
if (show_vcol) {
+ char vcol[4] = {255, 255, 255, 255};
GPU_vertbuf_attr_set(buffers->vert_buf, g_vbo_id.col, vbo_index, &vcol);
}
@@ -652,6 +659,8 @@ void GPU_pbvh_grid_buffers_update(GPU_PBVH_Buffers *buffers,
GPU_vertbuf_attr_set(buffers->vert_buf, g_vbo_id.msk, vbo_index + 3, &fmask);
empty_mask = empty_mask && (fmask == 0.0f);
}
+
+ char vcol[4] = {255, 255, 255, 255};
GPU_vertbuf_attr_set(buffers->vert_buf, g_vbo_id.col, vbo_index + 0, &vcol);
GPU_vertbuf_attr_set(buffers->vert_buf, g_vbo_id.col, vbo_index + 1, &vcol);
GPU_vertbuf_attr_set(buffers->vert_buf, g_vbo_id.col, vbo_index + 2, &vcol);
@@ -666,14 +675,15 @@ void GPU_pbvh_grid_buffers_update(GPU_PBVH_Buffers *buffers,
gpu_pbvh_batch_init(buffers, GPU_PRIM_TRIS);
}
+ /* Get material index from the first face of this buffer. */
+ buffers->material_index = grid_flag_mats[grid_indices[0]].mat_nr;
+
buffers->grids = grids;
buffers->grid_indices = grid_indices;
buffers->totgrid = totgrid;
buffers->grid_flag_mats = grid_flag_mats;
buffers->gridkey = *key;
buffers->show_mask = !empty_mask;
-
- // printf("node updated %p\n", buffers);
}
GPU_PBVH_Buffers *GPU_pbvh_grid_buffers_build(int totgrid, BLI_bitmap **grid_hidden)
@@ -793,6 +803,7 @@ void GPU_pbvh_bmesh_buffers_update(GPU_PBVH_Buffers *buffers,
const bool show_vcol = (update_flags & GPU_PBVH_BUFFERS_SHOW_VCOL) != 0;
int tottri, totvert, maxvert = 0;
bool empty_mask = true;
+ BMFace *f;
/* TODO, make mask layer optional for bmesh buffer */
const int cd_vert_mask_offset = CustomData_get_offset(&bm->vdata, CD_PAINT_MASK);
@@ -864,7 +875,7 @@ void GPU_pbvh_bmesh_buffers_update(GPU_PBVH_Buffers *buffers,
GPU_indexbuf_init(&elb_lines, GPU_PRIM_LINES, tottri * 3, totvert);
GSET_ITER (gs_iter, bm_faces) {
- BMFace *f = BLI_gsetIterator_getKey(&gs_iter);
+ f = BLI_gsetIterator_getKey(&gs_iter);
BLI_assert(f->len == 3);
@@ -922,7 +933,7 @@ void GPU_pbvh_bmesh_buffers_update(GPU_PBVH_Buffers *buffers,
GSetIterator gs_iter;
GSET_ITER (gs_iter, bm_faces) {
- BMFace *f = BLI_gsetIterator_getKey(&gs_iter);
+ f = BLI_gsetIterator_getKey(&gs_iter);
if (!BM_elem_flag_test(f, BM_ELEM_HIDDEN)) {
BMVert *v[3];
@@ -952,6 +963,9 @@ void GPU_pbvh_bmesh_buffers_update(GPU_PBVH_Buffers *buffers,
}
}
+ /* Get material index from the last face we iterated on. */
+ buffers->material_index = f->mat_nr;
+
buffers->show_mask = !empty_mask;
gpu_pbvh_batch_init(buffers, GPU_PRIM_TRIS);
@@ -990,6 +1004,11 @@ bool GPU_pbvh_buffers_has_mask(GPU_PBVH_Buffers *buffers)
return buffers->show_mask;
}
+short GPU_pbvh_buffers_material_index_get(GPU_PBVH_Buffers *buffers)
+{
+ return buffers->material_index;
+}
+
void GPU_pbvh_buffers_free(GPU_PBVH_Buffers *buffers)
{
if (buffers) {
@@ -1009,70 +1028,6 @@ void GPU_pbvh_buffers_free(GPU_PBVH_Buffers *buffers)
/** \} */
-/* -------------------------------------------------------------------- */
-/** \name Debug
- * \{ */
-
-/* debug function, draws the pbvh BB */
-void GPU_pbvh_BB_draw(float min[3], float max[3], bool leaf, uint pos)
-{
- if (leaf) {
- immUniformColor4f(0.0, 1.0, 0.0, 0.5);
- }
- else {
- immUniformColor4f(1.0, 0.0, 0.0, 0.5);
- }
-
- /* TODO(merwin): revisit this after we have mutable VertexBuffers
- * could keep a static batch & index buffer, change the VBO contents per draw
- */
-
- immBegin(GPU_PRIM_LINES, 24);
-
- /* top */
- immVertex3f(pos, min[0], min[1], max[2]);
- immVertex3f(pos, min[0], max[1], max[2]);
-
- immVertex3f(pos, min[0], max[1], max[2]);
- immVertex3f(pos, max[0], max[1], max[2]);
-
- immVertex3f(pos, max[0], max[1], max[2]);
- immVertex3f(pos, max[0], min[1], max[2]);
-
- immVertex3f(pos, max[0], min[1], max[2]);
- immVertex3f(pos, min[0], min[1], max[2]);
-
- /* bottom */
- immVertex3f(pos, min[0], min[1], min[2]);
- immVertex3f(pos, min[0], max[1], min[2]);
-
- immVertex3f(pos, min[0], max[1], min[2]);
- immVertex3f(pos, max[0], max[1], min[2]);
-
- immVertex3f(pos, max[0], max[1], min[2]);
- immVertex3f(pos, max[0], min[1], min[2]);
-
- immVertex3f(pos, max[0], min[1], min[2]);
- immVertex3f(pos, min[0], min[1], min[2]);
-
- /* sides */
- immVertex3f(pos, min[0], min[1], min[2]);
- immVertex3f(pos, min[0], min[1], max[2]);
-
- immVertex3f(pos, min[0], max[1], min[2]);
- immVertex3f(pos, min[0], max[1], max[2]);
-
- immVertex3f(pos, max[0], max[1], min[2]);
- immVertex3f(pos, max[0], max[1], max[2]);
-
- immVertex3f(pos, max[0], min[1], min[2]);
- immVertex3f(pos, max[0], min[1], max[2]);
-
- immEnd();
-}
-
-/** \} */
-
void GPU_pbvh_fix_linking()
{
}
diff --git a/source/blender/gpu/intern/gpu_codegen.c b/source/blender/gpu/intern/gpu_codegen.c
index a77bba5ab86..8dda98ab990 100644
--- a/source/blender/gpu/intern/gpu_codegen.c
+++ b/source/blender/gpu/intern/gpu_codegen.c
@@ -520,9 +520,6 @@ const char *GPU_builtin_name(eGPUBuiltin builtin)
else if (builtin == GPU_INVERSE_OBJECT_MATRIX) {
return "unfinvobmat";
}
- else if (builtin == GPU_INVERSE_NORMAL_MATRIX) {
- return "unfinvnormat";
- }
else if (builtin == GPU_LOC_TO_VIEW_MATRIX) {
return "unflocaltoviewmat";
}
@@ -532,6 +529,9 @@ const char *GPU_builtin_name(eGPUBuiltin builtin)
else if (builtin == GPU_VIEW_POSITION) {
return "varposition";
}
+ else if (builtin == GPU_WORLD_NORMAL) {
+ return "varwnormal";
+ }
else if (builtin == GPU_VIEW_NORMAL) {
return "varnormal";
}
@@ -786,15 +786,15 @@ static void codegen_call_functions(DynStr *ds, ListBase *nodes, GPUOutput *final
else if (input->builtin == GPU_INVERSE_OBJECT_MATRIX) {
BLI_dynstr_append(ds, "objinv");
}
- else if (input->builtin == GPU_INVERSE_NORMAL_MATRIX) {
- BLI_dynstr_append(ds, "norinv");
- }
else if (input->builtin == GPU_VIEW_POSITION) {
BLI_dynstr_append(ds, "viewposition");
}
else if (input->builtin == GPU_VIEW_NORMAL) {
BLI_dynstr_append(ds, "facingnormal");
}
+ else if (input->builtin == GPU_WORLD_NORMAL) {
+ BLI_dynstr_append(ds, "facingwnormal");
+ }
else {
BLI_dynstr_append(ds, GPU_builtin_name(input->builtin));
}
@@ -879,17 +879,15 @@ static char *code_generate_fragment(GPUMaterial *material,
if (builtins & GPU_INVERSE_OBJECT_MATRIX) {
BLI_dynstr_append(ds, "\t#define objinv ModelMatrixInverse\n");
}
- if (builtins & GPU_INVERSE_NORMAL_MATRIX) {
- BLI_dynstr_append(ds, "\t#define norinv NormalMatrixInverse\n");
- }
if (builtins & GPU_INVERSE_VIEW_MATRIX) {
BLI_dynstr_append(ds, "\t#define viewinv ViewMatrixInverse\n");
}
if (builtins & GPU_LOC_TO_VIEW_MATRIX) {
- BLI_dynstr_append(ds, "\t#define localtoviewmat ModelViewMatrix\n");
+ BLI_dynstr_append(ds, "\t#define localtoviewmat (ViewMatrix * ModelMatrix)\n");
}
if (builtins & GPU_INVERSE_LOC_TO_VIEW_MATRIX) {
- BLI_dynstr_append(ds, "\t#define invlocaltoviewmat ModelViewMatrixInverse\n");
+ BLI_dynstr_append(ds,
+ "\t#define invlocaltoviewmat (ModelMatrixInverse * ViewMatrixInverse)\n");
}
if (builtins & GPU_VIEW_NORMAL) {
BLI_dynstr_append(ds, "#ifdef HAIR_SHADER\n");
@@ -897,9 +895,22 @@ static char *code_generate_fragment(GPUMaterial *material,
BLI_dynstr_append(ds, "\tworld_normals_get(n);\n");
BLI_dynstr_append(ds, "\tvec3 facingnormal = transform_direction(ViewMatrix, n);\n");
BLI_dynstr_append(ds, "#else\n");
- BLI_dynstr_append(ds, "\tvec3 facingnormal = gl_FrontFacing? viewNormal: -viewNormal;\n");
+ BLI_dynstr_append(ds, "\tvec3 facingnormal = gl_FrontFacing ? viewNormal: -viewNormal;\n");
BLI_dynstr_append(ds, "#endif\n");
}
+ if (builtins & GPU_WORLD_NORMAL) {
+ BLI_dynstr_append(ds, "\tvec3 facingwnormal;\n");
+ if (builtins & GPU_VIEW_NORMAL) {
+ BLI_dynstr_append(ds, "#ifdef HAIR_SHADER\n");
+ BLI_dynstr_append(ds, "\tfacingwnormal = n;\n");
+ BLI_dynstr_append(ds, "#else\n");
+ BLI_dynstr_append(ds, "\tworld_normals_get(facingwnormal);\n");
+ BLI_dynstr_append(ds, "#endif\n");
+ }
+ else {
+ BLI_dynstr_append(ds, "\tworld_normals_get(facingwnormal);\n");
+ }
+ }
if (builtins & GPU_VIEW_POSITION) {
BLI_dynstr_append(ds, "\t#define viewposition viewPosition\n");
}
@@ -1024,13 +1035,39 @@ static char *code_generate_vertex(ListBase *nodes, const char *vert_code, bool u
BLI_dynstr_append(ds, "out vec3 barycentricPosg;\n");
}
+ BLI_dynstr_append(ds, "\n#define USE_ATTR\n");
+
+ /* Prototype, defined later (this is because of matrices definition). */
+ BLI_dynstr_append(ds, "void pass_attr(in vec3 position);\n");
+
+ BLI_dynstr_append(ds, "\n");
+
+ if (use_geom) {
+ /* XXX HACK: Eevee specific. */
+ char *vert_new, *vert_new2;
+ vert_new = BLI_str_replaceN(vert_code, "worldPosition", "worldPositiong");
+ vert_new2 = vert_new;
+ vert_new = BLI_str_replaceN(vert_new2, "viewPosition", "viewPositiong");
+ MEM_freeN(vert_new2);
+ vert_new2 = vert_new;
+ vert_new = BLI_str_replaceN(vert_new2, "worldNormal", "worldNormalg");
+ MEM_freeN(vert_new2);
+ vert_new2 = vert_new;
+ vert_new = BLI_str_replaceN(vert_new2, "viewNormal", "viewNormalg");
+ MEM_freeN(vert_new2);
+
+ BLI_dynstr_append(ds, vert_new);
+
+ MEM_freeN(vert_new);
+ }
+ else {
+ BLI_dynstr_append(ds, vert_code);
+ }
+
BLI_dynstr_append(ds, "\n");
BLI_dynstr_append(ds,
"#define USE_ATTR\n"
- "uniform mat3 NormalMatrix;\n"
- "uniform mat4 ModelMatrixInverse;\n"
- "uniform mat4 ModelMatrix;\n"
"vec3 srgb_to_linear_attr(vec3 c) {\n"
"\tc = max(c, vec3(0.0));\n"
"\tvec3 c1 = c * (1.0 / 12.92);\n"
@@ -1108,7 +1145,7 @@ static char *code_generate_vertex(ListBase *nodes, const char *vert_code, bool u
if (input->source == GPU_SOURCE_ATTR && input->attr_first) {
if (input->attr_type == CD_TANGENT) { /* silly exception */
BLI_dynstr_appendf(ds,
- "\tvar%d%s.xyz = NormalMatrix * att%d.xyz;\n",
+ "\tvar%d%s.xyz = transpose(mat3(ModelMatrixInverse)) * att%d.xyz;\n",
input->attr_id,
use_geom ? "g" : "",
input->attr_id);
@@ -1167,28 +1204,6 @@ static char *code_generate_vertex(ListBase *nodes, const char *vert_code, bool u
BLI_dynstr_append(ds, "}\n");
- if (use_geom) {
- /* XXX HACK: Eevee specific. */
- char *vert_new, *vert_new2;
- vert_new = BLI_str_replaceN(vert_code, "worldPosition", "worldPositiong");
- vert_new2 = vert_new;
- vert_new = BLI_str_replaceN(vert_new2, "viewPosition", "viewPositiong");
- MEM_freeN(vert_new2);
- vert_new2 = vert_new;
- vert_new = BLI_str_replaceN(vert_new2, "worldNormal", "worldNormalg");
- MEM_freeN(vert_new2);
- vert_new2 = vert_new;
- vert_new = BLI_str_replaceN(vert_new2, "viewNormal", "viewNormalg");
- MEM_freeN(vert_new2);
-
- BLI_dynstr_append(ds, vert_new);
-
- MEM_freeN(vert_new);
- }
- else {
- BLI_dynstr_append(ds, vert_code);
- }
-
code = BLI_dynstr_get_cstring(ds);
BLI_dynstr_free(ds);
@@ -1494,7 +1509,6 @@ static void gpu_node_input_link(GPUNode *node, GPUNodeLink *link, const eGPUType
input->source = GPU_SOURCE_TEX;
input->ima = link->ima;
input->iuser = link->iuser;
- input->image_isdata = link->image_isdata;
break;
case GPU_NODE_LINK_ATTR:
input->source = GPU_SOURCE_ATTR;
@@ -1739,13 +1753,12 @@ GPUNodeLink *GPU_uniform(float *num)
return link;
}
-GPUNodeLink *GPU_image(Image *ima, ImageUser *iuser, bool is_data)
+GPUNodeLink *GPU_image(Image *ima, ImageUser *iuser)
{
GPUNodeLink *link = GPU_node_link_create();
link->link_type = GPU_NODE_LINK_IMAGE_BLENDER;
link->ima = ima;
link->iuser = iuser;
- link->image_isdata = is_data;
return link;
}
diff --git a/source/blender/gpu/intern/gpu_codegen.h b/source/blender/gpu/intern/gpu_codegen.h
index 73155c3aafa..d1bb3f26920 100644
--- a/source/blender/gpu/intern/gpu_codegen.h
+++ b/source/blender/gpu/intern/gpu_codegen.h
@@ -99,7 +99,6 @@ struct GPUNodeLink {
struct {
struct Image *ima;
struct ImageUser *iuser;
- bool image_isdata;
};
};
};
@@ -137,7 +136,6 @@ typedef struct GPUInput {
struct GPUTexture **coba; /* input texture, only set at runtime */
struct Image *ima; /* image */
struct ImageUser *iuser; /* image user */
- bool image_isdata; /* image does not contain color data */
bool bindtex; /* input is responsible for binding the texture? */
int texid; /* number for multitexture, starting from zero */
eGPUType textype; /* texture type (2D, 1D Array ...) */
diff --git a/source/blender/gpu/intern/gpu_draw.c b/source/blender/gpu/intern/gpu_draw.c
index edc2f2171a5..638729d027c 100644
--- a/source/blender/gpu/intern/gpu_draw.c
+++ b/source/blender/gpu/intern/gpu_draw.c
@@ -50,6 +50,7 @@
#include "MEM_guardedalloc.h"
+#include "IMB_colormanagement.h"
#include "IMB_imbuf.h"
#include "IMB_imbuf_types.h"
@@ -207,53 +208,231 @@ static GPUTexture **gpu_get_image_gputexture(Image *ima, GLenum textarget)
return NULL;
}
-typedef struct VerifyThreadData {
- ImBuf *ibuf;
- float *srgb_frect;
-} VerifyThreadData;
+static uint gpu_texture_create_from_ibuf(Image *ima, ImBuf *ibuf, int textarget)
+{
+ uint bindcode = 0;
+ const bool mipmap = GPU_get_mipmap();
+
+#ifdef WITH_DDS
+ if (ibuf->ftype == IMB_FTYPE_DDS) {
+ /* DDS is loaded directly in compressed form. */
+ GPU_create_gl_tex_compressed(&bindcode, textarget, ima, ibuf);
+ return bindcode;
+ }
+#endif
+
+ /* Regular uncompressed texture. */
+ float *rect_float = ibuf->rect_float;
+ uchar *rect = (uchar *)ibuf->rect;
+ bool compress_as_srgb = false;
+
+ if (rect_float == NULL) {
+ /* Byte image is in original colorspace from the file. If the file is sRGB
+ * scene linear, or non-color data no conversion is needed. Otherwise we
+ * compress as scene linear + sRGB transfer function to avoid precision loss
+ * in common cases.
+ *
+ * We must also convert to premultiplied for correct texture interpolation
+ * and consistency with float images. */
+ if (!IMB_colormanagement_space_is_data(ibuf->rect_colorspace)) {
+ compress_as_srgb = !IMB_colormanagement_space_is_scene_linear(ibuf->rect_colorspace);
+
+ rect = MEM_mallocN(sizeof(uchar) * 4 * ibuf->x * ibuf->y, __func__);
+ if (rect == NULL) {
+ return bindcode;
+ }
+
+ IMB_colormanagement_imbuf_to_srgb_texture(
+ rect, 0, 0, ibuf->x, ibuf->y, ibuf, compress_as_srgb);
+ }
+ }
+ else if (ibuf->channels != 4) {
+ /* Float image is already in scene linear colorspace or non-color data by
+ * convention, no colorspace conversion needed. But we do require 4 channels
+ * currently. */
+ rect_float = MEM_mallocN(sizeof(float) * 4 * ibuf->x * ibuf->y, __func__);
+ if (rect_float == NULL) {
+ return bindcode;
+ }
+
+ IMB_buffer_float_from_float(rect_float,
+ ibuf->rect_float,
+ ibuf->channels,
+ IB_PROFILE_LINEAR_RGB,
+ IB_PROFILE_LINEAR_RGB,
+ false,
+ ibuf->x,
+ ibuf->y,
+ ibuf->x,
+ ibuf->x);
+ }
+
+ /* Create OpenGL texture. */
+ GPU_create_gl_tex(&bindcode,
+ (uint *)rect,
+ rect_float,
+ ibuf->x,
+ ibuf->y,
+ textarget,
+ mipmap,
+ compress_as_srgb,
+ ima);
+
+ /* Free buffers if needed. */
+ if (rect && rect != (uchar *)ibuf->rect) {
+ MEM_freeN(rect);
+ }
+ if (rect_float && rect_float != ibuf->rect_float) {
+ MEM_freeN(rect_float);
+ }
-static void gpu_verify_high_bit_srgb_buffer_slice(float *srgb_frect,
- ImBuf *ibuf,
- const int start_line,
- const int height)
+ return bindcode;
+}
+
+static void gpu_texture_update_scaled(
+ uchar *rect, float *rect_float, int full_w, int full_h, int x, int y, int w, int h)
{
- size_t offset = ibuf->channels * start_line * ibuf->x;
- float *current_srgb_frect = srgb_frect + offset;
- float *current_rect_float = ibuf->rect_float + offset;
- IMB_buffer_float_from_float(current_srgb_frect,
- current_rect_float,
- ibuf->channels,
- IB_PROFILE_SRGB,
- IB_PROFILE_LINEAR_RGB,
- true,
- ibuf->x,
- height,
- ibuf->x,
- ibuf->x);
- IMB_buffer_float_unpremultiply(current_srgb_frect, ibuf->x, height);
+ /* Partial update with scaling. */
+ int limit_w = smaller_power_of_2_limit(full_w);
+ int limit_h = smaller_power_of_2_limit(full_h);
+ float xratio = limit_w / (float)full_w;
+ float yratio = limit_h / (float)full_h;
+
+ /* Find sub coordinates in scaled image. Take ceiling because we will be
+ * losing 1 pixel due to rounding errors in x,y. */
+ int sub_x = x * xratio;
+ int sub_y = y * yratio;
+ int sub_w = (int)ceil(xratio * w);
+ int sub_h = (int)ceil(yratio * h);
+
+ /* ...but take back if we are over the limit! */
+ if (sub_w + sub_x > limit_w) {
+ sub_w--;
+ }
+ if (sub_h + sub_y > limit_h) {
+ sub_h--;
+ }
+
+ /* Scale pixels. */
+ ImBuf *ibuf = IMB_allocFromBuffer((uint *)rect, rect_float, w, h);
+ IMB_scaleImBuf(ibuf, sub_w, sub_h);
+
+ if (ibuf->rect_float) {
+ glTexSubImage2D(
+ GL_TEXTURE_2D, 0, sub_x, sub_y, sub_w, sub_h, GL_RGBA, GL_FLOAT, ibuf->rect_float);
+ }
+ else {
+ glTexSubImage2D(
+ GL_TEXTURE_2D, 0, sub_x, sub_y, sub_w, sub_h, GL_RGBA, GL_UNSIGNED_BYTE, ibuf->rect);
+ }
+
+ IMB_freeImBuf(ibuf);
}
-static void verify_thread_do(void *data_v, int start_scanline, int num_scanlines)
+static void gpu_texture_update_unscaled(
+ uchar *rect, float *rect_float, int x, int y, int w, int h, GLint tex_stride, GLint tex_offset)
{
- VerifyThreadData *data = (VerifyThreadData *)data_v;
- gpu_verify_high_bit_srgb_buffer_slice(
- data->srgb_frect, data->ibuf, start_scanline, num_scanlines);
+ /* Partial update without scaling. Stride and offset are used to copy only a
+ * subset of a possible larger buffer than what we are updating. */
+ GLint row_length;
+ glGetIntegerv(GL_UNPACK_ROW_LENGTH, &row_length);
+ glPixelStorei(GL_UNPACK_ROW_LENGTH, tex_stride);
+
+ if (rect_float == NULL) {
+ glTexSubImage2D(GL_TEXTURE_2D, 0, x, y, w, h, GL_RGBA, GL_UNSIGNED_BYTE, rect + tex_offset);
+ }
+ else {
+ glTexSubImage2D(GL_TEXTURE_2D, 0, x, y, w, h, GL_RGBA, GL_FLOAT, rect_float + tex_offset);
+ }
+
+ glPixelStorei(GL_UNPACK_ROW_LENGTH, row_length);
}
-static void gpu_verify_high_bit_srgb_buffer(float *srgb_frect, ImBuf *ibuf)
+static void gpu_texture_update_from_ibuf(ImBuf *ibuf, int x, int y, int w, int h)
{
- if (ibuf->y < 64) {
- gpu_verify_high_bit_srgb_buffer_slice(srgb_frect, ibuf, 0, ibuf->y);
+ /* Partial update of texture for texture painting. This is often much
+ * quicker than fully updating the texture for high resolution images.
+ * Assumes the OpenGL texture is bound to 0. */
+ const bool scaled = is_over_resolution_limit(GL_TEXTURE_2D, ibuf->x, ibuf->y);
+
+ if (scaled) {
+ /* Extra padding to account for bleed from neighboring pixels. */
+ const int padding = 4;
+ const int xmax = min_ii(x + w + padding, ibuf->x);
+ const int ymax = min_ii(y + h + padding, ibuf->y);
+ x = max_ii(x - padding, 0);
+ y = max_ii(y - padding, 0);
+ w = xmax - x;
+ h = ymax - y;
+ }
+
+ /* Get texture data pointers. */
+ float *rect_float = ibuf->rect_float;
+ uchar *rect = (uchar *)ibuf->rect;
+ GLint tex_stride = ibuf->x;
+ GLint tex_offset = ibuf->channels * (y * ibuf->x + x);
+
+ if (rect_float == NULL) {
+ /* Byte pixels. */
+ if (!IMB_colormanagement_space_is_data(ibuf->rect_colorspace)) {
+ const bool compress_as_srgb = !IMB_colormanagement_space_is_scene_linear(
+ ibuf->rect_colorspace);
+
+ rect = MEM_mallocN(sizeof(uchar) * 4 * w * h, __func__);
+ if (rect == NULL) {
+ return;
+ }
+
+ tex_stride = w;
+ tex_offset = 0;
+
+ /* Convert to scene linear with sRGB compression, and premultiplied for
+ * correct texture interpolation. */
+ IMB_colormanagement_imbuf_to_srgb_texture(rect, x, y, w, h, ibuf, compress_as_srgb);
+ }
+ }
+ else if (ibuf->channels != 4 || scaled) {
+ /* Float pixels. */
+ rect_float = MEM_mallocN(sizeof(float) * 4 * x * y, __func__);
+ if (rect_float == NULL) {
+ return;
+ }
+
+ tex_stride = w;
+ tex_offset = 0;
+
+ size_t ibuf_offset = (y * ibuf->x + x) * ibuf->channels;
+ IMB_buffer_float_from_float(rect_float,
+ ibuf->rect_float + ibuf_offset,
+ ibuf->channels,
+ IB_PROFILE_LINEAR_RGB,
+ IB_PROFILE_LINEAR_RGB,
+ false,
+ w,
+ h,
+ x,
+ ibuf->x);
+ }
+
+ if (scaled) {
+ /* Slower update where we first have to scale the input pixels. */
+ gpu_texture_update_scaled(rect, rect_float, ibuf->x, ibuf->y, x, y, w, h);
}
else {
- VerifyThreadData data;
- data.ibuf = ibuf;
- data.srgb_frect = srgb_frect;
- IMB_processor_apply_threaded_scanlines(ibuf->y, verify_thread_do, &data);
+ /* Fast update at same resolution. */
+ gpu_texture_update_unscaled(rect, rect_float, x, y, w, h, tex_stride, tex_offset);
+ }
+
+ /* Free buffers if needed. */
+ if (rect && rect != (uchar *)ibuf->rect) {
+ MEM_freeN(rect);
+ }
+ if (rect_float && rect_float != ibuf->rect_float) {
+ MEM_freeN(rect_float);
}
}
-GPUTexture *GPU_texture_from_blender(Image *ima, ImageUser *iuser, int textarget, bool is_data)
+GPUTexture *GPU_texture_from_blender(Image *ima, ImageUser *iuser, int textarget)
{
if (ima == NULL) {
return NULL;
@@ -286,62 +465,7 @@ GPUTexture *GPU_texture_from_blender(Image *ima, ImageUser *iuser, int textarget
return *tex;
}
- /* flag to determine whether deep format is used */
- bool use_high_bit_depth = false, do_color_management = false;
-
- if (ibuf->rect_float) {
- use_high_bit_depth = true;
-
- /* TODO unneeded when float images are correctly treated as linear always */
- if (!is_data) {
- do_color_management = true;
- }
- }
-
- const int rectw = ibuf->x;
- const int recth = ibuf->y;
- uint *rect = ibuf->rect;
- float *frect = NULL;
- float *srgb_frect = NULL;
-
- if (use_high_bit_depth) {
- if (do_color_management) {
- frect = srgb_frect = MEM_mallocN(ibuf->x * ibuf->y * sizeof(*srgb_frect) * 4,
- "floar_buf_col_cor");
- gpu_verify_high_bit_srgb_buffer(srgb_frect, ibuf);
- }
- else {
- frect = ibuf->rect_float;
- }
- }
-
- const bool mipmap = GPU_get_mipmap();
-
-#ifdef WITH_DDS
- if (ibuf->ftype == IMB_FTYPE_DDS) {
- GPU_create_gl_tex_compressed(&bindcode, rect, rectw, recth, textarget, mipmap, ima, ibuf);
- }
- else
-#endif
- {
- GPU_create_gl_tex(
- &bindcode, rect, frect, rectw, recth, textarget, mipmap, use_high_bit_depth, ima);
- }
-
- /* mark as non-color data texture */
- if (bindcode) {
- if (is_data) {
- ima->gpuflag |= IMA_GPU_IS_DATA;
- }
- else {
- ima->gpuflag &= ~IMA_GPU_IS_DATA;
- }
- }
-
- /* clean up */
- if (srgb_frect) {
- MEM_freeN(srgb_frect);
- }
+ bindcode = gpu_texture_create_from_ibuf(ima, ibuf, textarget);
BKE_image_release_ibuf(ima, ibuf, NULL);
@@ -349,15 +473,14 @@ GPUTexture *GPU_texture_from_blender(Image *ima, ImageUser *iuser, int textarget
return *tex;
}
-static void **gpu_gen_cube_map(
- uint *rect, float *frect, int rectw, int recth, bool use_high_bit_depth)
+static void **gpu_gen_cube_map(uint *rect, float *frect, int rectw, int recth)
{
- size_t block_size = use_high_bit_depth ? sizeof(float[4]) : sizeof(uchar[4]);
+ size_t block_size = frect ? sizeof(float[4]) : sizeof(uchar[4]);
void **sides = NULL;
int h = recth / 2;
int w = rectw / 3;
- if ((use_high_bit_depth && frect == NULL) || (!use_high_bit_depth && rect == NULL) || w != h) {
+ if (w != h) {
return sides;
}
@@ -376,7 +499,7 @@ static void **gpu_gen_cube_map(
* | NegZ | PosZ | PosY |
* |______|______|______|
*/
- if (use_high_bit_depth) {
+ if (frect) {
float(*frectb)[4] = (float(*)[4])frect;
float(**fsides)[4] = (float(**)[4])sides;
@@ -430,7 +553,7 @@ void GPU_create_gl_tex(uint *bind,
int recth,
int textarget,
bool mipmap,
- bool use_high_bit_depth,
+ bool use_srgb,
Image *ima)
{
ImBuf *ibuf = NULL;
@@ -441,7 +564,7 @@ void GPU_create_gl_tex(uint *bind,
rectw = smaller_power_of_2_limit(rectw);
recth = smaller_power_of_2_limit(recth);
- if (use_high_bit_depth) {
+ if (frect) {
ibuf = IMB_allocFromBuffer(NULL, frect, tpx, tpy);
IMB_scaleImBuf(ibuf, rectw, recth);
@@ -459,12 +582,15 @@ void GPU_create_gl_tex(uint *bind,
glGenTextures(1, (GLuint *)bind);
glBindTexture(textarget, *bind);
+ GLenum internal_format = (frect) ? GL_RGBA16F : (use_srgb) ? GL_SRGB8_ALPHA8 : GL_RGBA8;
+
if (textarget == GL_TEXTURE_2D) {
- if (use_high_bit_depth) {
- glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA16F, rectw, recth, 0, GL_RGBA, GL_FLOAT, frect);
+ if (frect) {
+ glTexImage2D(GL_TEXTURE_2D, 0, internal_format, rectw, recth, 0, GL_RGBA, GL_FLOAT, frect);
}
else {
- glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, rectw, recth, 0, GL_RGBA, GL_UNSIGNED_BYTE, rect);
+ glTexImage2D(
+ GL_TEXTURE_2D, 0, internal_format, rectw, recth, 0, GL_RGBA, GL_UNSIGNED_BYTE, rect);
}
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, gpu_get_mipmap_filter(1));
@@ -484,15 +610,14 @@ void GPU_create_gl_tex(uint *bind,
int w = rectw / 3, h = recth / 2;
if (h == w && is_power_of_2_i(h) && !is_over_resolution_limit(textarget, h, w)) {
- void **cube_map = gpu_gen_cube_map(rect, frect, rectw, recth, use_high_bit_depth);
- GLenum informat = use_high_bit_depth ? GL_RGBA16F : GL_RGBA8;
- GLenum type = use_high_bit_depth ? GL_FLOAT : GL_UNSIGNED_BYTE;
+ void **cube_map = gpu_gen_cube_map(rect, frect, rectw, recth);
+ GLenum type = frect ? GL_FLOAT : GL_UNSIGNED_BYTE;
if (cube_map) {
for (int i = 0; i < 6; i++) {
glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X + i,
0,
- informat,
+ internal_format,
w,
h,
0,
@@ -542,7 +667,7 @@ void GPU_create_gl_tex(uint *bind,
* This is so the viewport and the BGE can share some code.
* Returns false if the provided ImBuf doesn't have a supported DXT compression format
*/
-bool GPU_upload_dxt_texture(ImBuf *ibuf)
+bool GPU_upload_dxt_texture(ImBuf *ibuf, bool use_srgb)
{
#ifdef WITH_DDS
GLint format = 0;
@@ -553,13 +678,16 @@ bool GPU_upload_dxt_texture(ImBuf *ibuf)
if (GLEW_EXT_texture_compression_s3tc) {
if (ibuf->dds_data.fourcc == FOURCC_DXT1) {
- format = GL_COMPRESSED_RGBA_S3TC_DXT1_EXT;
+ format = (use_srgb) ? GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT :
+ GL_COMPRESSED_RGBA_S3TC_DXT1_EXT;
}
else if (ibuf->dds_data.fourcc == FOURCC_DXT3) {
- format = GL_COMPRESSED_RGBA_S3TC_DXT3_EXT;
+ format = (use_srgb) ? GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT3_EXT :
+ GL_COMPRESSED_RGBA_S3TC_DXT3_EXT;
}
else if (ibuf->dds_data.fourcc == FOURCC_DXT5) {
- format = GL_COMPRESSED_RGBA_S3TC_DXT5_EXT;
+ format = (use_srgb) ? GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT :
+ GL_COMPRESSED_RGBA_S3TC_DXT5_EXT;
}
}
@@ -606,25 +734,30 @@ bool GPU_upload_dxt_texture(ImBuf *ibuf)
return true;
#else
- (void)ibuf;
+ UNUSED_VARS(ibuf, use_srgb);
return false;
#endif
}
-void GPU_create_gl_tex_compressed(
- uint *bind, uint *pix, int x, int y, int textarget, int mipmap, Image *ima, ImBuf *ibuf)
+void GPU_create_gl_tex_compressed(unsigned int *bind, int textarget, Image *ima, ImBuf *ibuf)
{
+ /* For DDS we only support data, scene linear and sRGB. Converting to
+ * different colorspace would break the compression. */
+ const bool use_srgb = !(IMB_colormanagement_space_is_data(ibuf->rect_colorspace) ||
+ IMB_colormanagement_space_is_scene_linear(ibuf->rect_colorspace));
+ const bool mipmap = GPU_get_mipmap();
+
#ifndef WITH_DDS
(void)ibuf;
/* Fall back to uncompressed if DDS isn't enabled */
- GPU_create_gl_tex(bind, pix, NULL, x, y, textarget, mipmap, 0, ima);
+ GPU_create_gl_tex(bind, ibuf->rect, NULL, ibuf->x, ibuf->y, textarget, mipmap, use_srgb, ima);
#else
glGenTextures(1, (GLuint *)bind);
glBindTexture(textarget, *bind);
- if (textarget == GL_TEXTURE_2D && GPU_upload_dxt_texture(ibuf) == 0) {
+ if (textarget == GL_TEXTURE_2D && GPU_upload_dxt_texture(ibuf, use_srgb) == 0) {
glDeleteTextures(1, (GLuint *)bind);
- GPU_create_gl_tex(bind, pix, NULL, x, y, textarget, mipmap, 0, ima);
+ GPU_create_gl_tex(bind, ibuf->rect, NULL, ibuf->x, ibuf->y, textarget, mipmap, use_srgb, ima);
}
glBindTexture(textarget, 0);
@@ -680,146 +813,20 @@ void GPU_paint_set_mipmap(Main *bmain, bool mipmap)
}
}
-/* check if image has been downscaled and do scaled partial update */
-static bool gpu_check_scaled_image(
- ImBuf *ibuf, Image *ima, float *frect, int x, int y, int w, int h)
-{
- if (is_over_resolution_limit(GL_TEXTURE_2D, ibuf->x, ibuf->y)) {
- int x_limit = smaller_power_of_2_limit(ibuf->x);
- int y_limit = smaller_power_of_2_limit(ibuf->y);
-
- float xratio = x_limit / (float)ibuf->x;
- float yratio = y_limit / (float)ibuf->y;
-
- /* find new width, height and x,y gpu texture coordinates */
-
- /* take ceiling because we will be losing 1 pixel due to rounding errors in x,y... */
- int rectw = (int)ceil(xratio * w);
- int recth = (int)ceil(yratio * h);
-
- x *= xratio;
- y *= yratio;
-
- /* ...but take back if we are over the limit! */
- if (rectw + x > x_limit) {
- rectw--;
- }
- if (recth + y > y_limit) {
- recth--;
- }
-
- GPU_texture_bind(ima->gputexture[TEXTARGET_TEXTURE_2D], 0);
-
- /* float rectangles are already continuous in memory so we can use IMB_scaleImBuf */
- if (frect) {
- ImBuf *ibuf_scale = IMB_allocFromBuffer(NULL, frect, w, h);
- IMB_scaleImBuf(ibuf_scale, rectw, recth);
-
- glTexSubImage2D(
- GL_TEXTURE_2D, 0, x, y, rectw, recth, GL_RGBA, GL_FLOAT, ibuf_scale->rect_float);
-
- IMB_freeImBuf(ibuf_scale);
- }
- /* byte images are not continuous in memory so do manual interpolation */
- else {
- uchar *scalerect = MEM_mallocN(rectw * recth * sizeof(*scalerect) * 4, "scalerect");
- uint *p = (uint *)scalerect;
- int i, j;
- float inv_xratio = 1.0f / xratio;
- float inv_yratio = 1.0f / yratio;
- for (i = 0; i < rectw; i++) {
- float u = (x + i) * inv_xratio;
- for (j = 0; j < recth; j++) {
- float v = (y + j) * inv_yratio;
- bilinear_interpolation_color_wrap(ibuf, (uchar *)(p + i + j * (rectw)), NULL, u, v);
- }
- }
-
- glTexSubImage2D(GL_TEXTURE_2D, 0, x, y, rectw, recth, GL_RGBA, GL_UNSIGNED_BYTE, scalerect);
-
- MEM_freeN(scalerect);
- }
-
- if (GPU_get_mipmap()) {
- glGenerateMipmap(GL_TEXTURE_2D);
- }
- else {
- ima->gpuflag &= ~IMA_GPU_MIPMAP_COMPLETE;
- }
-
- GPU_texture_unbind(ima->gputexture[TEXTARGET_TEXTURE_2D]);
-
- return true;
- }
-
- return false;
-}
-
void GPU_paint_update_image(Image *ima, ImageUser *iuser, int x, int y, int w, int h)
{
ImBuf *ibuf = BKE_image_acquire_ibuf(ima, iuser, NULL);
if ((ima->gputexture[TEXTARGET_TEXTURE_2D] == NULL) || (ibuf == NULL) || (w == 0) || (h == 0)) {
- /* these cases require full reload still */
+ /* Full reload of texture. */
GPU_free_image(ima);
}
else {
- /* for the special case, we can do a partial update
- * which is much quicker for painting */
- GLint row_length, skip_pixels, skip_rows;
-
- /* if color correction is needed, we must update the part that needs updating. */
- if (ibuf->rect_float) {
- float *buffer = MEM_mallocN(w * h * sizeof(float) * 4, "temp_texpaint_float_buf");
- bool is_data = (ima->gpuflag & IMA_GPU_IS_DATA) != 0;
- IMB_partial_rect_from_float(ibuf, buffer, x, y, w, h, is_data);
-
- if (gpu_check_scaled_image(ibuf, ima, buffer, x, y, w, h)) {
- MEM_freeN(buffer);
- BKE_image_release_ibuf(ima, ibuf, NULL);
- return;
- }
-
- GPU_texture_bind(ima->gputexture[TEXTARGET_TEXTURE_2D], 0);
- glTexSubImage2D(GL_TEXTURE_2D, 0, x, y, w, h, GL_RGBA, GL_FLOAT, buffer);
-
- MEM_freeN(buffer);
-
- if (GPU_get_mipmap()) {
- glGenerateMipmap(GL_TEXTURE_2D);
- }
- else {
- ima->gpuflag &= ~IMA_GPU_MIPMAP_COMPLETE;
- }
-
- GPU_texture_unbind(ima->gputexture[TEXTARGET_TEXTURE_2D]);
-
- BKE_image_release_ibuf(ima, ibuf, NULL);
- return;
- }
-
- if (gpu_check_scaled_image(ibuf, ima, NULL, x, y, w, h)) {
- BKE_image_release_ibuf(ima, ibuf, NULL);
- return;
- }
-
+ /* Partial update of texture. */
GPU_texture_bind(ima->gputexture[TEXTARGET_TEXTURE_2D], 0);
- glGetIntegerv(GL_UNPACK_ROW_LENGTH, &row_length);
- glGetIntegerv(GL_UNPACK_SKIP_PIXELS, &skip_pixels);
- glGetIntegerv(GL_UNPACK_SKIP_ROWS, &skip_rows);
-
- glPixelStorei(GL_UNPACK_ROW_LENGTH, ibuf->x);
- glPixelStorei(GL_UNPACK_SKIP_PIXELS, x);
- glPixelStorei(GL_UNPACK_SKIP_ROWS, y);
-
- glTexSubImage2D(GL_TEXTURE_2D, 0, x, y, w, h, GL_RGBA, GL_UNSIGNED_BYTE, ibuf->rect);
-
- glPixelStorei(GL_UNPACK_ROW_LENGTH, row_length);
- glPixelStorei(GL_UNPACK_SKIP_PIXELS, skip_pixels);
- glPixelStorei(GL_UNPACK_SKIP_ROWS, skip_rows);
+ gpu_texture_update_from_ibuf(ibuf, x, y, w, h);
- /* see comment above as to why we are using gpu mipmap generation here */
if (GPU_get_mipmap()) {
glGenerateMipmap(GL_TEXTURE_2D);
}
@@ -1242,7 +1249,7 @@ static void gpu_free_image_immediate(Image *ima)
}
}
- ima->gpuflag &= ~(IMA_GPU_MIPMAP_COMPLETE | IMA_GPU_IS_DATA);
+ ima->gpuflag &= ~(IMA_GPU_MIPMAP_COMPLETE);
}
void GPU_free_image(Image *ima)
diff --git a/source/blender/gpu/intern/gpu_material.c b/source/blender/gpu/intern/gpu_material.c
index 1a668a48eed..fde60fd387d 100644
--- a/source/blender/gpu/intern/gpu_material.c
+++ b/source/blender/gpu/intern/gpu_material.c
@@ -36,6 +36,7 @@
#include "BLI_listbase.h"
#include "BLI_utildefines.h"
#include "BLI_string.h"
+#include "BLI_string_utils.h"
#include "BKE_main.h"
#include "BKE_node.h"
@@ -125,7 +126,6 @@ struct GPUMaterial {
enum {
GPU_DOMAIN_SURFACE = (1 << 0),
GPU_DOMAIN_VOLUME = (1 << 1),
- GPU_DOMAIN_SSS = (1 << 2),
};
/* Functions */
@@ -231,6 +231,12 @@ ListBase *GPU_material_get_inputs(GPUMaterial *material)
return &material->inputs;
}
+/* Return can be NULL if it's a world material. */
+Material *GPU_material_get_material(GPUMaterial *material)
+{
+ return material->ma;
+}
+
GPUUniformBuffer *GPU_material_uniform_buffer_get(GPUMaterial *material)
{
return material->ubo;
@@ -597,15 +603,6 @@ eGPUMaterialStatus GPU_material_status(GPUMaterial *mat)
/* Code generation */
-bool GPU_material_do_color_management(GPUMaterial *mat)
-{
- if (!BKE_scene_check_color_management_enabled(mat->scene)) {
- return false;
- }
-
- return true;
-}
-
bool GPU_material_use_domain_surface(GPUMaterial *mat)
{
return (mat->domain & GPU_DOMAIN_SURFACE);
@@ -646,6 +643,7 @@ GPUMaterial *GPU_material_from_nodetree_find(ListBase *gpumaterials,
* so only do this when they are needed.
*/
GPUMaterial *GPU_material_from_nodetree(Scene *scene,
+ struct Material *ma,
struct bNodeTree *ntree,
ListBase *gpumaterials,
const void *engine_type,
@@ -664,6 +662,7 @@ GPUMaterial *GPU_material_from_nodetree(Scene *scene,
/* allocate material */
GPUMaterial *mat = MEM_callocN(sizeof(GPUMaterial), "GPUMaterial");
+ mat->ma = ma;
mat->scene = scene;
mat->engine_type = engine_type;
mat->options = options;
@@ -679,14 +678,14 @@ GPUMaterial *GPU_material_from_nodetree(Scene *scene,
gpu_material_ramp_texture_build(mat);
- if (has_surface_output) {
- mat->domain |= GPU_DOMAIN_SURFACE;
- }
- if (has_volume_output) {
- mat->domain |= GPU_DOMAIN_VOLUME;
- }
+ SET_FLAG_FROM_TEST(mat->domain, has_surface_output, GPU_DOMAIN_SURFACE);
+ SET_FLAG_FROM_TEST(mat->domain, has_volume_output, GPU_DOMAIN_VOLUME);
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");
+ }
/* Prune the unused nodes and extract attributes before compiling so the
* generated VBOs are ready to accept the future shader. */
GPU_nodes_prune(&mat->nodes, mat->outlink);
@@ -702,6 +701,10 @@ GPUMaterial *GPU_material_from_nodetree(Scene *scene,
frag_lib,
defines);
+ if (GPU_material_flag_get(mat, GPU_MATFLAG_SSS)) {
+ MEM_freeN((char *)defines);
+ }
+
if (mat->pass == NULL) {
/* We had a cache hit and the shader has already failed to compile. */
mat->status = GPU_MAT_FAILED;
diff --git a/source/blender/gpu/intern/gpu_matrix.c b/source/blender/gpu/intern/gpu_matrix.c
index 5d65861c1e2..cc89da19705 100644
--- a/source/blender/gpu/intern/gpu_matrix.c
+++ b/source/blender/gpu/intern/gpu_matrix.c
@@ -502,19 +502,13 @@ static void gpu_mul_invert_projmat_m4_unmapped_v3(const float projmat[4][4], flo
co[2] *= -1;
}
-bool GPU_matrix_unproject(const float win[3],
- const float model[4][4],
- const float proj[4][4],
- const int view[4],
- float world[3])
+void GPU_matrix_unproject_model_inverted(const float win[3],
+ const float model_inverted[4][4],
+ const float proj[4][4],
+ const int view[4],
+ float world[3])
{
float in[3];
- float viewinv[4][4];
-
- if (!invert_m4_m4(viewinv, model)) {
- zero_v3(world);
- return false;
- }
copy_v3_v3(in, win);
@@ -523,8 +517,22 @@ bool GPU_matrix_unproject(const float win[3],
in[1] = (in[1] - view[1]) / view[3];
gpu_mul_invert_projmat_m4_unmapped_v3(proj, in);
- mul_v3_m4v3(world, viewinv, in);
+ mul_v3_m4v3(world, model_inverted, in);
+}
+bool GPU_matrix_unproject(const float win[3],
+ const float model[4][4],
+ const float proj[4][4],
+ const int view[4],
+ float world[3])
+{
+ float model_inverted[4][4];
+
+ if (!invert_m4_m4(model_inverted, model)) {
+ zero_v3(world);
+ return false;
+ }
+ GPU_matrix_unproject_model_inverted(win, model_inverted, proj, view, world);
return true;
}
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_select_sample_query.c b/source/blender/gpu/intern/gpu_select_sample_query.c
index 3fbc24d6089..56f9ef69221 100644
--- a/source/blender/gpu/intern/gpu_select_sample_query.c
+++ b/source/blender/gpu/intern/gpu_select_sample_query.c
@@ -104,8 +104,11 @@ void gpu_select_query_begin(
/* occlusion queries operates on fragments that pass tests and since we are interested on all
* objects in the view frustum independently of their order, we need to disable the depth test */
if (mode == GPU_SELECT_ALL) {
- glDisable(GL_DEPTH_TEST);
- glDepthMask(GL_FALSE);
+ /* glQueries on Windows+Intel drivers only works with depth testing turned on.
+ * See T62947 for details */
+ glEnable(GL_DEPTH_TEST);
+ glDepthFunc(GL_ALWAYS);
+ glDepthMask(GL_TRUE);
}
else if (mode == GPU_SELECT_NEAREST_FIRST_PASS) {
glClear(GL_DEPTH_BUFFER_BIT);
diff --git a/source/blender/gpu/intern/gpu_shader.c b/source/blender/gpu/intern/gpu_shader.c
index 3d5b0dda5e4..7201025ad8a 100644
--- a/source/blender/gpu/intern/gpu_shader.c
+++ b/source/blender/gpu/intern/gpu_shader.c
@@ -145,17 +145,8 @@ extern char datatoc_gpu_shader_selection_id_frag_glsl[];
extern char datatoc_gpu_shader_2D_line_dashed_uniform_color_vert_glsl[];
extern char datatoc_gpu_shader_2D_line_dashed_frag_glsl[];
extern char datatoc_gpu_shader_2D_line_dashed_geom_glsl[];
-extern char datatoc_gpu_shader_3D_line_dashed_uniform_color_legacy_vert_glsl[];
extern char datatoc_gpu_shader_3D_line_dashed_uniform_color_vert_glsl[];
-extern char datatoc_gpu_shader_edges_front_back_persp_vert_glsl[];
-extern char datatoc_gpu_shader_edges_front_back_persp_geom_glsl[];
-extern char datatoc_gpu_shader_edges_front_back_persp_legacy_vert_glsl[];
-extern char datatoc_gpu_shader_edges_front_back_ortho_vert_glsl[];
-extern char datatoc_gpu_shader_edges_overlay_vert_glsl[];
-extern char datatoc_gpu_shader_edges_overlay_geom_glsl[];
-extern char datatoc_gpu_shader_edges_overlay_simple_geom_glsl[];
-extern char datatoc_gpu_shader_edges_overlay_frag_glsl[];
extern char datatoc_gpu_shader_text_vert_glsl[];
extern char datatoc_gpu_shader_text_geom_glsl[];
extern char datatoc_gpu_shader_text_frag_glsl[];
@@ -729,23 +720,28 @@ void GPU_shader_uniform_vector(
return;
}
- if (length == 1) {
- glUniform1fv(location, arraysize, value);
- }
- else if (length == 2) {
- glUniform2fv(location, arraysize, value);
- }
- else if (length == 3) {
- glUniform3fv(location, arraysize, value);
- }
- else if (length == 4) {
- glUniform4fv(location, arraysize, value);
- }
- else if (length == 9) {
- glUniformMatrix3fv(location, arraysize, 0, value);
- }
- else if (length == 16) {
- glUniformMatrix4fv(location, arraysize, 0, value);
+ switch (length) {
+ case 1:
+ glUniform1fv(location, arraysize, value);
+ break;
+ case 2:
+ glUniform2fv(location, arraysize, value);
+ break;
+ case 3:
+ glUniform3fv(location, arraysize, value);
+ break;
+ case 4:
+ glUniform4fv(location, arraysize, value);
+ break;
+ case 9:
+ glUniformMatrix3fv(location, arraysize, 0, value);
+ break;
+ case 16:
+ glUniformMatrix4fv(location, arraysize, 0, value);
+ break;
+ default:
+ BLI_assert(0);
+ break;
}
}
@@ -756,17 +752,22 @@ void GPU_shader_uniform_vector_int(
return;
}
- if (length == 1) {
- glUniform1iv(location, arraysize, value);
- }
- else if (length == 2) {
- glUniform2iv(location, arraysize, value);
- }
- else if (length == 3) {
- glUniform3iv(location, arraysize, value);
- }
- else if (length == 4) {
- glUniform4iv(location, arraysize, value);
+ switch (length) {
+ case 1:
+ glUniform1iv(location, arraysize, value);
+ break;
+ case 2:
+ glUniform2iv(location, arraysize, value);
+ break;
+ case 3:
+ glUniform3iv(location, arraysize, value);
+ break;
+ case 4:
+ glUniform4iv(location, arraysize, value);
+ break;
+ default:
+ BLI_assert(0);
+ break;
}
}
@@ -832,30 +833,6 @@ static const GPUShaderStages builtin_shader_stages[GPU_SHADER_BUILTIN_LEN] = {
.vert = datatoc_gpu_shader_keyframe_diamond_vert_glsl,
.frag = datatoc_gpu_shader_keyframe_diamond_frag_glsl,
},
- /* This version is magical but slow! */
- [GPU_SHADER_EDGES_FRONT_BACK_PERSP] =
- {
- .vert = datatoc_gpu_shader_edges_front_back_persp_vert_glsl,
- .geom = datatoc_gpu_shader_edges_front_back_persp_geom_glsl,
- .frag = datatoc_gpu_shader_flat_color_frag_glsl,
- },
- [GPU_SHADER_EDGES_FRONT_BACK_ORTHO] =
- {
- .vert = datatoc_gpu_shader_edges_front_back_ortho_vert_glsl,
- .frag = datatoc_gpu_shader_flat_color_frag_glsl,
- },
- [GPU_SHADER_EDGES_OVERLAY_SIMPLE] =
- {
- .vert = datatoc_gpu_shader_3D_vert_glsl,
- .geom = datatoc_gpu_shader_edges_overlay_simple_geom_glsl,
- .frag = datatoc_gpu_shader_edges_overlay_frag_glsl,
- },
- [GPU_SHADER_EDGES_OVERLAY] =
- {
- .vert = datatoc_gpu_shader_edges_overlay_vert_glsl,
- .geom = datatoc_gpu_shader_edges_overlay_geom_glsl,
- .frag = datatoc_gpu_shader_edges_overlay_frag_glsl,
- },
[GPU_SHADER_SIMPLE_LIGHTING] =
{
.vert = datatoc_gpu_shader_3D_normal_vert_glsl,
@@ -1322,28 +1299,8 @@ GPUShader *GPU_shader_get_builtin_shader_with_config(eGPUBuiltinShader shader,
GPUShader **sh_p = &builtin_shaders[sh_cfg][shader];
if (*sh_p == NULL) {
- GPUShaderStages stages_legacy = {NULL};
const GPUShaderStages *stages = &builtin_shader_stages[shader];
- if (shader == GPU_SHADER_EDGES_FRONT_BACK_PERSP) {
- /* TODO: remove after switch to core profile (maybe) */
- if (!GLEW_VERSION_3_2) {
- stages_legacy.vert = datatoc_gpu_shader_edges_front_back_persp_legacy_vert_glsl;
- stages_legacy.frag = datatoc_gpu_shader_flat_color_alpha_test_0_frag_glsl;
- stages = &stages_legacy;
- }
- }
- else if (shader == GPU_SHADER_3D_LINE_DASHED_UNIFORM_COLOR) {
- /* Dashed need geometry shader, which are not supported by legacy OpenGL,
- * fallback to solid lines. */
- /* TODO: remove after switch to core profile (maybe) */
- if (!GLEW_VERSION_3_2) {
- stages_legacy.vert = datatoc_gpu_shader_3D_line_dashed_uniform_color_legacy_vert_glsl;
- stages_legacy.frag = datatoc_gpu_shader_2D_line_dashed_frag_glsl;
- stages = &stages_legacy;
- }
- }
-
/* common case */
if (sh_cfg == GPU_SHADER_CFG_DEFAULT) {
*sh_p = GPU_shader_create(
diff --git a/source/blender/gpu/intern/gpu_shader_interface.c b/source/blender/gpu/intern/gpu_shader_interface.c
index 698499af1ab..3993ee4df24 100644
--- a/source/blender/gpu/intern/gpu_shader_interface.c
+++ b/source/blender/gpu/intern/gpu_shader_interface.c
@@ -61,13 +61,9 @@ static const char *BuiltinUniform_name(GPUUniformBuiltin u)
[GPU_UNIFORM_VIEWPROJECTION_INV] = "ViewProjectionMatrixInverse",
[GPU_UNIFORM_NORMAL] = "NormalMatrix",
- [GPU_UNIFORM_NORMAL_INV] = "NormalMatrixInverse",
- [GPU_UNIFORM_WORLDNORMAL] = "WorldNormalMatrix",
- [GPU_UNIFORM_CAMERATEXCO] = "CameraTexCoFactors",
[GPU_UNIFORM_ORCO] = "OrcoTexCoFactors",
[GPU_UNIFORM_COLOR] = "color",
- [GPU_UNIFORM_EYE] = "eye",
[GPU_UNIFORM_CALLID] = "callId",
[GPU_UNIFORM_OBJECT_INFO] = "unfobjectinfo",
diff --git a/source/blender/gpu/intern/gpu_texture.c b/source/blender/gpu/intern/gpu_texture.c
index 61f86e70898..58d0dd5576f 100644
--- a/source/blender/gpu/intern/gpu_texture.c
+++ b/source/blender/gpu/intern/gpu_texture.c
@@ -544,6 +544,8 @@ static bool gpu_texture_check_capacity(
return false;
}
ATTR_FALLTHROUGH;
+ default:
+ break;
}
return true;
@@ -1079,7 +1081,7 @@ GPUTexture *GPU_texture_from_preview(PreviewImage *prv, int mipmap)
/* this binds a texture, so that's why we restore it to 0 */
if (bindcode == 0) {
GPU_create_gl_tex(
- &bindcode, prv->rect[0], NULL, prv->w[0], prv->h[0], GL_TEXTURE_2D, mipmap, 0, NULL);
+ &bindcode, prv->rect[0], NULL, prv->w[0], prv->h[0], GL_TEXTURE_2D, mipmap, false, NULL);
}
if (tex) {
tex->bindcode = bindcode;
diff --git a/source/blender/gpu/intern/gpu_vertex_buffer.c b/source/blender/gpu/intern/gpu_vertex_buffer.c
index f9823c18723..2f854fe03ea 100644
--- a/source/blender/gpu/intern/gpu_vertex_buffer.c
+++ b/source/blender/gpu/intern/gpu_vertex_buffer.c
@@ -85,17 +85,24 @@ void GPU_vertbuf_init_with_format_ex(GPUVertBuf *verts,
}
}
-void GPU_vertbuf_discard(GPUVertBuf *verts)
+/** Same as discard but does not free. */
+void GPU_vertbuf_clear(GPUVertBuf *verts)
{
if (verts->vbo_id) {
GPU_buf_free(verts->vbo_id);
+ verts->vbo_id = 0;
#if VRAM_USAGE
vbo_memory_usage -= GPU_vertbuf_size_get(verts);
#endif
}
if (verts->data) {
- MEM_freeN(verts->data);
+ MEM_SAFE_FREE(verts->data);
}
+}
+
+void GPU_vertbuf_discard(GPUVertBuf *verts)
+{
+ GPU_vertbuf_clear(verts);
MEM_freeN(verts);
}
diff --git a/source/blender/gpu/intern/gpu_vertex_format.c b/source/blender/gpu/intern/gpu_vertex_format.c
index 388773afbbc..37e1f9cf9da 100644
--- a/source/blender/gpu/intern/gpu_vertex_format.c
+++ b/source/blender/gpu/intern/gpu_vertex_format.c
@@ -58,12 +58,6 @@ void GPU_vertformat_copy(GPUVertFormat *dest, const GPUVertFormat *src)
{
/* copy regular struct fields */
memcpy(dest, src, sizeof(GPUVertFormat));
-
- for (uint i = 0; i < dest->attr_len; i++) {
- for (uint j = 0; j < dest->attrs[i].name_len; j++) {
- dest->attrs[i].name[j] = (char *)dest + (src->attrs[i].name[j] - ((char *)src));
- }
- }
}
static GLenum convert_comp_type_to_gl(GPUVertCompType type)
@@ -122,32 +116,20 @@ uint vertex_buffer_size(const GPUVertFormat *format, uint vertex_len)
return format->stride * vertex_len;
}
-static const char *copy_attr_name(GPUVertFormat *format, const char *name, const char *suffix)
+static uchar copy_attr_name(GPUVertFormat *format, const char *name)
{
/* strncpy does 110% of what we need; let's do exactly 100% */
- char *name_copy = format->names + format->name_offset;
- uint available = GPU_VERT_ATTR_NAMES_BUF_LEN - format->name_offset;
+ uchar name_offset = format->name_offset;
+ char *name_copy = format->names + name_offset;
+ uint available = GPU_VERT_ATTR_NAMES_BUF_LEN - name_offset;
bool terminated = false;
for (uint i = 0; i < available; ++i) {
const char c = name[i];
name_copy[i] = c;
if (c == '\0') {
- if (suffix) {
- for (uint j = 0; j < available; ++j) {
- const char s = suffix[j];
- name_copy[i + j] = s;
- if (s == '\0') {
- terminated = true;
- format->name_offset += (i + j + 1);
- break;
- }
- }
- }
- else {
- terminated = true;
- format->name_offset += (i + 1);
- }
+ terminated = true;
+ format->name_offset += (i + 1);
break;
}
}
@@ -157,7 +139,7 @@ static const char *copy_attr_name(GPUVertFormat *format, const char *name, const
#else
(void)terminated;
#endif
- return name_copy;
+ return name_offset;
}
uint GPU_vertformat_attr_add(GPUVertFormat *format,
@@ -196,7 +178,7 @@ uint GPU_vertformat_attr_add(GPUVertFormat *format,
const uint attr_id = format->attr_len++;
GPUVertAttr *attr = &format->attrs[attr_id];
- attr->name[attr->name_len++] = copy_attr_name(format, name, NULL);
+ attr->names[attr->name_len++] = copy_attr_name(format, name);
attr->comp_type = comp_type;
attr->gl_comp_type = convert_comp_type_to_gl(comp_type);
attr->comp_len = (comp_type == GPU_COMP_I10) ?
@@ -217,7 +199,7 @@ void GPU_vertformat_alias_add(GPUVertFormat *format, const char *alias)
assert(attr->name_len < GPU_VERT_ATTR_MAX_NAMES);
#endif
format->name_len++; /* multiname support */
- attr->name[attr->name_len++] = copy_attr_name(format, alias, NULL);
+ attr->names[attr->name_len++] = copy_attr_name(format, alias);
}
int GPU_vertformat_attr_id_get(const GPUVertFormat *format, const char *name)
@@ -225,7 +207,8 @@ int GPU_vertformat_attr_id_get(const GPUVertFormat *format, const char *name)
for (int i = 0; i < format->attr_len; i++) {
const GPUVertAttr *attr = &format->attrs[i];
for (int j = 0; j < attr->name_len; j++) {
- if (STREQ(name, attr->name[j])) {
+ const char *attr_name = GPU_vertformat_attr_name_get(format, attr, j);
+ if (STREQ(name, attr_name)) {
return i;
}
}
@@ -233,41 +216,6 @@ int GPU_vertformat_attr_id_get(const GPUVertFormat *format, const char *name)
return -1;
}
-void GPU_vertformat_triple_load(GPUVertFormat *format)
-{
-#if TRUST_NO_ONE
- assert(!format->packed);
- assert(format->attr_len * 3 < GPU_VERT_ATTR_MAX_LEN);
- assert(format->name_len + format->attr_len * 3 < GPU_VERT_ATTR_MAX_LEN);
-#endif
-
- VertexFormat_pack(format);
-
- uint old_attr_len = format->attr_len;
- for (uint a_idx = 0; a_idx < old_attr_len; ++a_idx) {
- GPUVertAttr *attr = &format->attrs[a_idx];
- /* Duplicate attr twice */
- for (int i = 1; i < 3; ++i) {
- GPUVertAttr *dst_attr = &format->attrs[format->attr_len];
- memcpy(dst_attr, attr, sizeof(GPUVertAttr));
- /* Increase offset to the next vertex. */
- dst_attr->offset += format->stride * i;
- /* Only copy first name for now. */
- dst_attr->name_len = 0;
- dst_attr->name[dst_attr->name_len++] = copy_attr_name(
- format, attr->name[0], (i == 1) ? "1" : "2");
- format->attr_len++;
- }
-
-#if TRUST_NO_ONE
- assert(attr->name_len < GPU_VERT_ATTR_MAX_NAMES);
-#endif
- /* Add alias to first attr. */
- format->name_len++;
- attr->name[attr->name_len++] = copy_attr_name(format, attr->name[0], "0");
- }
-}
-
uint padding(uint offset, uint alignment)
{
const uint mod = offset % alignment;
@@ -364,7 +312,6 @@ static uint calc_input_component_size(const GPUShaderInput *input)
static void get_fetch_mode_and_comp_type(int gl_type,
GPUVertCompType *r_comp_type,
- uint *r_gl_comp_type,
GPUVertFetchMode *r_fetch_mode)
{
switch (gl_type) {
@@ -382,7 +329,6 @@ static void get_fetch_mode_and_comp_type(int gl_type,
case GL_FLOAT_MAT4x2:
case GL_FLOAT_MAT4x3:
*r_comp_type = GPU_COMP_F32;
- *r_gl_comp_type = GL_FLOAT;
*r_fetch_mode = GPU_FETCH_FLOAT;
break;
case GL_INT:
@@ -390,7 +336,6 @@ static void get_fetch_mode_and_comp_type(int gl_type,
case GL_INT_VEC3:
case GL_INT_VEC4:
*r_comp_type = GPU_COMP_I32;
- *r_gl_comp_type = GL_INT;
*r_fetch_mode = GPU_FETCH_INT;
break;
case GL_UNSIGNED_INT:
@@ -398,7 +343,6 @@ static void get_fetch_mode_and_comp_type(int gl_type,
case GL_UNSIGNED_INT_VEC3:
case GL_UNSIGNED_INT_VEC4:
*r_comp_type = GPU_COMP_U32;
- *r_gl_comp_type = GL_UNSIGNED_INT;
*r_fetch_mode = GPU_FETCH_INT;
break;
default:
@@ -424,15 +368,19 @@ void GPU_vertformat_from_interface(GPUVertFormat *format, const GPUShaderInterfa
format->name_len++; /* multiname support */
format->attr_len++;
+ GPUVertCompType comp_type;
+ GPUVertFetchMode fetch_mode;
+ get_fetch_mode_and_comp_type(input->gl_type, &comp_type, &fetch_mode);
+
GPUVertAttr *attr = &format->attrs[input->location];
- attr->name[attr->name_len++] = copy_attr_name(
- format, name_buffer + input->name_offset, NULL);
+ attr->names[attr->name_len++] = copy_attr_name(format, name_buffer + input->name_offset);
attr->offset = 0; /* offsets & stride are calculated later (during pack) */
attr->comp_len = calc_input_component_size(input);
attr->sz = attr->comp_len * 4;
- get_fetch_mode_and_comp_type(
- input->gl_type, &attr->comp_type, &attr->gl_comp_type, &attr->fetch_mode);
+ attr->fetch_mode = fetch_mode;
+ attr->comp_type = comp_type;
+ attr->gl_comp_type = convert_comp_type_to_gl(comp_type);
}
}
}
diff --git a/source/blender/gpu/intern/gpu_viewport.c b/source/blender/gpu/intern/gpu_viewport.c
index 558b3f025a8..4fd439f4203 100644
--- a/source/blender/gpu/intern/gpu_viewport.c
+++ b/source/blender/gpu/intern/gpu_viewport.c
@@ -27,7 +27,7 @@
#include "BLI_listbase.h"
#include "BLI_rect.h"
-#include "BLI_mempool.h"
+#include "BLI_memblock.h"
#include "BIF_gl.h"
@@ -48,6 +48,8 @@
static const int default_fbl_len = (sizeof(DefaultFramebufferList)) / sizeof(void *);
static const int default_txl_len = (sizeof(DefaultTextureList)) / sizeof(void *);
+#define MAX_ENABLE_ENGINE 8
+
/* Maximum number of simultaneous engine enabled at the same time.
* Setting it lower than the real number will do lead to
* higher VRAM usage due to sub-efficient buffer reuse. */
@@ -64,8 +66,11 @@ struct GPUViewport {
int samples;
int flag;
- ListBase data; /* ViewportEngineData wrapped in LinkData */
- uint data_hash; /* If hash mismatch we free all ViewportEngineData in this viewport */
+ /* If engine_handles mismatch we free all ViewportEngineData in this viewport */
+ struct {
+ void *handle;
+ ViewportEngineData *data;
+ } engine_data[MAX_ENABLE_ENGINE];
DefaultFramebufferList *fbl;
DefaultTextureList *txl;
@@ -172,7 +177,6 @@ void GPU_viewport_clear_from_offscreen(GPUViewport *viewport)
void *GPU_viewport_engine_data_create(GPUViewport *viewport, void *engine_type)
{
- LinkData *ld = MEM_callocN(sizeof(LinkData), "LinkData");
ViewportEngineData *data = MEM_callocN(sizeof(ViewportEngineData), "ViewportEngineData");
int fbl_len, txl_len, psl_len, stl_len;
@@ -185,20 +189,25 @@ void *GPU_viewport_engine_data_create(GPUViewport *viewport, void *engine_type)
data->psl = MEM_callocN((sizeof(void *) * psl_len) + sizeof(PassList), "PassList");
data->stl = MEM_callocN((sizeof(void *) * stl_len) + sizeof(StorageList), "StorageList");
- ld->data = data;
- BLI_addtail(&viewport->data, ld);
+ for (int i = 0; i < MAX_ENABLE_ENGINE; i++) {
+ if (viewport->engine_data[i].handle == NULL) {
+ viewport->engine_data[i].handle = engine_type;
+ viewport->engine_data[i].data = data;
+ return data;
+ }
+ }
- return data;
+ BLI_assert(!"Too many draw engines enabled at the same time");
+ return NULL;
}
static void gpu_viewport_engines_data_free(GPUViewport *viewport)
{
int fbl_len, txl_len, psl_len, stl_len;
- LinkData *next;
- for (LinkData *link = viewport->data.first; link; link = next) {
- next = link->next;
- ViewportEngineData *data = link->data;
+ for (int i = 0; i < MAX_ENABLE_ENGINE && viewport->engine_data[i].handle; i++) {
+ ViewportEngineData *data = viewport->engine_data[i].data;
+
DRW_engine_viewport_data_size_get(data->engine_type, &fbl_len, &txl_len, &psl_len, &stl_len);
gpu_viewport_buffers_free(data->fbl, fbl_len, data->txl, txl_len);
@@ -219,19 +228,20 @@ static void gpu_viewport_engines_data_free(GPUViewport *viewport)
MEM_freeN(data);
- BLI_remlink(&viewport->data, link);
- MEM_freeN(link);
+ /* Mark as unused*/
+ viewport->engine_data[i].handle = NULL;
}
gpu_viewport_texture_pool_free(viewport);
}
-void *GPU_viewport_engine_data_get(GPUViewport *viewport, void *engine_type)
+void *GPU_viewport_engine_data_get(GPUViewport *viewport, void *engine_handle)
{
- for (LinkData *link = viewport->data.first; link; link = link->next) {
- ViewportEngineData *vdata = link->data;
- if (vdata->engine_type == engine_type) {
- return vdata;
+ BLI_assert(engine_handle != NULL);
+
+ for (int i = 0; i < MAX_ENABLE_ENGINE; i++) {
+ if (viewport->engine_data[i].handle == engine_handle) {
+ return viewport->engine_data[i].data;
}
}
return NULL;
@@ -352,24 +362,22 @@ static void gpu_viewport_texture_pool_free(GPUViewport *viewport)
BLI_freelistN(&viewport->tex_pool);
}
-bool GPU_viewport_engines_data_validate(GPUViewport *viewport, uint hash)
+/* Takes an NULL terminated array of engine_handle. Returns true is data is still valid. */
+bool GPU_viewport_engines_data_validate(GPUViewport *viewport, void **engine_handle_array)
{
- bool dirty = false;
-
- if (viewport->data_hash != hash) {
- gpu_viewport_engines_data_free(viewport);
- dirty = true;
+ for (int i = 0; i < MAX_ENABLE_ENGINE && engine_handle_array[i]; i++) {
+ if (viewport->engine_data[i].handle != engine_handle_array[i]) {
+ gpu_viewport_engines_data_free(viewport);
+ return false;
+ }
}
-
- viewport->data_hash = hash;
-
- return dirty;
+ return true;
}
void GPU_viewport_cache_release(GPUViewport *viewport)
{
- for (LinkData *link = viewport->data.first; link; link = link->next) {
- ViewportEngineData *data = link->data;
+ for (int i = 0; i < MAX_ENABLE_ENGINE && viewport->engine_data[i].handle; i++) {
+ ViewportEngineData *data = viewport->engine_data[i].data;
int psl_len;
DRW_engine_viewport_data_size_get(data->engine_type, NULL, NULL, &psl_len, NULL);
gpu_viewport_passes_free(data->psl, psl_len);
@@ -468,8 +476,8 @@ void GPU_viewport_bind(GPUViewport *viewport, const rcti *rect)
(TextureList *)viewport->txl,
default_txl_len);
- for (LinkData *link = viewport->data.first; link; link = link->next) {
- ViewportEngineData *data = link->data;
+ for (int i = 0; i < MAX_ENABLE_ENGINE && viewport->engine_data[i].handle; i++) {
+ ViewportEngineData *data = viewport->engine_data[i].data;
DRW_engine_viewport_data_size_get(data->engine_type, &fbl_len, &txl_len, NULL, NULL);
gpu_viewport_buffers_free(data->fbl, fbl_len, data->txl, txl_len);
}
@@ -593,13 +601,7 @@ static void gpu_viewport_storage_free(StorageList *stl, int stl_len)
static void gpu_viewport_passes_free(PassList *psl, int psl_len)
{
- for (int i = 0; i < psl_len; i++) {
- struct DRWPass *pass = psl->passes[i];
- if (pass) {
- DRW_pass_free(pass);
- psl->passes[i] = NULL;
- }
- }
+ memset(psl, 0, sizeof(struct DRWPass *) * psl_len);
}
/* Must be executed inside Drawmanager Opengl Context. */
@@ -618,28 +620,34 @@ void GPU_viewport_free(GPUViewport *viewport)
MEM_freeN(viewport->txl);
if (viewport->vmempool.calls != NULL) {
- BLI_mempool_destroy(viewport->vmempool.calls);
+ BLI_memblock_destroy(viewport->vmempool.calls, NULL);
}
if (viewport->vmempool.states != NULL) {
- BLI_mempool_destroy(viewport->vmempool.states);
+ 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_mempool_destroy(viewport->vmempool.shgroups);
+ BLI_memblock_destroy(viewport->vmempool.shgroups, NULL);
}
if (viewport->vmempool.uniforms != NULL) {
- BLI_mempool_destroy(viewport->vmempool.uniforms);
+ 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_mempool_destroy(viewport->vmempool.passes);
+ BLI_memblock_destroy(viewport->vmempool.passes, NULL);
}
if (viewport->vmempool.images != NULL) {
- BLI_mempool_iter iter;
+ BLI_memblock_iter iter;
GPUTexture **tex;
- BLI_mempool_iternew(viewport->vmempool.images, &iter);
- while ((tex = BLI_mempool_iterstep(&iter))) {
+ BLI_memblock_iternew(viewport->vmempool.images, &iter);
+ while ((tex = BLI_memblock_iterstep(&iter))) {
GPU_texture_free(*tex);
}
- BLI_mempool_destroy(viewport->vmempool.images);
+ BLI_memblock_destroy(viewport->vmempool.images, NULL);
}
DRW_instance_data_list_free(viewport->idatalist);
diff --git a/source/blender/gpu/shaders/gpu_shader_edges_front_back_ortho_vert.glsl b/source/blender/gpu/shaders/gpu_shader_edges_front_back_ortho_vert.glsl
deleted file mode 100644
index a71dfba575b..00000000000
--- a/source/blender/gpu/shaders/gpu_shader_edges_front_back_ortho_vert.glsl
+++ /dev/null
@@ -1,54 +0,0 @@
-
-// Draw "fancy" wireframe, displaying front-facing, back-facing and
-// silhouette lines differently.
-// Mike Erwin, April 2015
-
-uniform bool drawFront = true;
-uniform bool drawBack = true;
-uniform bool drawSilhouette = true;
-
-uniform vec4 frontColor;
-uniform vec4 backColor;
-uniform vec4 silhouetteColor;
-
-uniform vec3 eye; // direction we are looking
-
-uniform mat4 ModelViewProjectionMatrix;
-
-in vec3 pos;
-
-// normals of faces this edge joins (object coords)
-in vec3 N1;
-in vec3 N2;
-
-flat out vec4 finalColor;
-
-// TODO: in float angle; // [-pi .. +pi], + peak, 0 flat, - valley
-
-// to discard an entire line, set both endpoints to nowhere
-// and it won't produce any fragments
-const vec4 nowhere = vec4(vec3(0.0), 1.0);
-
-void main()
-{
- bool face_1_front = dot(N1, eye) > 0.0;
- bool face_2_front = dot(N2, eye) > 0.0;
-
- vec4 position = ModelViewProjectionMatrix * vec4(pos, 1.0);
-
- if (face_1_front && face_2_front) {
- // front-facing edge
- gl_Position = drawFront ? position : nowhere;
- finalColor = frontColor;
- }
- else if (face_1_front || face_2_front) {
- // exactly one face is front-facing, silhouette edge
- gl_Position = drawSilhouette ? position : nowhere;
- finalColor = silhouetteColor;
- }
- else {
- // back-facing edge
- gl_Position = drawBack ? position : nowhere;
- finalColor = backColor;
- }
-}
diff --git a/source/blender/gpu/shaders/gpu_shader_edges_front_back_persp_geom.glsl b/source/blender/gpu/shaders/gpu_shader_edges_front_back_persp_geom.glsl
deleted file mode 100644
index 3de14704781..00000000000
--- a/source/blender/gpu/shaders/gpu_shader_edges_front_back_persp_geom.glsl
+++ /dev/null
@@ -1,60 +0,0 @@
-
-// Draw "fancy" wireframe, displaying front-facing, back-facing and
-// silhouette lines differently.
-// Mike Erwin, April 2015
-
-// After working with this shader a while, convinced we should make
-// separate shaders for perpective & ortho. (Oct 2016)
-
-// Due to perspective, the line segment's endpoints might disagree on
-// whether the adjacent faces are front facing. This geometry shader
-// decides which edge type to use if endpoints disagree.
-
-uniform mat4 ProjectionMatrix;
-
-uniform bool drawFront = true;
-uniform bool drawBack = true;
-uniform bool drawSilhouette = true;
-
-uniform vec4 frontColor;
-uniform vec4 backColor;
-uniform vec4 silhouetteColor;
-
-layout(lines) in;
-layout(line_strip, max_vertices = 2) out;
-
-in vec4 MV_pos[];
-in float edgeClass[];
-
-flat out vec4 finalColor;
-
-void emitLine(vec4 color)
-{
- gl_Position = ProjectionMatrix * MV_pos[0];
- EmitVertex();
- gl_Position = ProjectionMatrix * MV_pos[1];
- finalColor = color;
- EmitVertex();
- EndPrimitive();
-}
-
-void main()
-{
- float finalEdgeClass = max(edgeClass[0], edgeClass[1]);
-
- if (finalEdgeClass > 0.0f) {
- // front-facing edge
- if (drawFront)
- emitLine(frontColor);
- }
- else if (finalEdgeClass < 0.0f) {
- // back-facing edge
- if (drawBack)
- emitLine(backColor);
- }
- else {
- // exactly one face is front-facing, silhouette edge
- if (drawSilhouette)
- emitLine(silhouetteColor);
- }
-}
diff --git a/source/blender/gpu/shaders/gpu_shader_edges_front_back_persp_legacy_vert.glsl b/source/blender/gpu/shaders/gpu_shader_edges_front_back_persp_legacy_vert.glsl
deleted file mode 100644
index ffd52a0a225..00000000000
--- a/source/blender/gpu/shaders/gpu_shader_edges_front_back_persp_legacy_vert.glsl
+++ /dev/null
@@ -1,68 +0,0 @@
-
-// Draw "fancy" wireframe, displaying front-facing, back-facing and
-// silhouette lines differently.
-// Mike Erwin, April 2015
-
-// After working with this shader a while, convinced we should make
-// separate shaders for perpective & ortho. (Oct 2016)
-
-// This shader is an imperfect stepping stone until all platforms are
-// ready for geometry shaders.
-
-// Due to perspective, the line segment's endpoints might disagree on
-// whether the adjacent faces are front facing. Need to use a geometry
-// shader or pass in an extra position attribute (the other endpoint)
-// to do this properly.
-
-uniform bool drawFront = true;
-uniform bool drawBack = true;
-uniform bool drawSilhouette = true;
-
-uniform vec4 frontColor;
-uniform vec4 backColor;
-uniform vec4 silhouetteColor;
-
-uniform mat4 ModelViewMatrix;
-uniform mat4 ModelViewProjectionMatrix;
-uniform mat3 NormalMatrix;
-
-in vec3 pos;
-
-// normals of faces this edge joins (object coords)
-in vec3 N1;
-in vec3 N2;
-
-flat out vec4 finalColor;
-
-// TODO: in float angle; // [-pi .. +pi], + peak, 0 flat, - valley
-
-// to discard an entire line, set its color to invisible
-// (must have GL_BLEND enabled, or discard in fragment shader)
-const vec4 invisible = vec4(0.0);
-
-bool front(vec3 N)
-{
- vec4 xformed = ModelViewMatrix * vec4(pos, 1.0);
- return dot(NormalMatrix * N, normalize(-xformed.xyz)) > 0.0;
-}
-
-void main()
-{
- bool face_1_front = front(N1);
- bool face_2_front = front(N2);
-
- gl_Position = ModelViewProjectionMatrix * vec4(pos, 1.0);
-
- if (face_1_front && face_2_front) {
- // front-facing edge
- finalColor = drawFront ? frontColor : invisible;
- }
- else if (face_1_front || face_2_front) {
- // exactly one face is front-facing, silhouette edge
- finalColor = drawSilhouette ? silhouetteColor : invisible;
- }
- else {
- // back-facing edge
- finalColor = drawBack ? backColor : invisible;
- }
-}
diff --git a/source/blender/gpu/shaders/gpu_shader_edges_front_back_persp_vert.glsl b/source/blender/gpu/shaders/gpu_shader_edges_front_back_persp_vert.glsl
deleted file mode 100644
index c8b722e1d7e..00000000000
--- a/source/blender/gpu/shaders/gpu_shader_edges_front_back_persp_vert.glsl
+++ /dev/null
@@ -1,44 +0,0 @@
-
-// Draw "fancy" wireframe, displaying front-facing, back-facing and
-// silhouette lines differently.
-// Mike Erwin, April 2015
-
-// After working with this shader a while, convinced we should make
-// separate shaders for perpective & ortho. (Oct 2016)
-
-// Due to perspective, the line segment's endpoints might disagree on
-// whether the adjacent faces are front facing. We use a geometry
-// shader to resolve this properly.
-
-uniform mat4 ModelViewMatrix;
-uniform mat3 NormalMatrix;
-
-in vec3 pos;
-in vec3 N1, N2; // normals of faces this edge joins (object coords)
-
-out vec4 MV_pos;
-out float edgeClass;
-
-// TODO: in float angle; // [-pi .. +pi], + peak, 0 flat, - valley
-
-bool front(vec3 N, vec3 eye)
-{
- return dot(NormalMatrix * N, eye) > 0.0;
-}
-
-void main()
-{
- MV_pos = ModelViewMatrix * vec4(pos, 1.0);
-
- vec3 eye = normalize(-MV_pos.xyz);
-
- bool face_1_front = front(N1, eye);
- bool face_2_front = front(N2, eye);
-
- if (face_1_front && face_2_front)
- edgeClass = 1.0; // front-facing edge
- else if (face_1_front || face_2_front)
- edgeClass = 0.0; // exactly one face is front-facing, silhouette edge
- else
- edgeClass = -1.0; // back-facing edge
-}
diff --git a/source/blender/gpu/shaders/gpu_shader_edges_overlay_frag.glsl b/source/blender/gpu/shaders/gpu_shader_edges_overlay_frag.glsl
deleted file mode 100644
index 7b35f67dd54..00000000000
--- a/source/blender/gpu/shaders/gpu_shader_edges_overlay_frag.glsl
+++ /dev/null
@@ -1,21 +0,0 @@
-
-#define SMOOTH 1
-
-const float transitionWidth = 1.0;
-
-uniform vec4 fillColor = vec4(0);
-uniform vec4 outlineColor = vec4(0, 0, 0, 1);
-
-noperspective in vec3 distanceToOutline;
-
-out vec4 FragColor;
-
-void main()
-{
- float edgeness = min(min(distanceToOutline.x, distanceToOutline.y), distanceToOutline.z);
-#if SMOOTH
- FragColor = mix(outlineColor, fillColor, smoothstep(0, transitionWidth, edgeness));
-#else
- FragColor = (edgeness <= 0) ? outlineColor : fillColor;
-#endif
-}
diff --git a/source/blender/gpu/shaders/gpu_shader_edges_overlay_geom.glsl b/source/blender/gpu/shaders/gpu_shader_edges_overlay_geom.glsl
deleted file mode 100644
index 48fff1629fd..00000000000
--- a/source/blender/gpu/shaders/gpu_shader_edges_overlay_geom.glsl
+++ /dev/null
@@ -1,72 +0,0 @@
-layout(triangles) in;
-layout(triangle_strip, max_vertices = 3) out;
-
-uniform float outlineWidth = 1.0;
-uniform vec2 viewportSize;
-
-in vec4 pos_xformed[];
-in float widthModulator[];
-
-noperspective out vec3 distanceToOutline;
-
-// project to screen space
-vec2 proj(int axis)
-{
- vec4 pos = pos_xformed[axis];
- return (0.5 * (pos.xy / pos.w) + 0.5) * viewportSize;
-}
-
-float dist(vec2 pos[3], int v)
-{
- // current vertex position
- vec2 vpos = pos[v];
- // endpoints of opposite edge
- vec2 e1 = pos[(v + 1) % 3];
- vec2 e2 = pos[(v + 2) % 3];
-
- float abs_det = length(cross(vec3(vpos - e1, 0), vec3(vpos - e2, 0))); // could simplify
- return abs_det / distance(e2, e1);
-}
-
-vec3 distance[3];
-
-void clearEdge(int v)
-{
- float distant = 10 * outlineWidth;
- for (int i = 0; i < 3; ++i)
- distance[i][v] += distant;
-}
-
-void modulateEdge(int v)
-{
- float offset = min(widthModulator[v], 1) * outlineWidth;
- for (int i = 0; i < 3; ++i)
- distance[i][v] -= offset;
-}
-
-void main()
-{
- vec2 pos[3] = vec2[3](proj(0), proj(1), proj(2));
-
- for (int v = 0; v < 3; ++v)
- distance[v] = vec3(0);
-
- for (int v = 0; v < 3; ++v) {
- if (widthModulator[v] > 0) {
- distance[v][v] = dist(pos, v);
- modulateEdge(v);
- }
- }
-
- for (int v = 0; v < 3; ++v)
- if (widthModulator[v] <= 0)
- clearEdge(v);
-
- for (int v = 0; v < 3; ++v) {
- gl_Position = pos_xformed[v];
- distanceToOutline = distance[v];
- EmitVertex();
- }
-
- EndPrimitive();
-}
diff --git a/source/blender/gpu/shaders/gpu_shader_edges_overlay_simple_geom.glsl b/source/blender/gpu/shaders/gpu_shader_edges_overlay_simple_geom.glsl
deleted file mode 100644
index 12f5a2c7811..00000000000
--- a/source/blender/gpu/shaders/gpu_shader_edges_overlay_simple_geom.glsl
+++ /dev/null
@@ -1,56 +0,0 @@
-layout(triangles) in;
-layout(triangle_strip, max_vertices = 3) out;
-
-uniform float outlineWidth = 1.0;
-uniform vec2 viewportSize;
-
-noperspective out vec3 distanceToOutline;
-
-// project to screen space
-vec2 proj(int axis)
-{
- vec4 pos = gl_in[axis].gl_Position;
- return (0.5 * (pos.xy / pos.w) + 0.5) * viewportSize;
-}
-
-float dist(vec2 pos[3], int v)
-{
- // current vertex position
- vec2 vpos = pos[v];
- // endpoints of opposite edge
- vec2 e1 = pos[(v + 1) % 3];
- vec2 e2 = pos[(v + 2) % 3];
-
- float abs_det = length(cross(vec3(vpos - e1, 0), vec3(vpos - e2, 0))); // could simplify
- return abs_det / distance(e2, e1);
-}
-
-vec3 distance[3];
-
-void modulateEdge(int v)
-{
- float offset = 0.5 * outlineWidth;
- for (int i = 0; i < 3; ++i)
- distance[i][v] -= offset;
-}
-
-void main()
-{
- vec2 pos[3] = vec2[3](proj(0), proj(1), proj(2));
-
- for (int v = 0; v < 3; ++v)
- distance[v] = vec3(0);
-
- for (int v = 0; v < 3; ++v) {
- distance[v][v] = dist(pos, v);
- modulateEdge(v);
- }
-
- for (int v = 0; v < 3; ++v) {
- gl_Position = gl_in[v].gl_Position;
- distanceToOutline = distance[v];
- EmitVertex();
- }
-
- EndPrimitive();
-}
diff --git a/source/blender/gpu/shaders/gpu_shader_edges_overlay_vert.glsl b/source/blender/gpu/shaders/gpu_shader_edges_overlay_vert.glsl
deleted file mode 100644
index 33615ac36e5..00000000000
--- a/source/blender/gpu/shaders/gpu_shader_edges_overlay_vert.glsl
+++ /dev/null
@@ -1,14 +0,0 @@
-
-uniform mat4 ModelViewProjectionMatrix;
-
-in vec3 pos;
-in float edgeWidthModulator;
-
-out vec4 pos_xformed;
-out float widthModulator;
-
-void main()
-{
- pos_xformed = ModelViewProjectionMatrix * vec4(pos, 1.0);
- widthModulator = edgeWidthModulator;
-}
diff --git a/source/blender/gpu/shaders/gpu_shader_instance_edges_variying_color_vert.glsl b/source/blender/gpu/shaders/gpu_shader_instance_edges_variying_color_vert.glsl
index d9e73f81c45..62a526cae49 100644
--- a/source/blender/gpu/shaders/gpu_shader_instance_edges_variying_color_vert.glsl
+++ b/source/blender/gpu/shaders/gpu_shader_instance_edges_variying_color_vert.glsl
@@ -26,21 +26,21 @@ out vec3 fCol;
// TODO: in float angle; // [-pi .. +pi], + peak, 0 flat, - valley
-bool front(mat3 NormalMatrix, vec3 N, vec3 eye)
+bool front(mat3 normal_matrix, vec3 N, vec3 eye)
{
- return dot(NormalMatrix * N, eye) > 0.0;
+ return dot(normal_matrix * N, eye) > 0.0;
}
void main()
{
vec3 eye;
- mat4 ModelViewMatrix = ViewMatrix * InstanceModelMatrix;
+ mat4 model_view_matrix = ViewMatrix * InstanceModelMatrix;
vec4 pos_4d = vec4(pos, 1.0);
- MV_pos = ModelViewMatrix * pos_4d;
+ MV_pos = model_view_matrix * pos_4d;
- mat3 NormalMatrix = transpose(inverse(mat3(ModelViewMatrix)));
+ mat3 normal_matrix = transpose(inverse(mat3(model_view_matrix)));
/* if persp */
if (ProjectionMatrix[3][3] == 0.0) {
@@ -50,8 +50,8 @@ void main()
eye = vec3(0.0, 0.0, 1.0);
}
- bool face_1_front = front(NormalMatrix, N1, eye);
- bool face_2_front = front(NormalMatrix, N2, eye);
+ bool face_1_front = front(normal_matrix, N1, eye);
+ bool face_2_front = front(normal_matrix, N2, eye);
if (face_1_front && face_2_front)
edgeClass = 1.0; // front-facing edge
diff --git a/source/blender/gpu/shaders/gpu_shader_instance_objectspace_variying_color_vert.glsl b/source/blender/gpu/shaders/gpu_shader_instance_objectspace_variying_color_vert.glsl
index 9b1a08d8d86..5b3922d7a72 100644
--- a/source/blender/gpu/shaders/gpu_shader_instance_objectspace_variying_color_vert.glsl
+++ b/source/blender/gpu/shaders/gpu_shader_instance_objectspace_variying_color_vert.glsl
@@ -1,5 +1,5 @@
-uniform mat4 ViewMatrix;
+uniform mat4 ViewMatrixInverse;
uniform mat4 ViewProjectionMatrix;
/* ---- Instantiated Attrs ---- */
@@ -15,13 +15,12 @@ flat out vec4 finalColor;
void main()
{
- mat4 ModelViewProjectionMatrix = ViewProjectionMatrix * InstanceModelMatrix;
- /* This is slow and run per vertex, but it's still faster than
- * doing it per instance on CPU and sending it on via instance attr. */
- mat3 NormalMatrix = transpose(inverse(mat3(ViewMatrix * InstanceModelMatrix)));
+ gl_Position = ViewProjectionMatrix * (InstanceModelMatrix * vec4(pos, 1.0));
- gl_Position = ModelViewProjectionMatrix * vec4(pos, 1.0);
- normal = NormalMatrix * nor;
+ /* This is slow and run per vertex, but it's still faster than
+ * doing it per instance on CPU and sending it on via instance attribute. */
+ mat3 normal_mat = transpose(inverse(mat3(InstanceModelMatrix)));
+ normal = normalize((transpose(mat3(ViewMatrixInverse)) * (normal_mat * nor)));
finalColor = color;
}
diff --git a/source/blender/gpu/shaders/gpu_shader_material.glsl b/source/blender/gpu/shaders/gpu_shader_material.glsl
index cf7a83e8a87..b94a7d6cc0a 100644
--- a/source/blender/gpu/shaders/gpu_shader_material.glsl
+++ b/source/blender/gpu/shaders/gpu_shader_material.glsl
@@ -1,14 +1,4 @@
-uniform mat4 ModelViewMatrix;
-uniform mat4 ModelViewMatrixInverse;
-uniform mat3 NormalMatrix;
-uniform mat3 NormalMatrixInverse;
-
-#ifndef USE_ATTR
-uniform mat4 ModelMatrix;
-uniform mat4 ModelMatrixInverse;
-#endif
-
/* Converters */
float convert_rgba_to_float(vec4 color)
@@ -119,38 +109,6 @@ void hsv_to_rgb(vec4 hsv, out vec4 outcol)
outcol = vec4(rgb, hsv.w);
}
-float srgb_to_linearrgb(float c)
-{
- if (c < 0.04045)
- return (c < 0.0) ? 0.0 : c * (1.0 / 12.92);
- else
- return pow((c + 0.055) * (1.0 / 1.055), 2.4);
-}
-
-float linearrgb_to_srgb(float c)
-{
- if (c < 0.0031308)
- return (c < 0.0) ? 0.0 : c * 12.92;
- else
- return 1.055 * pow(c, 1.0 / 2.4) - 0.055;
-}
-
-void srgb_to_linearrgb(vec4 col_from, out vec4 col_to)
-{
- col_to.r = srgb_to_linearrgb(col_from.r);
- col_to.g = srgb_to_linearrgb(col_from.g);
- col_to.b = srgb_to_linearrgb(col_from.b);
- col_to.a = col_from.a;
-}
-
-void linearrgb_to_srgb(vec4 col_from, out vec4 col_to)
-{
- col_to.r = linearrgb_to_srgb(col_from.r);
- col_to.g = linearrgb_to_srgb(col_from.g);
- col_to.b = linearrgb_to_srgb(col_from.b);
- col_to.a = col_from.a;
-}
-
void color_to_normal_new_shading(vec3 color, out vec3 normal)
{
normal = vec3(2.0) * color - vec3(1.0);
@@ -204,9 +162,9 @@ void direction_transform_m4v3(vec3 vin, mat4 mat, out vec3 vout)
vout = (mat * vec4(vin, 0.0)).xyz;
}
-void mat3_mul(vec3 vin, mat3 mat, out vec3 vout)
+void normal_transform_transposed_m4v3(vec3 vin, mat4 mat, out vec3 vout)
{
- vout = mat * vin;
+ vout = transpose(mat3(mat)) * vin;
}
void point_transform_m4v3(vec3 vin, mat4 mat, out vec3 vout)
@@ -1162,8 +1120,9 @@ vec3 cellnoise_color(vec3 p)
float floorfrac(float x, out int i)
{
- i = floor_to_int(x);
- return x - i;
+ float x_floor = floor(x);
+ i = int(x_floor);
+ return x - x_floor;
}
/* bsdfs */
@@ -1275,6 +1234,8 @@ void node_bsdf_principled(vec4 base_color,
float ior,
float transmission,
float transmission_roughness,
+ vec4 emission,
+ float alpha,
vec3 N,
vec3 CN,
vec3 T,
@@ -1354,6 +1315,8 @@ void node_bsdf_principled(vec4 base_color,
# endif
result.sss_data.rgb *= (1.0 - transmission);
# endif
+ result.radiance += emission.rgb;
+ result.opacity = alpha;
}
void node_bsdf_principled_dielectric(vec4 base_color,
@@ -1373,6 +1336,8 @@ void node_bsdf_principled_dielectric(vec4 base_color,
float ior,
float transmission,
float transmission_roughness,
+ vec4 emission,
+ float alpha,
vec3 N,
vec3 CN,
vec3 T,
@@ -1402,6 +1367,8 @@ void node_bsdf_principled_dielectric(vec4 base_color,
result.ssr_data = vec4(ssr_spec, roughness);
result.ssr_normal = normal_encode(vN, viewCameraVec);
result.ssr_id = int(ssr_id);
+ result.radiance += emission.rgb;
+ result.opacity = alpha;
}
void node_bsdf_principled_metallic(vec4 base_color,
@@ -1421,6 +1388,8 @@ void node_bsdf_principled_metallic(vec4 base_color,
float ior,
float transmission,
float transmission_roughness,
+ vec4 emission,
+ float alpha,
vec3 N,
vec3 CN,
vec3 T,
@@ -1441,6 +1410,8 @@ void node_bsdf_principled_metallic(vec4 base_color,
result.ssr_data = vec4(ssr_spec, roughness);
result.ssr_normal = normal_encode(vN, viewCameraVec);
result.ssr_id = int(ssr_id);
+ result.radiance += emission.rgb;
+ result.opacity = alpha;
}
void node_bsdf_principled_clearcoat(vec4 base_color,
@@ -1460,6 +1431,8 @@ void node_bsdf_principled_clearcoat(vec4 base_color,
float ior,
float transmission,
float transmission_roughness,
+ vec4 emission,
+ float alpha,
vec3 N,
vec3 CN,
vec3 T,
@@ -1489,6 +1462,8 @@ void node_bsdf_principled_clearcoat(vec4 base_color,
result.ssr_data = vec4(ssr_spec, roughness);
result.ssr_normal = normal_encode(vN, viewCameraVec);
result.ssr_id = int(ssr_id);
+ result.radiance += emission.rgb;
+ result.opacity = alpha;
}
void node_bsdf_principled_subsurface(vec4 base_color,
@@ -1508,6 +1483,8 @@ void node_bsdf_principled_subsurface(vec4 base_color,
float ior,
float transmission,
float transmission_roughness,
+ vec4 emission,
+ float alpha,
vec3 N,
vec3 CN,
vec3 T,
@@ -1562,6 +1539,8 @@ void node_bsdf_principled_subsurface(vec4 base_color,
result.radiance += (out_diff + out_trans) * mixed_ss_base_color;
# endif
result.radiance += out_diff * out_sheen;
+ result.radiance += emission.rgb;
+ result.opacity = alpha;
}
void node_bsdf_principled_glass(vec4 base_color,
@@ -1581,6 +1560,8 @@ void node_bsdf_principled_glass(vec4 base_color,
float ior,
float transmission,
float transmission_roughness,
+ vec4 emission,
+ float alpha,
vec3 N,
vec3 CN,
vec3 T,
@@ -1615,6 +1596,8 @@ void node_bsdf_principled_glass(vec4 base_color,
result.ssr_data = vec4(ssr_spec, roughness);
result.ssr_normal = normal_encode(vN, viewCameraVec);
result.ssr_id = int(ssr_id);
+ result.radiance += emission.rgb;
+ result.opacity = alpha;
}
void node_bsdf_translucent(vec4 color, vec3 N, out Closure result)
@@ -1743,11 +1726,11 @@ void node_tex_environment_texco(vec3 viewvec, out vec3 worldvec)
vec4 v = (ProjectionMatrix[3][3] == 0.0) ? vec4(viewvec, 1.0) : vec4(0.0, 0.0, 1.0, 1.0);
vec4 co_homogenous = (ProjectionMatrixInverse * v);
- vec4 co = vec4(co_homogenous.xyz / co_homogenous.w, 0.0);
+ vec3 co = co_homogenous.xyz / co_homogenous.w;
# if defined(WORLD_BACKGROUND) || defined(PROBE_CAPTURE)
- worldvec = (ViewMatrixInverse * co).xyz;
+ worldvec = mat3(ViewMatrixInverse) * co;
# else
- worldvec = (ModelViewMatrixInverse * co).xyz;
+ worldvec = mat3(ModelMatrixInverse) * (mat3(ViewMatrixInverse) * co);
# endif
#endif
}
@@ -2014,18 +1997,13 @@ void tangent_orco_z(vec3 orco_in, out vec3 orco_out)
orco_out = orco_in.yxz * vec3(-0.5, 0.5, 0.0) + vec3(0.25, -0.25, 0.0);
}
-void node_tangentmap(vec4 attr_tangent, mat4 toworld, out vec3 tangent)
+void node_tangentmap(vec4 attr_tangent, out vec3 tangent)
{
- tangent = normalize((toworld * vec4(attr_tangent.xyz, 0.0)).xyz);
+ tangent = normalize(attr_tangent.xyz);
}
-void node_tangent(vec3 N, vec3 orco, mat4 objmat, mat4 toworld, out vec3 T)
+void node_tangent(vec3 N, vec3 orco, mat4 objmat, out vec3 T)
{
-#ifndef VOLUMETRICS
- N = normalize(gl_FrontFacing ? worldNormal : -worldNormal);
-#else
- N = (toworld * vec4(N, 0.0)).xyz;
-#endif
T = (objmat * vec4(orco, 0.0)).xyz;
T = cross(N, normalize(cross(T, N)));
}
@@ -2060,7 +2038,7 @@ void node_geometry(vec3 I,
position = worldPosition;
# ifndef VOLUMETRICS
- normal = normalize(gl_FrontFacing ? worldNormal : -worldNormal);
+ normal = normalize(N);
vec3 B = dFdx(worldPosition);
vec3 T = dFdy(worldPosition);
true_normal = normalize(cross(B, T));
@@ -2069,7 +2047,7 @@ void node_geometry(vec3 I,
true_normal = normal;
# endif
tangent_orco_z(orco, orco);
- node_tangent(N, orco, objmat, toworld, tangent);
+ node_tangent(N, orco, objmat, tangent);
parametric = vec3(barycentric, 0.0);
backfacing = (gl_FrontFacing) ? 0.0 : 1.0;
@@ -2091,9 +2069,8 @@ void generated_texco(vec3 I, vec3 attr_orco, out vec3 generated)
}
void node_tex_coord(vec3 I,
- vec3 N,
- mat4 viewinvmat,
- mat4 obinvmat,
+ vec3 wN,
+ mat4 obmatinv,
vec4 camerafac,
vec3 attr_orco,
vec3 attr_uv,
@@ -2106,22 +2083,18 @@ void node_tex_coord(vec3 I,
out vec3 reflection)
{
generated = attr_orco;
- normal = normalize(NormalMatrixInverse * N);
+ normal = normalize(normal_world_to_object(wN));
uv = attr_uv;
- object = (obinvmat * (viewinvmat * vec4(I, 1.0))).xyz;
+ object = (obmatinv * (ViewMatrixInverse * vec4(I, 1.0))).xyz;
camera = vec3(I.xy, -I.z);
vec4 projvec = ProjectionMatrix * vec4(I, 1.0);
window = vec3(mtex_2d_mapping(projvec.xyz / projvec.w).xy * camerafac.xy + camerafac.zw, 0.0);
-
- vec3 shade_I = (ProjectionMatrix[3][3] == 0.0) ? normalize(I) : vec3(0.0, 0.0, -1.0);
- vec3 view_reflection = reflect(shade_I, normalize(N));
- reflection = (viewinvmat * vec4(view_reflection, 0.0)).xyz;
+ reflection = reflect(cameraVec, normalize(wN));
}
void node_tex_coord_background(vec3 I,
vec3 N,
- mat4 viewinvmat,
- mat4 obinvmat,
+ mat4 obmatinv,
vec4 camerafac,
vec3 attr_orco,
vec3 attr_uv,
@@ -2140,11 +2113,7 @@ void node_tex_coord_background(vec3 I,
co = normalize(co);
-#if defined(WORLD_BACKGROUND) || defined(PROBE_CAPTURE)
vec3 coords = (ViewMatrixInverse * co).xyz;
-#else
- vec3 coords = (ModelViewMatrixInverse * co).xyz;
-#endif
generated = coords;
normal = -coords;
@@ -2345,6 +2314,21 @@ void node_tex_environment_empty(vec3 co, out vec4 color)
/* 16bits floats limits. Higher/Lower values produce +/-inf. */
#define safe_color(a) (clamp(a, -65520.0, 65520.0))
+void tex_color_alpha_clear(vec4 color, out vec4 result)
+{
+ result = vec4(color.rgb, 1.0);
+}
+
+void tex_color_alpha_unpremultiply(vec4 color, out vec4 result)
+{
+ if (color.a == 0.0 || color.a == 1.0) {
+ result = vec4(color.rgb, 1.0);
+ }
+ else {
+ result = vec4(color.rgb / color.a, 1.0);
+ }
+}
+
void node_tex_image_linear(vec3 co, sampler2D ima, out vec4 color, out float alpha)
{
color = safe_color(texture(ima, co.xy));
@@ -3245,6 +3229,7 @@ void node_light_falloff(
void node_object_info(mat4 obmat,
vec4 info,
+ float mat_index,
out vec3 location,
out float object_index,
out float material_index,
@@ -3252,7 +3237,7 @@ void node_object_info(mat4 obmat,
{
location = obmat[3].xyz;
object_index = info.x;
- material_index = info.y;
+ material_index = mat_index;
random = info.z;
}
@@ -3346,6 +3331,7 @@ void node_vector_displacement_tangent(vec4 vector,
mat4 viewmat,
out vec3 result)
{
+ /* TODO(fclem) this is broken. revisit latter. */
vec3 N_object = normalize(((vec4(normal, 0.0) * viewmat) * obmat).xyz);
vec3 T_object = normalize(((vec4(tangent.xyz, 0.0) * viewmat) * obmat).xyz);
vec3 B_object = tangent.w * normalize(cross(N_object, T_object));
@@ -3390,11 +3376,11 @@ void node_output_world(Closure surface, Closure volume, out Closure result)
#endif /* VOLUMETRICS */
}
-#ifndef VOLUMETRICS
/* TODO : clean this ifdef mess */
/* EEVEE output */
void world_normals_get(out vec3 N)
{
+#ifndef VOLUMETRICS
# ifdef HAIR_SHADER
vec3 B = normalize(cross(worldNormal, hairTangent));
float cos_theta;
@@ -3412,8 +3398,12 @@ void world_normals_get(out vec3 N)
# else
N = gl_FrontFacing ? worldNormal : -worldNormal;
# endif
+#else
+ generated_from_orco(vec3(0.0), N);
+#endif
}
+#ifndef VOLUMETRICS
void node_eevee_specular(vec4 diffuse,
vec4 specular,
float roughness,
diff --git a/source/blender/imbuf/IMB_colormanagement.h b/source/blender/imbuf/IMB_colormanagement.h
index 620f8984d9f..a27945cc369 100644
--- a/source/blender/imbuf/IMB_colormanagement.h
+++ b/source/blender/imbuf/IMB_colormanagement.h
@@ -58,6 +58,11 @@ void IMB_colormanagement_assign_rect_colorspace(struct ImBuf *ibuf, const char *
const char *IMB_colormanagement_get_float_colorspace(struct ImBuf *ibuf);
const char *IMB_colormanagement_get_rect_colorspace(struct ImBuf *ibuf);
+bool IMB_colormanagement_space_is_data(struct ColorSpace *colorspace);
+bool IMB_colormanagement_space_is_scene_linear(struct ColorSpace *colorspace);
+bool IMB_colormanagement_space_is_srgb(struct ColorSpace *colorspace);
+bool IMB_colormanagement_space_name_is_data(const char *name);
+
BLI_INLINE float IMB_colormanagement_get_luminance(const float rgb[3]);
BLI_INLINE unsigned char IMB_colormanagement_get_luminance_byte(const unsigned char[3]);
BLI_INLINE void IMB_colormangement_xyz_to_rgb(float rgb[3], const float xyz[3]);
@@ -124,6 +129,14 @@ void IMB_colormanagement_colorspace_to_scene_linear(float *buffer,
struct ColorSpace *colorspace,
bool predivide);
+void IMB_colormanagement_imbuf_to_srgb_texture(unsigned char *rect,
+ const int x,
+ const int y,
+ const int width,
+ const int height,
+ const struct ImBuf *ibuf,
+ const bool compress_as_srgb);
+
void IMB_colormanagement_scene_linear_to_color_picking_v3(float pixel[3]);
void IMB_colormanagement_color_picking_to_scene_linear_v3(float pixel[3]);
@@ -340,6 +353,7 @@ enum {
COLOR_ROLE_DEFAULT_SEQUENCER,
COLOR_ROLE_DEFAULT_BYTE,
COLOR_ROLE_DEFAULT_FLOAT,
+ COLOR_ROLE_DATA,
};
#include "intern/colormanagement_inline.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/IMB_colormanagement_intern.h b/source/blender/imbuf/intern/IMB_colormanagement_intern.h
index 2566016ffdd..a83f2d60b8c 100644
--- a/source/blender/imbuf/intern/IMB_colormanagement_intern.h
+++ b/source/blender/imbuf/intern/IMB_colormanagement_intern.h
@@ -48,6 +48,13 @@ typedef struct ColorSpace {
bool is_invertible;
bool is_data;
+
+ /* Additional info computed only when needed since it's not cheap. */
+ struct {
+ bool cached;
+ bool is_srgb;
+ bool is_scene_linear;
+ } info;
} ColorSpace;
typedef struct ColorManagedDisplay {
diff --git a/source/blender/imbuf/intern/cache.c b/source/blender/imbuf/intern/cache.c
index 01c588daedd..7ddf4423bbf 100644
--- a/source/blender/imbuf/intern/cache.c
+++ b/source/blender/imbuf/intern/cache.c
@@ -156,7 +156,7 @@ void imb_tile_cache_tile_free(ImBuf *ibuf, int tx, int ty)
if (gtile) {
/* in case another thread is loading this */
while (gtile->loading) {
- ;
+ /* pass */
}
BLI_ghash_remove(GLOBAL_CACHE.tilehash, gtile, NULL, NULL);
@@ -295,7 +295,7 @@ static ImGlobalTile *imb_global_cache_get_tile(ImBuf *ibuf,
BLI_mutex_unlock(&GLOBAL_CACHE.mutex);
while (gtile->loading) {
- ;
+ /* pass */
}
}
else {
diff --git a/source/blender/imbuf/intern/colormanagement.c b/source/blender/imbuf/intern/colormanagement.c
index f31d4ede693..583a3be8168 100644
--- a/source/blender/imbuf/intern/colormanagement.c
+++ b/source/blender/imbuf/intern/colormanagement.c
@@ -65,6 +65,7 @@
#define DISPLAY_BUFFER_CHANNELS 4
/* ** list of all supported color spaces, displays and views */
+static char global_role_data[MAX_COLORSPACE_NAME];
static char global_role_scene_linear[MAX_COLORSPACE_NAME];
static char global_role_color_picking[MAX_COLORSPACE_NAME];
static char global_role_texture_painting[MAX_COLORSPACE_NAME];
@@ -488,6 +489,7 @@ static void colormanage_load_config(OCIO_ConstConfigRcPtr *config)
const char *name;
/* get roles */
+ colormanage_role_color_space_name_get(config, global_role_data, OCIO_ROLE_DATA, NULL);
colormanage_role_color_space_name_get(
config, global_role_scene_linear, OCIO_ROLE_SCENE_LINEAR, NULL);
colormanage_role_color_space_name_get(
@@ -745,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) {
@@ -838,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);
}
@@ -987,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) {
@@ -1055,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);
}
}
@@ -1260,6 +1278,8 @@ void IMB_colormanagement_validate_settings(const ColorManagedDisplaySettings *di
const char *IMB_colormanagement_role_colorspace_name_get(int role)
{
switch (role) {
+ case COLOR_ROLE_DATA:
+ return global_role_data;
case COLOR_ROLE_SCENE_LINEAR:
return global_role_scene_linear;
case COLOR_ROLE_COLOR_PICKING:
@@ -1341,6 +1361,48 @@ const char *IMB_colormanagement_get_rect_colorspace(ImBuf *ibuf)
}
}
+bool IMB_colormanagement_space_is_data(ColorSpace *colorspace)
+{
+ return (colorspace && colorspace->is_data);
+}
+
+static void colormanage_ensure_srgb_scene_linear_info(ColorSpace *colorspace)
+{
+ if (!colorspace->info.cached) {
+ OCIO_ConstConfigRcPtr *config = OCIO_getCurrentConfig();
+ OCIO_ConstColorSpaceRcPtr *ocio_colorspace = OCIO_configGetColorSpace(config,
+ colorspace->name);
+
+ bool is_scene_linear, is_srgb;
+ OCIO_colorSpaceIsBuiltin(config, ocio_colorspace, &is_scene_linear, &is_srgb);
+
+ OCIO_colorSpaceRelease(ocio_colorspace);
+ OCIO_configRelease(config);
+
+ colorspace->info.is_scene_linear = is_scene_linear;
+ colorspace->info.is_srgb = is_srgb;
+ colorspace->info.cached = true;
+ }
+}
+
+bool IMB_colormanagement_space_is_scene_linear(ColorSpace *colorspace)
+{
+ colormanage_ensure_srgb_scene_linear_info(colorspace);
+ return (colorspace && colorspace->info.is_scene_linear);
+}
+
+bool IMB_colormanagement_space_is_srgb(ColorSpace *colorspace)
+{
+ colormanage_ensure_srgb_scene_linear_info(colorspace);
+ return (colorspace && colorspace->info.is_srgb);
+}
+
+bool IMB_colormanagement_space_name_is_data(const char *name)
+{
+ ColorSpace *colorspace = colormanage_colorspace_get_named(name);
+ return (colorspace && colorspace->is_data);
+}
+
/*********************** Threaded display buffer transform routines *************************/
typedef struct DisplayBufferThread {
@@ -1359,6 +1421,7 @@ typedef struct DisplayBufferThread {
int channels;
float dither;
bool is_data;
+ bool predivide;
const char *byte_colorspace;
const char *float_colorspace;
@@ -1423,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;
@@ -1440,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;
@@ -1488,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;
@@ -1544,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,
@@ -2111,6 +2176,69 @@ void IMB_colormanagement_colorspace_to_scene_linear(float *buffer,
}
}
+void IMB_colormanagement_imbuf_to_srgb_texture(unsigned char *out_buffer,
+ const int offset_x,
+ const int offset_y,
+ const int width,
+ const int height,
+ const struct ImBuf *ibuf,
+ const bool compress_as_srgb)
+{
+ /* Convert byte buffer for texture storage on the GPU. These have builtin
+ * support for converting sRGB to linear, which allows us to store textures
+ * without precision or performance loss at minimal memory usage. */
+ BLI_assert(ibuf->rect && ibuf->rect_float == NULL);
+
+ OCIO_ConstProcessorRcPtr *processor = NULL;
+ if (compress_as_srgb && ibuf->rect_colorspace &&
+ !IMB_colormanagement_space_is_srgb(ibuf->rect_colorspace)) {
+ processor = colorspace_to_scene_linear_processor(ibuf->rect_colorspace);
+ }
+
+ /* 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;
+ const size_t out_offset = y * width;
+ const unsigned char *in = in_buffer + in_offset * 4;
+ unsigned char *out = out_buffer + out_offset * 4;
+
+ if (processor) {
+ /* Convert to scene linear, to sRGB and premultiply. */
+ for (int x = 0; x < width; x++, in += 4, out += 4) {
+ float pixel[4];
+ rgba_uchar_to_float(pixel, in);
+ OCIO_processorApplyRGB(processor, pixel);
+ linearrgb_to_srgb_v3_v3(pixel, pixel);
+ if (use_premultiply) {
+ mul_v3_fl(pixel, pixel[3]);
+ }
+ rgba_float_to_uchar(out, pixel);
+ }
+ }
+ else if (use_premultiply) {
+ /* Premultiply only. */
+ for (int x = 0; x < width; x++, in += 4, out += 4) {
+ out[0] = (in[0] * in[3]) >> 8;
+ out[1] = (in[1] * in[3]) >> 8;
+ out[2] = (in[2] * in[3]) >> 8;
+ 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];
+ }
+ }
+ }
+}
+
/* Conversion between color picking role. Typically we would expect such a
* requirements:
* - It is approximately perceptually linear, so that the HSV numbers and
@@ -3097,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/metadata.c b/source/blender/imbuf/intern/metadata.c
index ed3b214047a..ac31f7db791 100644
--- a/source/blender/imbuf/intern/metadata.c
+++ b/source/blender/imbuf/intern/metadata.c
@@ -55,7 +55,6 @@ void IMB_metadata_free(struct IDProperty *metadata)
}
IDP_FreeProperty(metadata);
- MEM_freeN(metadata);
}
bool IMB_metadata_get_field(struct IDProperty *metadata,
diff --git a/source/blender/imbuf/intern/radiance_hdr.c b/source/blender/imbuf/intern/radiance_hdr.c
index 58ac966ac30..5e81b716619 100644
--- a/source/blender/imbuf/intern/radiance_hdr.c
+++ b/source/blender/imbuf/intern/radiance_hdr.c
@@ -354,7 +354,7 @@ static int fwritecolrs(FILE *file, int width, int channels, unsigned char *ibufs
for (cnt = 1; (cnt < 127) && ((beg + cnt) < width) &&
(rgbe_scan[beg + cnt][i] == rgbe_scan[beg][i]);
cnt++) {
- ;
+ /* pass */
}
if (cnt >= MINRUN) {
break; /* long enough */
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_ID.h b/source/blender/makesdna/DNA_ID.h
index 2cdbfa06e30..5a666653043 100644
--- a/source/blender/makesdna/DNA_ID.h
+++ b/source/blender/makesdna/DNA_ID.h
@@ -448,7 +448,9 @@ typedef enum ID_Type {
/* No copy-on-write for these types.
* Keep in sync with check_datablocks_copy_on_writable and deg_copy_on_write_is_needed */
-#define ID_TYPE_IS_COW(_id_type) (!ELEM(_id_type, ID_BR, ID_LS, ID_PAL, ID_IM))
+/* TODO(sergey): Make Sound copyable. It is here only because the code for dependency graph is
+ * being work in progress. */
+#define ID_TYPE_IS_COW(_id_type) (!ELEM(_id_type, ID_BR, ID_LS, ID_PAL, ID_IM, ID_SO))
#ifdef GS
# undef GS
diff --git a/source/blender/makesdna/DNA_action_types.h b/source/blender/makesdna/DNA_action_types.h
index c524f50ff52..c8a76791cef 100644
--- a/source/blender/makesdna/DNA_action_types.h
+++ b/source/blender/makesdna/DNA_action_types.h
@@ -512,6 +512,12 @@ typedef enum ePose_Flags {
POSE_FLAG_DEPRECATED = (1 << 6), /* deprecated. */
/* pose constraint flags needs to be updated */
POSE_CONSTRAINTS_NEED_UPDATE_FLAGS = (1 << 7),
+ /* Use auto IK in pose mode */
+ POSE_AUTO_IK = (1 << 8),
+ /* Use x-axis mirror in pose mode */
+ POSE_MIRROR_EDIT = (1 << 9),
+ /* Use relative mirroring in mirror mode */
+ POSE_MIRROR_RELATIVE = (1 << 10),
} ePose_Flags;
/* IK Solvers ------------------------------------ */
diff --git a/source/blender/makesdna/DNA_anim_types.h b/source/blender/makesdna/DNA_anim_types.h
index c76d4895b25..ecf587301c7 100644
--- a/source/blender/makesdna/DNA_anim_types.h
+++ b/source/blender/makesdna/DNA_anim_types.h
@@ -357,6 +357,7 @@ typedef enum eDriverTarget_TransformChannels {
DTAR_TRANSCHAN_SCALEX,
DTAR_TRANSCHAN_SCALEY,
DTAR_TRANSCHAN_SCALEZ,
+ DTAR_TRANSCHAN_SCALE_AVG,
MAX_DTAR_TRANSCHAN_TYPES,
} eDriverTarget_TransformChannels;
@@ -969,6 +970,8 @@ typedef enum eInsertKeyFlags {
INSERTKEY_DRIVER = (1 << 8),
/** for cyclic FCurves, adjust key timing to preserve the cycle period and flow */
INSERTKEY_CYCLE_AWARE = (1 << 9),
+ /** don't create new F-Curves (implied by INSERTKEY_REPLACE) */
+ INSERTKEY_AVAILABLE = (1 << 10),
} eInsertKeyFlags;
/* ************************************************ */
diff --git a/source/blender/makesdna/DNA_armature_types.h b/source/blender/makesdna/DNA_armature_types.h
index 483ff3483d3..b18ab503e94 100644
--- a/source/blender/makesdna/DNA_armature_types.h
+++ b/source/blender/makesdna/DNA_armature_types.h
@@ -104,7 +104,11 @@ typedef struct bArmature {
struct AnimData *adt;
ListBase bonebase;
- ListBase chainbase;
+
+ /** Ghash for quicker lookups of bones by name. */
+ struct GHash *bonehash;
+ void *_pad1;
+
/** Editbone listbase, we use pointer so we can check state. */
ListBase *edbo;
@@ -144,9 +148,9 @@ typedef enum eArmature_Flag {
ARM_POSEMODE = (1 << 4),
ARM_FLAG_UNUSED_5 = (1 << 5), /* cleared */
ARM_DELAYDEFORM = (1 << 6),
- ARM_FLAG_UNUSED_7 = (1 << 7), /* cleared */
+ ARM_FLAG_UNUSED_7 = (1 << 7),
ARM_MIRROR_EDIT = (1 << 8),
- ARM_AUTO_IK = (1 << 9),
+ ARM_FLAG_UNUSED_9 = (1 << 9),
/** made option negative, for backwards compat */
ARM_NO_CUSTOM = (1 << 10),
/** draw custom colors */
diff --git a/source/blender/makesdna/DNA_camera_types.h b/source/blender/makesdna/DNA_camera_types.h
index 8c5d911b7fa..b78b2f64648 100644
--- a/source/blender/makesdna/DNA_camera_types.h
+++ b/source/blender/makesdna/DNA_camera_types.h
@@ -67,6 +67,19 @@ typedef struct CameraBGImage {
short source;
} CameraBGImage;
+/** Properties for dof effect. */
+typedef struct CameraDOFSettings {
+ /** Focal distance for depth of field. */
+ struct Object *focus_object;
+ float focus_distance;
+ float aperture_fstop;
+ float aperture_rotation;
+ float aperture_ratio;
+ int aperture_blades;
+ short flag;
+ char _pad[2];
+} CameraDOFSettings;
+
typedef struct Camera_Runtime {
/* For draw manager. */
float drw_corners[2][4][2];
@@ -91,13 +104,14 @@ typedef struct Camera {
float lens, ortho_scale, drawsize;
float sensor_x, sensor_y;
float shiftx, shifty;
- float dof_distance;
+ float dof_distance DNA_DEPRECATED;
/** Old animation system, deprecated for 2.5. */
struct Ipo *ipo DNA_DEPRECATED;
- struct Object *dof_ob;
- struct GPUDOFSettings gpu_dof;
+ struct Object *dof_ob DNA_DEPRECATED;
+ struct GPUDOFSettings gpu_dof DNA_DEPRECATED;
+ struct CameraDOFSettings dof;
/* CameraBGImage reference images */
struct ListBase bg_images;
@@ -204,6 +218,11 @@ enum {
CAM_BGIMG_SOURCE_MOVIE = 1,
};
+/* CameraDOFSettings->flag */
+enum {
+ CAM_DOF_ENABLED = (1 << 0),
+};
+
#ifdef __cplusplus
}
#endif
diff --git a/source/blender/makesdna/DNA_collection_types.h b/source/blender/makesdna/DNA_collection_types.h
index b935acd5a24..c7f3ef4156d 100644
--- a/source/blender/makesdna/DNA_collection_types.h
+++ b/source/blender/makesdna/DNA_collection_types.h
@@ -76,10 +76,10 @@ typedef struct Collection {
/* Collection->flag */
enum {
- COLLECTION_RESTRICT_VIEW = (1 << 0), /* Hidden in viewport. */
+ COLLECTION_RESTRICT_VIEWPORT = (1 << 0), /* Disable in viewports. */
COLLECTION_RESTRICT_SELECT = (1 << 1), /* Not selectable in viewport. */
COLLECTION_DISABLED_DEPRECATED = (1 << 2), /* Not used anymore */
- COLLECTION_RESTRICT_RENDER = (1 << 3), /* Hidden in renders. */
+ COLLECTION_RESTRICT_RENDER = (1 << 3), /* Disable in renders. */
COLLECTION_HAS_OBJECT_CACHE = (1 << 4), /* Runtime: object_cache is populated. */
COLLECTION_IS_MASTER = (1 << 5), /* Is master collection embedded in the scene. */
};
diff --git a/source/blender/makesdna/DNA_constraint_types.h b/source/blender/makesdna/DNA_constraint_types.h
index f839f22ec9f..c09ea400f4c 100644
--- a/source/blender/makesdna/DNA_constraint_types.h
+++ b/source/blender/makesdna/DNA_constraint_types.h
@@ -289,14 +289,16 @@ typedef struct bLocateLikeConstraint {
typedef struct bSizeLikeConstraint {
struct Object *tar;
int flag;
- int reserved1;
+ float power;
/** MAX_ID_NAME-2. */
char subtarget[64];
} bSizeLikeConstraint;
/* Maintain Volume Constraint */
typedef struct bSameVolumeConstraint {
- int flag;
+ char free_axis;
+ char mode;
+ char _pad[2];
float volume;
} bSameVolumeConstraint;
@@ -758,12 +760,22 @@ typedef enum eTransform_ToFrom {
TRANS_SCALE = 2,
} eTransform_ToFrom;
-/* bSameVolumeConstraint.flag */
-typedef enum eSameVolume_Modes {
+/* bSameVolumeConstraint.free_axis */
+typedef enum eSameVolume_Axis {
SAMEVOL_X = 0,
SAMEVOL_Y = 1,
SAMEVOL_Z = 2,
-} eSameVolume_Modes;
+} eSameVolume_Axis;
+
+/* bSameVolumeConstraint.mode */
+typedef enum eSameVolume_Mode {
+ /* Strictly maintain the volume, overriding non-free axis scale. */
+ SAMEVOL_STRICT = 0,
+ /* Maintain the volume when scale is uniform, pass non-uniform other axis scale through. */
+ SAMEVOL_UNIFORM = 1,
+ /* Maintain the volume when scaled only on the free axis, pass other axis scale through. */
+ SAMEVOL_SINGLE_AXIS = 2,
+} eSameVolume_Mode;
/* bActionConstraint.flag */
typedef enum eActionConstraint_Flags {
@@ -894,6 +906,9 @@ typedef enum eSplineIK_Flags {
/* for "volumetric" xz scale mode, limit the minimum or maximum scale values */
CONSTRAINT_SPLINEIK_USE_BULGE_MIN = (1 << 5),
CONSTRAINT_SPLINEIK_USE_BULGE_MAX = (1 << 6),
+
+ /* apply volume preservation over original scaling of the bone */
+ CONSTRAINT_SPLINEIK_USE_ORIGINAL_SCALE = (1 << 7),
} eSplineIK_Flags;
/* bSplineIKConstraint->xzScaleMode */
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_gpencil_types.h b/source/blender/makesdna/DNA_gpencil_types.h
index bb38311cbac..007be021def 100644
--- a/source/blender/makesdna/DNA_gpencil_types.h
+++ b/source/blender/makesdna/DNA_gpencil_types.h
@@ -518,7 +518,8 @@ typedef struct bGPdata {
/** Draw mode for strokes (eGP_DrawMode). */
short draw_mode;
- char _pad3[2];
+ /** Keyframe type for onion filter (eBezTriple_KeyframeType plus All option) */
+ short onion_keytype;
bGPgrid grid;
diff --git a/source/blender/makesdna/DNA_image_types.h b/source/blender/makesdna/DNA_image_types.h
index fec5f96b4f3..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 */
@@ -191,22 +191,50 @@ enum {
IMA_GPU_REFRESH = (1 << 0),
/** All mipmap levels in OpenGL texture set? */
IMA_GPU_MIPMAP_COMPLETE = (1 << 1),
- /** OpenGL image texture bound as non-color data. */
- IMA_GPU_IS_DATA = (1 << 2),
};
-/* ima->type and ima->source moved to BKE_image.h, for API */
+/* Image.source, where the image comes from */
+enum {
+ IMA_SRC_CHECK = 0,
+ IMA_SRC_FILE = 1,
+ IMA_SRC_SEQUENCE = 2,
+ IMA_SRC_MOVIE = 3,
+ IMA_SRC_GENERATED = 4,
+ IMA_SRC_VIEWER = 5,
+};
+
+/* Image.type, how to handle or generate the image */
+enum {
+ IMA_TYPE_IMAGE = 0,
+ IMA_TYPE_MULTILAYER = 1,
+ /* generated */
+ IMA_TYPE_UV_TEST = 2,
+ /* viewers */
+ IMA_TYPE_R_RESULT = 4,
+ IMA_TYPE_COMPOSITE = 5,
+};
+
+/* Image.gen_type */
+enum {
+ IMA_GENTYPE_BLANK = 0,
+ IMA_GENTYPE_GRID = 1,
+ IMA_GENTYPE_GRID_COLOR = 2,
+};
/* render */
#define IMA_MAX_RENDER_TEXT (1 << 9)
-/* gen_flag */
-#define IMA_GEN_FLOAT 1
+/* Image.gen_flag */
+enum {
+ IMA_GEN_FLOAT = 1,
+};
-/* alpha_mode */
+/* Image.alpha_mode */
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_layer_types.h b/source/blender/makesdna/DNA_layer_types.h
index dd8adeaf153..5f64e3220b7 100644
--- a/source/blender/makesdna/DNA_layer_types.h
+++ b/source/blender/makesdna/DNA_layer_types.h
@@ -133,7 +133,7 @@ enum {
LAYER_COLLECTION_EXCLUDE = (1 << 4),
LAYER_COLLECTION_HOLDOUT = (1 << 5),
LAYER_COLLECTION_INDIRECT_ONLY = (1 << 6),
- LAYER_COLLECTION_RESTRICT_VIEW = (1 << 7),
+ LAYER_COLLECTION_HIDE = (1 << 7),
};
/* Layer Collection->runtime_flag */
diff --git a/source/blender/makesdna/DNA_light_types.h b/source/blender/makesdna/DNA_light_types.h
index 6bd118b7be9..5e881053910 100644
--- a/source/blender/makesdna/DNA_light_types.h
+++ b/source/blender/makesdna/DNA_light_types.h
@@ -66,6 +66,9 @@ typedef struct Light {
short area_shape;
float area_size, area_sizey, area_sizez;
+ float sun_angle;
+ char _pad3[4];
+
/* texact is for buttons */
short texact, shadhalostep;
diff --git a/source/blender/makesdna/DNA_material_types.h b/source/blender/makesdna/DNA_material_types.h
index 02f8245413d..d65a4896758 100644
--- a/source/blender/makesdna/DNA_material_types.h
+++ b/source/blender/makesdna/DNA_material_types.h
@@ -99,6 +99,9 @@ typedef struct MaterialGPencilStyle {
/** Factor used to mix texture and stroke color. */
float mix_stroke_factor;
+ /** Mode used to align Dots and Boxes with stroke drawing path and object rotation */
+ int alignment_mode;
+ char _pad[4];
} MaterialGPencilStyle;
/* MaterialGPencilStyle->flag */
@@ -123,8 +126,6 @@ typedef enum eMaterialGPencilStyle_Flag {
GP_STYLE_STROKE_SHOW = (1 << 8),
/* Fill show main switch */
GP_STYLE_FILL_SHOW = (1 << 9),
- /* Don't rotate dots/boxes */
- GP_STYLE_COLOR_LOCK_DOTS = (1 << 10),
/* mix stroke texture */
GP_STYLE_STROKE_TEX_MIX = (1 << 11),
} eMaterialGPencilStyle_Flag;
@@ -315,7 +316,7 @@ enum {
enum {
MA_BL_HIDE_BACKFACE = (1 << 0),
MA_BL_SS_REFRACTION = (1 << 1),
- MA_BL_FLAG_UNUSED_2 = (1 << 2), /* cleared */
+ MA_BL_CULL_BACKFACE = (1 << 2),
MA_BL_TRANSLUCENCY = (1 << 3),
};
@@ -347,4 +348,10 @@ enum {
GP_STYLE_GRADIENT_RADIAL,
};
+/* Grease Pencil Follow Drawing Modes */
+enum {
+ GP_STYLE_FOLLOW_PATH = 0,
+ GP_STYLE_FOLLOW_OBJ,
+ GP_STYLE_FOLLOW_FIXED,
+};
#endif
diff --git a/source/blender/makesdna/DNA_mesh_types.h b/source/blender/makesdna/DNA_mesh_types.h
index 8f08b212d6d..f54c178f1d0 100644
--- a/source/blender/makesdna/DNA_mesh_types.h
+++ b/source/blender/makesdna/DNA_mesh_types.h
@@ -233,11 +233,11 @@ enum {
/* me->flag */
enum {
- ME_FLAG_UNUSED_0 = 1 << 0, /* cleared */
- ME_FLAG_UNUSED_1 = 1 << 1, /* cleared */
- ME_TWOSIDED = 1 << 2,
- ME_FLAG_UNUSED_3 = 1 << 3, /* cleared */
- ME_FLAG_UNUSED_4 = 1 << 4, /* cleared */
+ ME_FLAG_UNUSED_0 = 1 << 0, /* cleared */
+ ME_FLAG_UNUSED_1 = 1 << 1, /* cleared */
+ ME_FLAG_DEPRECATED_2 = 1 << 2, /* deprecated */
+ ME_FLAG_UNUSED_3 = 1 << 3, /* cleared */
+ ME_FLAG_UNUSED_4 = 1 << 4, /* cleared */
ME_AUTOSMOOTH = 1 << 5,
ME_FLAG_UNUSED_6 = 1 << 6, /* cleared */
ME_FLAG_UNUSED_7 = 1 << 7, /* cleared */
diff --git a/source/blender/makesdna/DNA_node_types.h b/source/blender/makesdna/DNA_node_types.h
index 226e1d2f841..3890fc63f3f 100644
--- a/source/blender/makesdna/DNA_node_types.h
+++ b/source/blender/makesdna/DNA_node_types.h
@@ -832,7 +832,7 @@ typedef struct NodeTexSky {
typedef struct NodeTexImage {
NodeTexBase base;
ImageUser iuser;
- int color_space;
+ int color_space DNA_DEPRECATED;
int projection;
float projection_blend;
int interpolation;
@@ -853,7 +853,7 @@ typedef struct NodeTexBrick {
typedef struct NodeTexEnvironment {
NodeTexBase base;
ImageUser iuser;
- int color_space;
+ int color_space DNA_DEPRECATED;
int projection;
int interpolation;
char _pad[4];
@@ -1121,10 +1121,6 @@ typedef struct NodeCryptomatte {
#define SHD_SKY_OLD 0
#define SHD_SKY_NEW 1
-/* image/environment texture */
-#define SHD_COLORSPACE_NONE 0
-#define SHD_COLORSPACE_COLOR 1
-
/* environment texture */
#define SHD_PROJ_EQUIRECTANGULAR 0
#define SHD_PROJ_MIRROR_BALL 1
diff --git a/source/blender/makesdna/DNA_object_types.h b/source/blender/makesdna/DNA_object_types.h
index 1aeb4a2f4d2..9bbb6f1656c 100644
--- a/source/blender/makesdna/DNA_object_types.h
+++ b/source/blender/makesdna/DNA_object_types.h
@@ -44,6 +44,7 @@ struct FluidsimSettings;
struct GpencilBatchCache;
struct Ipo;
struct Material;
+struct Mesh;
struct Object;
struct PartDeflect;
struct ParticleSystem;
@@ -136,6 +137,10 @@ typedef struct Object_Runtime {
/** Only used for drawing the parent/child help-line. */
float parent_display_origin[3];
+ /** Selection id of this object; only available in the original object */
+ int select_id;
+ char _pad1[4];
+
/** Axis aligned boundbox (in localspace). */
struct BoundBox *bb;
@@ -156,11 +161,17 @@ typedef struct Object_Runtime {
*/
struct Mesh *mesh_deform_eval;
+ /* This is a mesh representation of corresponding object.
+ * It created when Python calls `object.to_mesh()`. */
+ struct Mesh *object_as_temp_mesh;
+
/** Runtime evaluated curve-specific data, not stored in the file. */
struct CurveCache *curve_cache;
/** Runtime grease pencil drawing data */
struct GpencilBatchCache *gpencil_cache;
+
+ void *_pad2; /* Padding is here for win32s unconventional stuct alignment rules. */
} Object_Runtime;
typedef struct Object {
@@ -365,9 +376,7 @@ typedef struct Object {
char empty_image_visibility_flag;
char empty_image_depth;
char empty_image_flag;
- char _pad8[1];
-
- int select_id;
+ char _pad8[5];
/** Contains data for levels of detail. */
ListBase lodlevels;
@@ -600,7 +609,7 @@ enum {
/* ob->restrictflag */
enum {
- OB_RESTRICT_VIEW = 1 << 0,
+ OB_RESTRICT_VIEWPORT = 1 << 0,
OB_RESTRICT_SELECT = 1 << 1,
OB_RESTRICT_RENDER = 1 << 2,
};
diff --git a/source/blender/makesdna/DNA_scene_types.h b/source/blender/makesdna/DNA_scene_types.h
index baa9b3ed5c3..0973405ce7b 100644
--- a/source/blender/makesdna/DNA_scene_types.h
+++ b/source/blender/makesdna/DNA_scene_types.h
@@ -661,19 +661,15 @@ typedef struct RenderData {
*/
int mode;
+ short frs_sec;
+
/**
* What to do with the sky/background.
* Picks sky/premul blending for the background.
*/
- short alphamode;
-
- /**
- * The number of samples to use per pixel.
- */
- short osa;
+ char alphamode;
- short frs_sec;
- char _pad[6];
+ char _pad0[1];
/* safety, border and display rect */
rctf safety, border;
@@ -1447,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];
@@ -1503,7 +1500,7 @@ typedef struct ToolSettings {
/* Normal Editing */
float normal_vector[3];
- int face_strength;
+ char _pad6[4];
} ToolSettings;
/* *************************************************************** */
@@ -1566,6 +1563,11 @@ typedef struct SceneDisplay {
float matcap_ssao_attenuation;
int matcap_ssao_samples;
+ /** Method of AA for viewport rendering and image rendering */
+ char viewport_aa;
+ char render_aa;
+ char _pad[6];
+
/** OpenGL render engine settings. */
View3DShading shading;
} SceneDisplay;
@@ -1640,7 +1642,7 @@ typedef struct TransformOrientationSlot {
char _pad0[7];
} TransformOrientationSlot;
-/* Indices when used in Scene.orientation. */
+/** Indices when used in #Scene.orientation_slots */
enum {
SCE_ORIENT_DEFAULT = 0,
SCE_ORIENT_TRANSLATE = 1,
@@ -1723,7 +1725,7 @@ typedef struct Scene {
/* Units */
struct UnitSettings unit;
- /* Grease Pencil - Annotations */
+ /** Grease Pencil - Annotations */
struct bGPdata *gpd;
/* Movie Tracking */
@@ -1764,15 +1766,15 @@ typedef struct Scene {
/* **************** RENDERDATA ********************* */
-/* RenderData.flag */
+/** #RenderData.flag */
/* use preview range */
#define SCER_PRV_RANGE (1 << 0)
#define SCER_LOCK_FRAME_SELECTION (1 << 1)
/* show/use subframes (for checking motion blur) */
#define SCER_SHOW_SUBFRAME (1 << 3)
-/* RenderData.mode */
-#define R_OSA (1 << 0)
+/** #RenderData.mode */
+#define R_MODE_UNUSED_0 (1 << 0) /* dirty */
#define R_MODE_UNUSED_1 (1 << 1) /* cleared */
#define R_MODE_UNUSED_2 (1 << 2) /* cleared */
#define R_MODE_UNUSED_3 (1 << 3) /* cleared */
@@ -1804,7 +1806,7 @@ typedef struct Scene {
#define R_PERSISTENT_DATA (1 << 26) /* keep data around for re-render */
#define R_MODE_UNUSED_27 (1 << 27) /* cleared */
-/* RenderData.seq_flag */
+/** #RenderData.seq_flag */
enum {
R_SEQ_UNUSED_0 = (1 << 0), /* cleared */
R_SEQ_UNUSED_1 = (1 << 1), /* cleared */
@@ -1814,14 +1816,14 @@ enum {
R_SEQ_OVERRIDE_SCENE_SETTINGS = (1 << 5),
};
-/* RenderData.displaymode */
+/** #RenderData.displaymode */
#define R_OUTPUT_SCREEN 0
#define R_OUTPUT_AREA 1
#define R_OUTPUT_WINDOW 2
#define R_OUTPUT_NONE 3
/*#define R_OUTPUT_FORKED 4*/
-/* RenderData.filtertype (used for nodes) */
+/** #RenderData.filtertype (used for nodes) */
#define R_FILTER_BOX 0
#define R_FILTER_TENT 1
#define R_FILTER_QUAD 2
@@ -1831,7 +1833,7 @@ enum {
#define R_FILTER_MITCH 6
#define R_FILTER_FAST_GAUSS 7
-/* RenderData.scemode */
+/** #RenderData.scemode */
#define R_DOSEQ (1 << 0)
#define R_BG_RENDER (1 << 1)
/* passepartout is camera option now, keep this for backward compatibility */
@@ -1856,7 +1858,7 @@ enum {
#define R_EXR_CACHE_FILE (1 << 20)
#define R_MULTIVIEW (1 << 21)
-/* RenderData.stamp */
+/** #RenderData.stamp */
#define R_STAMP_TIME (1 << 0)
#define R_STAMP_FRAME (1 << 1)
#define R_STAMP_DATE (1 << 2)
@@ -1881,10 +1883,12 @@ enum {
R_STAMP_HOSTNAME)
/** #RenderData.alphamode */
-#define R_ADDSKY 0
-#define R_ALPHAPREMUL 1
+enum {
+ R_ADDSKY = 0,
+ R_ALPHAPREMUL = 1,
+};
-/* RenderData.color_mgt_flag */
+/** #RenderData.color_mgt_flag */
enum {
/** deprecated, should only be used in versioning code only */
R_COLOR_MANAGEMENT = (1 << 0),
@@ -2086,13 +2090,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 {
@@ -2244,14 +2241,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 */
@@ -2366,19 +2355,19 @@ typedef enum eGPencil_Guide_Reference {
/* SceneEEVEE->flag */
enum {
- SCE_EEVEE_VOLUMETRIC_ENABLED = (1 << 0),
+ // SCE_EEVEE_VOLUMETRIC_ENABLED = (1 << 0), /* Unused */
SCE_EEVEE_VOLUMETRIC_LIGHTS = (1 << 1),
SCE_EEVEE_VOLUMETRIC_SHADOWS = (1 << 2),
// SCE_EEVEE_VOLUMETRIC_COLORED = (1 << 3), /* Unused */
SCE_EEVEE_GTAO_ENABLED = (1 << 4),
SCE_EEVEE_GTAO_BENT_NORMALS = (1 << 5),
SCE_EEVEE_GTAO_BOUNCE = (1 << 6),
- SCE_EEVEE_DOF_ENABLED = (1 << 7),
+ // SCE_EEVEE_DOF_ENABLED = (1 << 7), /* Moved to camera->dof.flag */
SCE_EEVEE_BLOOM_ENABLED = (1 << 8),
SCE_EEVEE_MOTION_BLUR_ENABLED = (1 << 9),
SCE_EEVEE_SHADOW_HIGH_BITDEPTH = (1 << 10),
SCE_EEVEE_TAA_REPROJECTION = (1 << 11),
- SCE_EEVEE_SSS_ENABLED = (1 << 12),
+ // SCE_EEVEE_SSS_ENABLED = (1 << 12), /* Unused */
SCE_EEVEE_SSS_SEPARATE_ALBEDO = (1 << 13),
SCE_EEVEE_SSR_ENABLED = (1 << 14),
SCE_EEVEE_SSR_REFRACTION = (1 << 15),
@@ -2397,6 +2386,17 @@ enum {
SHADOW_METHOD_MAX = 3,
};
+/* SceneDisplay->render_aa, SceneDisplay->viewport_aa */
+enum {
+ SCE_DISPLAY_AA_OFF = 0,
+ SCE_DISPLAY_AA_FXAA = 1,
+ SCE_DISPLAY_AA_SAMPLES_5 = 5,
+ SCE_DISPLAY_AA_SAMPLES_8 = 8,
+ SCE_DISPLAY_AA_SAMPLES_11 = 11,
+ SCE_DISPLAY_AA_SAMPLES_16 = 16,
+ SCE_DISPLAY_AA_SAMPLES_32 = 32,
+};
+
#ifdef __cplusplus
}
#endif
diff --git a/source/blender/makesdna/DNA_screen_types.h b/source/blender/makesdna/DNA_screen_types.h
index 411777333a9..f5c2a518ef6 100644
--- a/source/blender/makesdna/DNA_screen_types.h
+++ b/source/blender/makesdna/DNA_screen_types.h
@@ -139,7 +139,7 @@ typedef struct Panel {
struct uiLayout *layout;
/** Defined as UI_MAX_NAME_STR. */
- char panelname[64], tabname[64];
+ char panelname[64];
/** Panel name is identifier for restoring location. */
char drawname[64];
/** Offset within the region. */
@@ -155,8 +155,6 @@ typedef struct Panel {
short snap;
/** Panels are aligned according to increasing sort-order. */
int sortorder;
- /** This panel is tabbed in *paneltab. */
- struct Panel *paneltab;
/** Runtime for panel manipulation. */
void *activedata;
/** Sub panels. */
@@ -599,31 +597,39 @@ enum {
/* Region supports panel tabs (categories). */
#define RGN_TYPE_HAS_CATEGORY_MASK (1 << RGN_TYPE_UI)
-/* region alignment */
-#define RGN_ALIGN_NONE 0
-#define RGN_ALIGN_TOP 1
-#define RGN_ALIGN_BOTTOM 2
-#define RGN_ALIGN_LEFT 3
-#define RGN_ALIGN_RIGHT 4
-#define RGN_ALIGN_HSPLIT 5
-#define RGN_ALIGN_VSPLIT 6
-#define RGN_ALIGN_FLOAT 7
-#define RGN_ALIGN_QSPLIT 8
-#define RGN_ALIGN_ENUM_MASK 0x0F
+/** #ARegion.alignment */
+enum {
+ RGN_ALIGN_NONE = 0,
+ RGN_ALIGN_TOP = 1,
+ RGN_ALIGN_BOTTOM = 2,
+ RGN_ALIGN_LEFT = 3,
+ RGN_ALIGN_RIGHT = 4,
+ RGN_ALIGN_HSPLIT = 5,
+ RGN_ALIGN_VSPLIT = 6,
+ RGN_ALIGN_FLOAT = 7,
+ RGN_ALIGN_QSPLIT = 8,
+ /* Maximum 15. */
+
+ /* Flags start here. */
+ RGN_SPLIT_PREV = 32,
+};
-#define RGN_SPLIT_PREV 32
+/** Mask out flags so we can check the alignment. */
+#define RGN_ALIGN_ENUM_FROM_MASK(align) ((align) & ((1 << 4) - 1))
/** #ARegion.flag */
enum {
RGN_FLAG_HIDDEN = (1 << 0),
RGN_FLAG_TOO_SMALL = (1 << 1),
- /* Force delayed reinit of region size data, so that region size is calculated
+ /**
+ * Force delayed reinit of region size data, so that region size is calculated
* just big enough to show all its content (if enough space is available).
- * Note that only ED_region_header supports this right now. */
+ * Note that only ED_region_header supports this right now.
+ */
RGN_FLAG_DYNAMIC_SIZE = (1 << 2),
- /* Region data is NULL'd on read, never written. */
+ /** Region data is NULL'd on read, never written. */
RGN_FLAG_TEMP_REGIONDATA = (1 << 3),
- /* The region must either use its prefsizex/y or be hidden. */
+ /** The region must either use its prefsizex/y or be hidden. */
RGN_FLAG_PREFSIZE_OR_HIDDEN = (1 << 4),
/** Size has been clamped (floating regions only). */
RGN_FLAG_SIZE_CLAMP_X = (1 << 5),
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_space_types.h b/source/blender/makesdna/DNA_space_types.h
index 9e8ece0c6e8..20d4f7d96e4 100644
--- a/source/blender/makesdna/DNA_space_types.h
+++ b/source/blender/makesdna/DNA_space_types.h
@@ -247,7 +247,7 @@ typedef struct SpaceOutliner {
short flag, outlinevis, storeflag, search_flags;
int filter;
char filter_state;
- char _pad;
+ char show_restrict_flags;
short filter_id_type;
/**
@@ -260,7 +260,7 @@ typedef struct SpaceOutliner {
typedef enum eSpaceOutliner_Flag {
SO_TESTBLOCKS = (1 << 0),
SO_NEWSELECTED = (1 << 1),
- SO_HIDE_RESTRICTCOLS = (1 << 2),
+ SO_FLAG_UNUSED_1 = (1 << 2), /* cleared */
SO_HIDE_KEYINGSETINFO = (1 << 3),
SO_SKIP_SORT_ALPHA = (1 << 4),
} eSpaceOutliner_Flag;
@@ -309,6 +309,17 @@ typedef enum eSpaceOutliner_StateFilter {
SO_FILTER_OB_ACTIVE = 3,
} eSpaceOutliner_StateFilter;
+/* SpaceOutliner.show_restrict_flags */
+typedef enum eSpaceOutliner_ShowRestrictFlag {
+ SO_RESTRICT_ENABLE = (1 << 0),
+ SO_RESTRICT_SELECT = (1 << 1),
+ SO_RESTRICT_HIDE = (1 << 2),
+ SO_RESTRICT_VIEWPORT = (1 << 3),
+ SO_RESTRICT_RENDER = (1 << 4),
+ SO_RESTRICT_HOLDOUT = (1 << 5),
+ SO_RESTRICT_INDIRECT_ONLY = (1 << 6),
+} eSpaceOutliner_Restrict;
+
/* SpaceOutliner.outlinevis */
typedef enum eSpaceOutliner_Mode {
SO_SCENES = 0,
diff --git a/source/blender/makesdna/DNA_userdef_types.h b/source/blender/makesdna/DNA_userdef_types.h
index 4a7b46fc154..9cab63dbfeb 100644
--- a/source/blender/makesdna/DNA_userdef_types.h
+++ b/source/blender/makesdna/DNA_userdef_types.h
@@ -38,11 +38,6 @@ struct ColorBand;
#define MAX_STYLE_NAME 64
-#define GPU_VIEWPORT_QUALITY_FXAA 0.10f
-#define GPU_VIEWPORT_QUALITY_TAA8 0.25f
-#define GPU_VIEWPORT_QUALITY_TAA16 0.6f
-#define GPU_VIEWPORT_QUALITY_TAA32 0.8f
-
/** default offered by Blender.
* #uiFont.uifont_id */
typedef enum eUIFont_ID {
@@ -189,6 +184,8 @@ typedef struct ThemeUI {
char gizmo_b[4];
/* Icon Colors. */
+ /** Scene items. */
+ char icon_scene[4];
/** Collection items. */
char icon_collection[4];
/** Object items. */
@@ -199,6 +196,9 @@ typedef struct ThemeUI {
char icon_modifier[4];
/** Shading related items. */
char icon_shading[4];
+ /** Intensity of the border icons. >0 will render an border around themed
+ * icons. */
+ float icon_border_intensity;
} ThemeUI;
/* try to put them all in one, if needed a special struct can be created as well
@@ -283,6 +283,8 @@ 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 _pad5[4];
char nurb_uline[4], nurb_vline[4];
char act_spline[4], nurb_sel_uline[4], nurb_sel_vline[4], lastsel_point[4];
@@ -361,6 +363,14 @@ typedef struct ThemeSpace {
char match[4];
/** Outliner - selected item. */
char selected_highlight[4];
+ /** Outliner - selected object. */
+ char selected_object[4];
+ /** Outliner - active object. */
+ char active_object[4];
+ /** Outliner - edited object. */
+ char edited_object[4];
+ /** Outliner - row color difference. */
+ char row_alternate[4];
/** Skin modifier root color. */
char skin_root[4];
@@ -372,7 +382,6 @@ typedef struct ThemeSpace {
char anim_non_active[4];
/** Preview range overlay. */
char anim_preview_range[4];
- char _pad2[4];
/** NLA 'Tweaking' action/strip. */
char nla_tweaking[4];
@@ -398,6 +407,8 @@ typedef struct ThemeSpace {
char metadatabg[4];
char metadatatext[4];
+
+ char _pad2[4];
} ThemeSpace;
/* set of colors for use as a custom color set for Objects/Bones wire drawing */
@@ -535,6 +546,11 @@ typedef struct WalkNavigation {
char _pad0[6];
} WalkNavigation;
+typedef struct UserDef_Runtime {
+ char is_dirty;
+ char _pad0[7];
+} UserDef_Runtime;
+
typedef struct UserDef {
/* UserDef has separate do-version handling, and can be read from other files */
int versionfile, subversionfile;
@@ -542,8 +558,12 @@ typedef struct UserDef {
/** #eUserPref_Flag. */
int flag;
/** #eDupli_ID_Flags. */
- int dupflag;
- int savetime;
+ short dupflag;
+ /**
+ * #eUserPref_PrefFlag preferences for the preferences. */
+ char pref_flag;
+ char savetime;
+ char _pad4[4];
/** FILE_MAXDIR length. */
char tempdir[768];
char fontdir[768];
@@ -600,6 +620,7 @@ typedef struct UserDef {
int dpi;
/** Runtime, multiplier to scale UI elements based on DPI. */
float dpi_fac;
+ float inv_dpi_fac;
/** Runtime, line width and point size based on DPI. */
float pixelsize;
/** Deprecated, for forward compatibility. */
@@ -609,7 +630,7 @@ typedef struct UserDef {
int scrollback;
/** Node insert offset (aka auto-offset) margin, but might be useful for later stuff as well. */
char node_margin;
- char _pad2[5];
+ char _pad2[1];
/** #eUserpref_Translation_Flags. */
short transopts;
short menuthreshold1, menuthreshold2;
@@ -633,7 +654,7 @@ typedef struct UserDef {
short undosteps;
char _pad1[2];
int undomemory;
- float gpu_viewport_quality;
+ float gpu_viewport_quality DNA_DEPRECATED;
short gp_manhattendist, gp_euclideandist, gp_eraser;
/** #eGP_UserdefSettings. */
short gp_settings;
@@ -643,7 +664,7 @@ typedef struct UserDef {
char _pad3[4];
short gizmo_flag, gizmo_size;
short edit_studio_light;
- char _pad6[2];
+ short lookdev_sphere_size;
short vbotimeout, vbocollectrate;
short textimeout, texcollectrate;
int memcachelimit;
@@ -761,7 +782,12 @@ typedef struct UserDef {
char factor_display_type;
- char _pad5[3];
+ char viewport_aa;
+
+ char _pad5[2];
+
+ /** Runtime data (keep last). */
+ UserDef_Runtime runtime;
} UserDef;
/* from blenkernel blender.c */
@@ -816,7 +842,7 @@ typedef enum eUserPref_Flag {
USER_TOOLTIPS = (1 << 11),
USER_TWOBUTTONMOUSE = (1 << 12),
USER_NONUMPAD = (1 << 13),
- USER_FLAG_UNUSED_14 = (1 << 14), /* cleared */
+ USER_ADD_CURSORALIGNED = (1 << 14),
USER_FILECOMPRESS = (1 << 15),
USER_SAVE_PREVIEWS = (1 << 16),
USER_CUSTOM_RANGE = (1 << 17),
@@ -831,6 +857,10 @@ typedef enum eUserPref_Flag {
USER_TOOLTIPS_PYTHON = (1 << 26),
} eUserPref_Flag;
+typedef enum eUserPref_PrefFlag {
+ USER_PREF_FLAG_SAVE = (1 << 0),
+} eUserPref_PrefFlag;
+
/** #bPathCompare.flag */
typedef enum ePathCompare_Flag {
USER_PATHCMP_GLOB = (1 << 0),
diff --git a/source/blender/makesdna/DNA_view2d_types.h b/source/blender/makesdna/DNA_view2d_types.h
index 0f25b47cb0b..8734a73c07a 100644
--- a/source/blender/makesdna/DNA_view2d_types.h
+++ b/source/blender/makesdna/DNA_view2d_types.h
@@ -151,10 +151,10 @@ enum {
V2D_SCROLL_BOTTOM = (1 << 3),
/* UNUSED = (1 << 4), */
V2D_SCROLL_HORIZONTAL = (V2D_SCROLL_TOP | V2D_SCROLL_BOTTOM),
- /* scale markings - vertical */
- V2D_SCROLL_SCALE_VERTICAL = (1 << 5),
- /* scale markings - horizontal */
- V2D_SCROLL_SCALE_HORIZONTAL = (1 << 6),
+ /* display vertical scale handles */
+ V2D_SCROLL_VERTICAL_HANDLES = (1 << 5),
+ /* display horizontal scale handles */
+ V2D_SCROLL_HORIZONTAL_HANDLES = (1 << 6),
/* induce hiding of scrollbars - set by region drawing in response to size of region */
V2D_SCROLL_VERTICAL_HIDE = (1 << 7),
V2D_SCROLL_HORIZONTAL_HIDE = (1 << 8),
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..82c356ab662 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,14 @@ 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(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 +1633,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,7 +1658,7 @@ 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,
@@ -1600,8 +1700,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 +1715,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]];
@@ -1642,4 +1742,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 b9e0853b1ab..3aa0ff4b28a 100644
--- a/source/blender/makesdna/intern/dna_rename_defs.h
+++ b/source/blender/makesdna/intern/dna_rename_defs.h
@@ -58,12 +58,12 @@ DNA_STRUCT_RENAME(SpaceIpo, SpaceGraph)
DNA_STRUCT_RENAME(SpaceOops, SpaceOutliner)
DNA_STRUCT_RENAME_ELEM(BPoint, alfa, tilt)
DNA_STRUCT_RENAME_ELEM(BezTriple, alfa, tilt)
-DNA_STRUCT_RENAME_ELEM(Bone, scaleIn, scale_in_x)
-DNA_STRUCT_RENAME_ELEM(Bone, scaleOut, scale_out_x)
DNA_STRUCT_RENAME_ELEM(Bone, curveInX, curve_in_x)
DNA_STRUCT_RENAME_ELEM(Bone, curveInY, curve_in_y)
DNA_STRUCT_RENAME_ELEM(Bone, curveOutX, curve_out_x)
DNA_STRUCT_RENAME_ELEM(Bone, curveOutY, curve_out_y)
+DNA_STRUCT_RENAME_ELEM(Bone, scaleIn, scale_in_x)
+DNA_STRUCT_RENAME_ELEM(Bone, scaleOut, scale_out_x)
DNA_STRUCT_RENAME_ELEM(Camera, YF_dofdist, dof_distance)
DNA_STRUCT_RENAME_ELEM(Camera, clipend, clip_end)
DNA_STRUCT_RENAME_ELEM(Camera, clipsta, clip_start)
@@ -77,12 +77,13 @@ DNA_STRUCT_RENAME_ELEM(ParticleSettings, dup_ob, instance_object)
DNA_STRUCT_RENAME_ELEM(ParticleSettings, dupliweights, instance_weights)
DNA_STRUCT_RENAME_ELEM(View3D, far, clip_end)
DNA_STRUCT_RENAME_ELEM(View3D, near, clip_start)
-DNA_STRUCT_RENAME_ELEM(bPoseChannel, scaleIn, scale_in_x)
-DNA_STRUCT_RENAME_ELEM(bPoseChannel, scaleOut, scale_out_x)
DNA_STRUCT_RENAME_ELEM(bPoseChannel, curveInX, curve_in_x)
DNA_STRUCT_RENAME_ELEM(bPoseChannel, curveInY, curve_in_y)
DNA_STRUCT_RENAME_ELEM(bPoseChannel, curveOutX, curve_out_x)
DNA_STRUCT_RENAME_ELEM(bPoseChannel, curveOutY, curve_out_y)
+DNA_STRUCT_RENAME_ELEM(bPoseChannel, scaleIn, scale_in_x)
+DNA_STRUCT_RENAME_ELEM(bPoseChannel, scaleOut, scale_out_x)
+DNA_STRUCT_RENAME_ELEM(bSameVolumeConstraint, flag, free_axis)
DNA_STRUCT_RENAME_ELEM(bTheme, tact, space_action)
DNA_STRUCT_RENAME_ELEM(bTheme, tbuts, space_properties)
DNA_STRUCT_RENAME_ELEM(bTheme, tclip, space_clip)
diff --git a/source/blender/makesdna/intern/makesdna.c b/source/blender/makesdna/intern/makesdna.c
index 0ea1ca9c018..7e53231a547 100644
--- a/source/blender/makesdna/intern/makesdna.c
+++ b/source/blender/makesdna/intern/makesdna.c
@@ -41,6 +41,8 @@
* numbers give more output.
*/
+#define DNA_DEPRECATED_ALLOW
+
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
@@ -142,10 +144,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`. */
@@ -159,7 +161,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;
@@ -342,7 +344,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 */
@@ -358,14 +359,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;
}
}
@@ -373,18 +374,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;
}
/**
@@ -511,7 +512,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;
}
@@ -526,15 +527,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)
@@ -542,23 +543,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;
}
@@ -894,7 +895,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. */
@@ -912,7 +913,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]);
@@ -1097,7 +1098,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];
@@ -1110,7 +1111,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];
@@ -1148,7 +1149,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");
@@ -1158,7 +1159,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]);
@@ -1188,15 +1189,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,
@@ -1231,7 +1232,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 */
@@ -1258,19 +1259,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];
@@ -1286,7 +1287,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 {
@@ -1297,11 +1298,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;
@@ -1313,11 +1314,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;
@@ -1330,19 +1331,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;
@@ -1355,7 +1356,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,
@@ -1363,7 +1364,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");
}
@@ -1371,7 +1372,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 a7b111d49da..30abf0f54bf 100644
--- a/source/blender/makesrna/RNA_access.h
+++ b/source/blender/makesrna/RNA_access.h
@@ -97,6 +97,7 @@ extern StructRNA RNA_BuildGpencilModifier;
extern StructRNA RNA_BuildModifier;
extern StructRNA RNA_CacheFile;
extern StructRNA RNA_Camera;
+extern StructRNA RNA_CameraDOFSettings;
extern StructRNA RNA_CastModifier;
extern StructRNA RNA_ChildOfConstraint;
extern StructRNA RNA_ChildParticle;
@@ -725,6 +726,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;
@@ -1030,9 +1032,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(PointerRNA *ptr, PropertyRNA *prop, PointerRNA ptr_value);
-PointerRNA RNA_property_pointer_get_default(PointerRNA *ptr, PropertyRNA *prop);
+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,
+ 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/RNA_enum_types.h b/source/blender/makesrna/RNA_enum_types.h
index 119186ff748..02aaef44a1f 100644
--- a/source/blender/makesrna/RNA_enum_types.h
+++ b/source/blender/makesrna/RNA_enum_types.h
@@ -96,6 +96,7 @@ extern const EnumPropertyItem rna_enum_keyblock_type_items[];
extern const EnumPropertyItem rna_enum_keyingset_path_grouping_items[];
extern const EnumPropertyItem rna_enum_keying_flag_items[];
+extern const EnumPropertyItem rna_enum_keying_flag_items_api[];
extern const EnumPropertyItem rna_enum_keyframe_paste_offset_items[];
extern const EnumPropertyItem rna_enum_keyframe_paste_merge_items[];
diff --git a/source/blender/makesrna/intern/makesrna.c b/source/blender/makesrna/intern/makesrna.c
index 3e948e2d712..35045a3a408 100644
--- a/source/blender/makesrna/intern/makesrna.c
+++ b/source/blender/makesrna/intern/makesrna.c
@@ -1033,10 +1033,10 @@ static char *rna_def_property_set_func(
break;
}
case PROP_POINTER: {
- fprintf(f, "void %s(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(ptr, value);\n", manualfunc);
+ fprintf(f, " %s(ptr, value, reports);\n", manualfunc);
}
else {
rna_print_data_get(f, dp);
@@ -2024,7 +2024,7 @@ static void rna_def_function_funcs_header(FILE *f, StructRNA *srna, FunctionDefR
char funcname[2048];
rna_construct_wrapper_function_name(
- funcname, sizeof(funcname), srna->identifier, func->identifier, NULL);
+ funcname, sizeof(funcname), srna->identifier, func->identifier, "func");
rna_generate_static_parameter_prototypes(f, srna, dfunc, funcname, 1);
}
@@ -2452,7 +2452,7 @@ static void rna_def_struct_function_call_impl_cpp(FILE *f, StructRNA *srna, Func
int first = 1;
rna_construct_wrapper_function_name(
- funcname, sizeof(funcname), srna->identifier, func->identifier, NULL);
+ funcname, sizeof(funcname), srna->identifier, func->identifier, "func");
fprintf(f, "%s(", funcname);
@@ -2615,7 +2615,7 @@ static void rna_def_function_wrapper_funcs(FILE *f, StructDefRNA *dsrna, Functio
}
rna_construct_wrapper_function_name(
- funcname, sizeof(funcname), srna->identifier, func->identifier, NULL);
+ funcname, sizeof(funcname), srna->identifier, func->identifier, "func");
rna_generate_static_parameter_prototypes(f, srna, dfunc, funcname, 0);
diff --git a/source/blender/makesrna/intern/rna_ID.c b/source/blender/makesrna/intern/rna_ID.c
index 149cd7caf84..7e6a3e70b9d 100644
--- a/source/blender/makesrna/intern/rna_ID.c
+++ b/source/blender/makesrna/intern/rna_ID.c
@@ -435,6 +435,11 @@ StructRNA *rna_PropertyGroup_refine(PointerRNA *ptr)
return ptr->type;
}
+static ID *rna_ID_evaluated_get(ID *id, struct Depsgraph *depsgraph)
+{
+ return DEG_get_evaluated_id(depsgraph, id);
+}
+
static ID *rna_ID_copy(ID *id, Main *bmain)
{
ID *newid;
@@ -458,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
@@ -473,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:
@@ -480,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)
@@ -1446,6 +1460,15 @@ static void rna_def_ID(BlenderRNA *brna)
RNA_def_property_pointer_funcs(prop, "rna_IDPreview_get", NULL, NULL, NULL);
/* functions */
+ func = RNA_def_function(srna, "evaluated_get", "rna_ID_evaluated_get");
+ RNA_def_function_ui_description(
+ func, "Get corresponding evaluated ID from the given dependency graph");
+ parm = RNA_def_pointer(
+ func, "depsgraph", "Depsgraph", "", "Dependency graph to perform lookup in");
+ RNA_def_parameter_flags(parm, PROP_NEVER_NULL, PARM_REQUIRED);
+ parm = RNA_def_pointer(func, "id", "ID", "", "New copy of the ID");
+ RNA_def_function_return(func, parm);
+
func = RNA_def_function(srna, "copy", "rna_ID_copy");
RNA_def_function_ui_description(
func, "Create a copy of this data-block (not supported for all data-blocks)");
@@ -1517,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 d5dfd0b5503..20358ca80fd 100644
--- a/source/blender/makesrna/intern/rna_access.c
+++ b/source/blender/makesrna/intern/rna_access.c
@@ -302,7 +302,7 @@ static IDProperty *rna_idproperty_ui_ensure(PointerRNA *ptr, PropertyRNA *prop,
idprop = IDP_New(IDP_GROUP, &dummy, RNA_IDP_UI);
if (!IDP_AddToGroup(props, idprop)) {
- IDP_FreeProperty(idprop);
+ IDP_FreePropertyContent(idprop);
return NULL;
}
}
@@ -316,7 +316,7 @@ static IDProperty *rna_idproperty_ui_ensure(PointerRNA *ptr, PropertyRNA *prop,
rv = IDP_New(IDP_GROUP, &dummy, name);
if (!IDP_AddToGroup(idprop, rv)) {
- IDP_FreeProperty(rv);
+ IDP_FreePropertyContent(rv);
return NULL;
}
}
@@ -370,7 +370,7 @@ static bool rna_idproperty_ui_set_default(PointerRNA *ptr,
item = IDP_New(type, value, "default");
if (!IDP_AddToGroup(idp_ui, item)) {
- IDP_FreeProperty(item);
+ IDP_FreePropertyContent(item);
return false;
}
}
@@ -3733,24 +3733,29 @@ PointerRNA RNA_property_pointer_get(PointerRNA *ptr, PropertyRNA *prop)
}
}
-void RNA_property_pointer_set(PointerRNA *ptr, PropertyRNA *prop, PointerRNA ptr_value)
+void RNA_property_pointer_set(PointerRNA *ptr,
+ PropertyRNA *prop,
+ PointerRNA ptr_value,
+ ReportList *reports)
{
PointerPropertyRNA *pprop = (PointerPropertyRNA *)prop;
BLI_assert(RNA_property_type(prop) == PROP_POINTER);
/* Check types */
if (ptr_value.type != NULL && !RNA_struct_is_a(ptr_value.type, pprop->type)) {
- printf("%s: expected %s type, not %s.\n",
- __func__,
- pprop->type->identifier,
- ptr_value.type->identifier);
+ BKE_reportf(reports,
+ RPT_ERROR,
+ "%s: expected %s type, not %s.\n",
+ __func__,
+ pprop->type->identifier,
+ ptr_value.type->identifier);
return;
}
/* 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(ptr, ptr_value);
+ pprop->set(ptr, ptr_value, reports);
}
/* IDProperty */
else if (prop->flag & PROP_EDITABLE) {
@@ -3961,7 +3966,7 @@ void RNA_property_collection_add(PointerRNA *ptr, PropertyRNA *prop, PointerRNA
item = IDP_New(IDP_GROUP, &val, "");
IDP_AppendArray(idprop, item);
/* IDP_AppendArray does a shallow copy (memcpy), only free memory */
- /* IDP_FreeProperty(item); */
+ /* IDP_FreePropertyContent(item); */
MEM_freeN(item);
rna_idproperty_touch(idprop);
}
@@ -3977,7 +3982,7 @@ void RNA_property_collection_add(PointerRNA *ptr, PropertyRNA *prop, PointerRNA
item = IDP_New(IDP_GROUP, &val, "");
IDP_AppendArray(idprop, item);
/* IDP_AppendArray does a shallow copy (memcpy), only free memory */
- /* IDP_FreeProperty(item); */
+ /* IDP_FreePropertyContent(item); */
MEM_freeN(item);
}
}
@@ -6422,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(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);
@@ -7971,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(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 bb3585df24e..4e98db21089 100644
--- a/source/blender/makesrna/intern/rna_action.c
+++ b/source/blender/makesrna/intern/rna_action.c
@@ -214,7 +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(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;
@@ -339,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 15429ec6b5e..6228414e4f4 100644
--- a/source/blender/makesrna/intern/rna_animation.c
+++ b/source/blender/makesrna/intern/rna_animation.c
@@ -72,6 +72,43 @@ const EnumPropertyItem rna_enum_keying_flag_items[] = {
{0, NULL, 0, NULL, NULL},
};
+/* Contains additional flags suitable for use in Python API functions. */
+const EnumPropertyItem rna_enum_keying_flag_items_api[] = {
+ {INSERTKEY_NEEDED,
+ "INSERTKEY_NEEDED",
+ 0,
+ "Only Needed",
+ "Only insert keyframes where they're needed in the relevant F-Curves"},
+ {INSERTKEY_MATRIX,
+ "INSERTKEY_VISUAL",
+ 0,
+ "Visual Keying",
+ "Insert keyframes based on 'visual transforms'"},
+ {INSERTKEY_XYZ2RGB,
+ "INSERTKEY_XYZ_TO_RGB",
+ 0,
+ "XYZ=RGB Colors",
+ "Color for newly added transformation F-Curves (Location, Rotation, Scale) "
+ "and also Color is based on the transform axis"},
+ {INSERTKEY_REPLACE,
+ "INSERTKEY_REPLACE",
+ 0,
+ "Replace Existing",
+ "Only replace existing keyframes"},
+ {INSERTKEY_AVAILABLE,
+ "INSERTKEY_AVAILABLE",
+ 0,
+ "Only Available",
+ "Don't create F-Curves when they don't already exist"},
+ {INSERTKEY_CYCLE_AWARE,
+ "INSERTKEY_CYCLE_AWARE",
+ 0,
+ "Cycle Aware Keying",
+ "When inserting into a curve with cyclic extrapolation, remap the keyframe inside "
+ "the cycle time range, and if changing an end key, also update the other one"},
+ {0, NULL, 0, NULL, NULL},
+};
+
#ifdef RNA_RUNTIME
# include "BLI_math_base.h"
@@ -114,7 +151,9 @@ static int rna_AnimData_action_editable(PointerRNA *ptr, const char **UNUSED(r_i
return PROP_EDITABLE;
}
-static void rna_AnimData_action_set(PointerRNA *ptr, PointerRNA value)
+static void rna_AnimData_action_set(PointerRNA *ptr,
+ PointerRNA value,
+ struct ReportList *UNUSED(reports))
{
ID *ownerId = (ID *)ptr->id.data;
@@ -424,7 +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(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;
@@ -575,7 +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(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;
@@ -1266,6 +1309,9 @@ static void rna_def_animdata(BlenderRNA *brna)
RNA_def_property_ui_text(
prop, "Use NLA Tweak Mode", "Whether to enable or disable tweak mode in NLA");
RNA_def_property_update(prop, NC_ANIMATION | ND_NLA, "rna_AnimData_update");
+
+ /* Animation Data API */
+ RNA_api_animdata(srna);
}
/* --- */
diff --git a/source/blender/makesrna/intern/rna_animation_api.c b/source/blender/makesrna/intern/rna_animation_api.c
index f201b8e6e99..e063e5de22c 100644
--- a/source/blender/makesrna/intern/rna_animation_api.c
+++ b/source/blender/makesrna/intern/rna_animation_api.c
@@ -37,6 +37,7 @@
# include "BKE_context.h"
# include "BKE_report.h"
+# include "BKE_nla.h"
# include "ED_keyframing.h"
@@ -59,6 +60,11 @@ static void rna_KeyingSet_context_refresh(KeyingSet *ks, bContext *C, ReportList
}
}
+static float rna_AnimData_nla_tweak_strip_time_to_scene(AnimData *adt, float frame, bool invert)
+{
+ return BKE_nla_tweakedit_remap(adt, frame, invert ? NLATIME_CONVERT_UNMAP : NLATIME_CONVERT_MAP);
+}
+
#else
void RNA_api_keyingset(StructRNA *srna)
@@ -75,4 +81,25 @@ void RNA_api_keyingset(StructRNA *srna)
RNA_def_function_flag(func, FUNC_USE_CONTEXT | FUNC_USE_REPORTS);
}
+void RNA_api_animdata(StructRNA *srna)
+{
+ FunctionRNA *func;
+ PropertyRNA *parm;
+
+ /* Convert between action time and scene time when tweaking a NLA strip. */
+ func = RNA_def_function(
+ srna, "nla_tweak_strip_time_to_scene", "rna_AnimData_nla_tweak_strip_time_to_scene");
+ RNA_def_function_ui_description(func,
+ "Convert a time value from the local time of the tweaked strip "
+ "to scene time, exactly as done by built-in key editing tools. "
+ "Returns the input time unchanged if not tweaking.");
+ parm = RNA_def_float(
+ func, "frame", 0.0, MINAFRAME, MAXFRAME, "", "Input time", MINAFRAME, MAXFRAME);
+ RNA_def_parameter_flags(parm, 0, PARM_REQUIRED);
+ RNA_def_boolean(func, "invert", false, "Invert", "Convert scene time to action time");
+ parm = RNA_def_float(
+ func, "result", 0.0, MINAFRAME, MAXFRAME, "", "Converted time", MINAFRAME, MAXFRAME);
+ RNA_def_function_return(func, parm);
+}
+
#endif
diff --git a/source/blender/makesrna/intern/rna_armature.c b/source/blender/makesrna/intern/rna_armature.c
index 5461aaa0f1a..604be10d5ab 100644
--- a/source/blender/makesrna/intern/rna_armature.c
+++ b/source/blender/makesrna/intern/rna_armature.c
@@ -67,7 +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(PointerRNA *ptr, PointerRNA value)
+static void rna_Armature_act_bone_set(PointerRNA *ptr,
+ PointerRNA value,
+ struct ReportList *UNUSED(reports))
{
bArmature *arm = (bArmature *)ptr->data;
@@ -89,7 +91,9 @@ static void rna_Armature_act_bone_set(PointerRNA *ptr, PointerRNA value)
}
}
-static void rna_Armature_act_edit_bone_set(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;
@@ -395,7 +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(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;
@@ -463,7 +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(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;
@@ -474,7 +482,9 @@ static void rna_EditBone_bbone_prev_set(PointerRNA *ptr, PointerRNA value)
}
}
-static void rna_Bone_bbone_prev_set(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;
@@ -491,7 +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(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;
@@ -502,7 +514,9 @@ static void rna_EditBone_bbone_next_set(PointerRNA *ptr, PointerRNA value)
}
}
-static void rna_Bone_bbone_next_set(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;
@@ -575,6 +589,20 @@ static void rna_Armature_bones_next(CollectionPropertyIterator *iter)
iter->valid = (internal->link != NULL);
}
+/* not essential, but much faster then the default lookup function */
+static int rna_Armature_bones_lookup_string(PointerRNA *ptr, const char *key, PointerRNA *r_ptr)
+{
+ bArmature *arm = (bArmature *)ptr->data;
+ Bone *bone = BKE_armature_find_bone_name(arm, key);
+ if (bone) {
+ RNA_pointer_create(ptr->id.data, &RNA_Bone, bone, r_ptr);
+ return true;
+ }
+ else {
+ return false;
+ }
+}
+
static bool rna_Armature_is_editmode_get(PointerRNA *ptr)
{
bArmature *arm = (bArmature *)ptr->id.data;
@@ -621,9 +649,10 @@ void rna_def_bone_curved_common(StructRNA *srna, bool is_posebone)
if (is_posebone == false) {
prop = RNA_def_property(srna, "use_endroll_as_inroll", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_ui_text(
- prop, "Inherit End Roll", "Use Roll Out of parent bone as Roll In of its children");
+ prop, "Inherit End Roll", "Add Roll Out of the Start Handle bone to the Roll In value");
RNA_def_property_boolean_sdna(prop, NULL, "flag", BONE_ADD_PARENT_END_ROLL);
- RNA_def_property_update(prop, 0, "rna_Armature_update_data");
+ RNA_def_property_clear_flag(prop, PROP_ANIMATABLE);
+ RNA_def_property_update(prop, 0, "rna_Armature_dependency_update");
}
/* Curve X/Y Offsets */
@@ -1285,8 +1314,15 @@ static void rna_def_armature(BlenderRNA *brna)
/* Collections */
prop = RNA_def_property(srna, "bones", PROP_COLLECTION, PROP_NONE);
RNA_def_property_collection_sdna(prop, NULL, "bonebase", NULL);
- RNA_def_property_collection_funcs(
- prop, NULL, "rna_Armature_bones_next", NULL, NULL, NULL, NULL, NULL, NULL);
+ RNA_def_property_collection_funcs(prop,
+ NULL,
+ "rna_Armature_bones_next",
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ "rna_Armature_bones_lookup_string",
+ NULL);
RNA_def_property_struct_type(prop, "Bone");
RNA_def_property_ui_text(prop, "Bones", "");
rna_def_armature_bones(brna, prop);
@@ -1359,13 +1395,6 @@ static void rna_def_armature(BlenderRNA *brna)
RNA_def_property_update(prop, 0, "rna_Armature_redraw_data");
RNA_def_property_flag(prop, PROP_LIB_EXCEPTION);
- prop = RNA_def_property(srna, "use_auto_ik", PROP_BOOLEAN, PROP_NONE);
- RNA_def_property_boolean_sdna(prop, NULL, "flag", ARM_AUTO_IK);
- RNA_def_property_ui_text(
- prop, "Auto IK", "Add temporary IK constraints while grabbing bones in Pose Mode");
- RNA_def_property_update(prop, 0, "rna_Armature_redraw_data");
- RNA_def_property_flag(prop, PROP_LIB_EXCEPTION);
-
prop = RNA_def_property(srna, "show_bone_custom_shapes", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_negative_sdna(prop, NULL, "flag", ARM_NO_CUSTOM);
RNA_def_property_ui_text(
diff --git a/source/blender/makesrna/intern/rna_camera.c b/source/blender/makesrna/intern/rna_camera.c
index 1f356624f3f..6bab07d2940 100644
--- a/source/blender/makesrna/intern/rna_camera.c
+++ b/source/blender/makesrna/intern/rna_camera.c
@@ -131,6 +131,38 @@ static void rna_Camera_dof_update(Main *bmain, Scene *scene, PointerRNA *UNUSED(
WM_main_add_notifier(NC_SCENE | ND_SEQUENCER, scene);
}
+char *rna_CameraDOFSettings_path(PointerRNA *ptr)
+{
+ /* if there is ID-data, resolve the path using the index instead of by name,
+ * since the name used is the name of the texture assigned, but the texture
+ * may be used multiple times in the same stack
+ */
+ if (ptr->id.data) {
+ if (GS(((ID *)ptr->id.data)->name) == ID_CA) {
+ return BLI_strdup("dof");
+ }
+ }
+
+ return BLI_strdup("");
+}
+
+static void rna_CameraDOFSettings_aperture_blades_set(PointerRNA *ptr, const int value)
+{
+ CameraDOFSettings *dofsettings = (CameraDOFSettings *)ptr->data;
+
+ if (value == 1 || value == 2) {
+ if (dofsettings->aperture_blades == 0) {
+ dofsettings->aperture_blades = 3;
+ }
+ else {
+ dofsettings->aperture_blades = 0;
+ }
+ }
+ else {
+ dofsettings->aperture_blades = value;
+ }
+}
+
#else
static void rna_def_camera_background_image(BlenderRNA *brna)
@@ -376,6 +408,68 @@ static void rna_def_camera_stereo_data(BlenderRNA *brna)
RNA_def_property_update(prop, NC_OBJECT | ND_DRAW, NULL);
}
+static void rna_def_camera_dof_settings_data(BlenderRNA *brna)
+{
+ StructRNA *srna;
+ PropertyRNA *prop;
+
+ srna = RNA_def_struct(brna, "CameraDOFSettings", NULL);
+ RNA_def_struct_sdna(srna, "CameraDOFSettings");
+ RNA_def_struct_path_func(srna, "rna_CameraDOFSettings_path");
+ RNA_def_struct_ui_text(srna, "Depth of Field", "Depth of Field settings");
+
+ prop = RNA_def_property(srna, "use_dof", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(prop, NULL, "flag", CAM_DOF_ENABLED);
+ RNA_def_property_ui_text(prop, "Depth of Field", "Use Depth of Field");
+ RNA_def_property_update(prop, NC_OBJECT | ND_DRAW, "rna_Camera_dof_update");
+
+ prop = RNA_def_property(srna, "focus_object", PROP_POINTER, PROP_NONE);
+ RNA_def_property_struct_type(prop, "Object");
+ RNA_def_property_pointer_sdna(prop, NULL, "focus_object");
+ RNA_def_property_flag(prop, PROP_EDITABLE);
+ RNA_def_property_ui_text(
+ prop, "Focus Object", "Use this object to define the depth of field focal point");
+ RNA_def_property_update(prop, NC_OBJECT | ND_DRAW, "rna_Camera_dependency_update");
+
+ prop = RNA_def_property(srna, "focus_distance", PROP_FLOAT, PROP_DISTANCE);
+ RNA_def_property_float_default(prop, 10.0f);
+ // RNA_def_property_pointer_sdna(prop, NULL, "focus_distance");
+ RNA_def_property_range(prop, 0.0f, FLT_MAX);
+ RNA_def_property_ui_range(prop, 0.0f, 5000.0f, 1, 2);
+ RNA_def_property_ui_text(
+ prop, "Focus Distance", "Distance to the focus point for depth of field");
+ RNA_def_property_update(prop, NC_OBJECT | ND_DRAW, "rna_Camera_dof_update");
+
+ prop = RNA_def_property(srna, "aperture_fstop", PROP_FLOAT, PROP_NONE);
+ RNA_def_property_ui_text(
+ prop,
+ "F-Stop",
+ "F-Stop ratio (lower numbers give more defocus, higher numbers give a sharper image)");
+ RNA_def_property_float_default(prop, 5.6f);
+ RNA_def_property_range(prop, 0.0f, FLT_MAX);
+ RNA_def_property_ui_range(prop, 0.1f, 128.0f, 10, 1);
+ RNA_def_property_update(prop, NC_OBJECT | ND_DRAW, "rna_Camera_dof_update");
+
+ prop = RNA_def_property(srna, "aperture_blades", PROP_INT, PROP_NONE);
+ RNA_def_property_ui_text(
+ prop, "Blades", "Number of blades in aperture for polygonal bokeh (at least 3)");
+ RNA_def_property_range(prop, 0, 16);
+ RNA_def_property_int_funcs(prop, NULL, "rna_CameraDOFSettings_aperture_blades_set", NULL);
+ RNA_def_property_update(prop, NC_OBJECT | ND_DRAW, "rna_Camera_dof_update");
+
+ prop = RNA_def_property(srna, "aperture_rotation", PROP_FLOAT, PROP_ANGLE);
+ RNA_def_property_ui_text(prop, "Rotation", "Rotation of blades in aperture");
+ RNA_def_property_range(prop, -M_PI, M_PI);
+ RNA_def_property_update(prop, NC_OBJECT | ND_DRAW, "rna_Camera_dof_update");
+
+ prop = RNA_def_property(srna, "aperture_ratio", PROP_FLOAT, PROP_NONE);
+ RNA_def_property_ui_text(prop, "Ratio", "Distortion to simulate anamorphic lens bokeh");
+ RNA_def_property_float_default(prop, 1.0f);
+ RNA_def_property_range(prop, 0.01f, FLT_MAX);
+ RNA_def_property_ui_range(prop, 1.0f, 2.0f, 0.1, 3);
+ RNA_def_property_update(prop, NC_OBJECT | ND_DRAW, "rna_Camera_dof_update");
+}
+
void RNA_def_camera(BlenderRNA *brna)
{
StructRNA *srna;
@@ -525,12 +619,6 @@ void RNA_def_camera(BlenderRNA *brna)
RNA_def_property_ui_text(prop, "Shift Y", "Camera vertical shift");
RNA_def_property_update(prop, NC_OBJECT | ND_DRAW, "rna_Camera_update");
- prop = RNA_def_property(srna, "dof_distance", PROP_FLOAT, PROP_DISTANCE);
- RNA_def_property_range(prop, 0.0f, FLT_MAX);
- RNA_def_property_ui_range(prop, 0.0f, 5000.0f, 1, 2);
- RNA_def_property_ui_text(prop, "DOF Distance", "Distance to the focus point for depth of field");
- RNA_def_property_update(prop, NC_OBJECT | ND_DRAW, "rna_Camera_dof_update");
-
/* Stereo Settings */
prop = RNA_def_property(srna, "stereo", PROP_POINTER, PROP_NONE);
RNA_def_property_flag(prop, PROP_NEVER_NULL);
@@ -645,17 +733,9 @@ void RNA_def_camera(BlenderRNA *brna)
RNA_def_property_update(prop, NC_CAMERA | ND_DRAW_RENDER_VIEWPORT, NULL);
/* pointers */
- prop = RNA_def_property(srna, "dof_object", PROP_POINTER, PROP_NONE);
- RNA_def_property_struct_type(prop, "Object");
- RNA_def_property_pointer_sdna(prop, NULL, "dof_ob");
- RNA_def_property_flag(prop, PROP_EDITABLE);
- RNA_def_property_ui_text(
- prop, "DOF Object", "Use this object to define the depth of field focal point");
- RNA_def_property_update(prop, NC_OBJECT | ND_DRAW, "rna_Camera_dependency_update");
-
- prop = RNA_def_property(srna, "gpu_dof", PROP_POINTER, PROP_NONE);
- RNA_def_property_struct_type(prop, "GPUDOFSettings");
- RNA_def_property_ui_text(prop, "GPU Depth Of Field", "");
+ prop = RNA_def_property(srna, "dof", PROP_POINTER, PROP_NONE);
+ RNA_def_property_struct_type(prop, "CameraDOFSettings");
+ RNA_def_property_ui_text(prop, "Depth Of Field", "");
RNA_def_property_update(prop, NC_OBJECT | ND_DRAW, NULL);
prop = RNA_def_property(srna, "background_images", PROP_COLLECTION, PROP_NONE);
@@ -674,6 +754,7 @@ void RNA_def_camera(BlenderRNA *brna)
/* *** Animated *** */
rna_def_camera_stereo_data(brna);
+ rna_def_camera_dof_settings_data(brna);
/* Camera API */
RNA_api_camera(srna);
diff --git a/source/blender/makesrna/intern/rna_cloth.c b/source/blender/makesrna/intern/rna_cloth.c
index 160634307f9..f5cb29b5e69 100644
--- a/source/blender/makesrna/intern/rna_cloth.c
+++ b/source/blender/makesrna/intern/rna_cloth.c
@@ -306,7 +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(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_collection.c b/source/blender/makesrna/intern/rna_collection.c
index 501895eefc8..ae944f59a35 100644
--- a/source/blender/makesrna/intern/rna_collection.c
+++ b/source/blender/makesrna/intern/rna_collection.c
@@ -405,15 +405,15 @@ void RNA_def_collections(BlenderRNA *brna)
RNA_def_property_override_flag(prop, PROPOVERRIDE_OVERRIDABLE_STATIC);
RNA_def_property_clear_flag(prop, PROP_ANIMATABLE);
RNA_def_property_ui_icon(prop, ICON_RESTRICT_SELECT_OFF, -1);
- RNA_def_property_ui_text(prop, "Disable Select", "Disable collection for viewport selection");
+ RNA_def_property_ui_text(prop, "Disable Selection", "Disable selection in viewport");
RNA_def_property_update(prop, NC_SCENE | ND_LAYER_CONTENT, "rna_Collection_flag_update");
prop = RNA_def_property(srna, "hide_viewport", PROP_BOOLEAN, PROP_NONE);
- RNA_def_property_boolean_sdna(prop, NULL, "flag", COLLECTION_RESTRICT_VIEW);
+ RNA_def_property_boolean_sdna(prop, NULL, "flag", COLLECTION_RESTRICT_VIEWPORT);
RNA_def_property_override_flag(prop, PROPOVERRIDE_OVERRIDABLE_STATIC);
RNA_def_property_clear_flag(prop, PROP_ANIMATABLE);
RNA_def_property_ui_icon(prop, ICON_RESTRICT_VIEW_OFF, -1);
- RNA_def_property_ui_text(prop, "Disable Viewport", "Disable collection in viewport");
+ RNA_def_property_ui_text(prop, "Disable in Viewports", "Globally disable in viewports");
RNA_def_property_update(prop, NC_SCENE | ND_LAYER_CONTENT, "rna_Collection_flag_update");
prop = RNA_def_property(srna, "hide_render", PROP_BOOLEAN, PROP_NONE);
@@ -421,7 +421,7 @@ void RNA_def_collections(BlenderRNA *brna)
RNA_def_property_override_flag(prop, PROPOVERRIDE_OVERRIDABLE_STATIC);
RNA_def_property_clear_flag(prop, PROP_ANIMATABLE);
RNA_def_property_ui_icon(prop, ICON_RESTRICT_RENDER_OFF, -1);
- RNA_def_property_ui_text(prop, "Disable Render", "Disable collection in renders");
+ RNA_def_property_ui_text(prop, "Disable in Renders", "Globally disable in renders");
RNA_def_property_update(prop, NC_SCENE | ND_LAYER_CONTENT, "rna_Collection_flag_update");
}
diff --git a/source/blender/makesrna/intern/rna_color.c b/source/blender/makesrna/intern/rna_color.c
index 40ee069657c..da2bf710428 100644
--- a/source/blender/makesrna/intern/rna_color.c
+++ b/source/blender/makesrna/intern/rna_color.c
@@ -525,6 +525,22 @@ static char *rna_ColorManagedViewSettings_path(PointerRNA *UNUSED(ptr))
return BLI_strdup("view_settings");
}
+static bool rna_ColorManagedColorspaceSettings_is_data_get(struct PointerRNA *ptr)
+{
+ ColorManagedColorspaceSettings *colorspace = (ColorManagedColorspaceSettings *)ptr->data;
+ const char *data_name = IMB_colormanagement_role_colorspace_name_get(COLOR_ROLE_DATA);
+ return STREQ(colorspace->name, data_name);
+}
+
+static void rna_ColorManagedColorspaceSettings_is_data_set(struct PointerRNA *ptr, bool value)
+{
+ ColorManagedColorspaceSettings *colorspace = (ColorManagedColorspaceSettings *)ptr->data;
+ if (value) {
+ const char *data_name = IMB_colormanagement_role_colorspace_name_get(COLOR_ROLE_DATA);
+ STRNCPY(colorspace->name, data_name);
+ }
+}
+
static int rna_ColorManagedColorspaceSettings_colorspace_get(struct PointerRNA *ptr)
{
ColorManagedColorspaceSettings *colorspace = (ColorManagedColorspaceSettings *)ptr->data;
@@ -1120,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},
};
@@ -1227,6 +1243,7 @@ static void rna_def_colormanage(BlenderRNA *brna)
prop = RNA_def_property(srna, "name", PROP_ENUM, PROP_NONE);
RNA_def_property_flag(prop, PROP_ENUM_NO_CONTEXT);
+ RNA_def_property_clear_flag(prop, PROP_ANIMATABLE);
RNA_def_property_enum_items(prop, color_space_items);
RNA_def_property_enum_funcs(prop,
"rna_ColorManagedColorspaceSettings_colorspace_get",
@@ -1235,6 +1252,17 @@ static void rna_def_colormanage(BlenderRNA *brna)
RNA_def_property_ui_text(prop, "Input Color Space", "Color space of the image or movie on disk");
RNA_def_property_update(prop, NC_WINDOW, "rna_ColorManagedColorspaceSettings_reload_update");
+ prop = RNA_def_property(srna, "is_data", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_clear_flag(prop, PROP_ANIMATABLE);
+ RNA_def_property_boolean_funcs(prop,
+ "rna_ColorManagedColorspaceSettings_is_data_get",
+ "rna_ColorManagedColorspaceSettings_is_data_set");
+ RNA_def_property_ui_text(
+ prop,
+ "Is Data",
+ "Treat image as non-color data without color management, like normal or displacement maps");
+ RNA_def_property_update(prop, NC_WINDOW, "rna_ColorManagement_update");
+
//
srna = RNA_def_struct(brna, "ColorManagedSequencerColorspaceSettings", NULL);
RNA_def_struct_path_func(srna, "rna_ColorManagedSequencerColorspaceSettings_path");
diff --git a/source/blender/makesrna/intern/rna_constraint.c b/source/blender/makesrna/intern/rna_constraint.c
index c1c235d497b..ac319a545ac 100644
--- a/source/blender/makesrna/intern/rna_constraint.c
+++ b/source/blender/makesrna/intern/rna_constraint.c
@@ -351,7 +351,9 @@ static StructRNA *rna_ConstraintType_refine(struct PointerRNA *ptr)
}
}
-static void rna_ConstraintTargetBone_target_set(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;
@@ -665,7 +667,9 @@ static bool rna_Constraint_cameraObject_poll(PointerRNA *ptr, PointerRNA value)
return 0;
}
-static void rna_Constraint_followTrack_camera_set(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;
@@ -682,7 +686,9 @@ static void rna_Constraint_followTrack_camera_set(PointerRNA *ptr, PointerRNA va
}
}
-static void rna_Constraint_followTrack_depthObject_set(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;
@@ -712,7 +718,9 @@ static bool rna_Constraint_followTrack_depthObject_poll(PointerRNA *ptr, Pointer
return 0;
}
-static void rna_Constraint_objectSolver_camera_set(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;
@@ -1327,6 +1335,13 @@ static void rna_def_constraint_size_like(BlenderRNA *brna)
RNA_def_property_ui_text(prop, "Copy Z", "Copy the target's Z scale");
RNA_def_property_update(prop, NC_OBJECT | ND_CONSTRAINT, "rna_Constraint_update");
+ prop = RNA_def_property(srna, "power", PROP_FLOAT, PROP_NONE);
+ RNA_def_property_float_sdna(prop, NULL, "power");
+ RNA_def_property_float_default(prop, 1.0f);
+ RNA_def_property_ui_range(prop, -FLT_MAX, FLT_MAX, 1, 3);
+ RNA_def_property_ui_text(prop, "Power", "Raise the target's scale to the specified power");
+ RNA_def_property_update(prop, NC_OBJECT | ND_CONSTRAINT, "rna_Constraint_update");
+
prop = RNA_def_property(srna, "use_offset", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "flag", SIZELIKE_OFFSET);
RNA_def_property_ui_text(prop, "Offset", "Combine original scale with copied scale");
@@ -1346,13 +1361,34 @@ static void rna_def_constraint_same_volume(BlenderRNA *brna)
StructRNA *srna;
PropertyRNA *prop;
- static const EnumPropertyItem volume_items[] = {
+ static const EnumPropertyItem axis_items[] = {
{SAMEVOL_X, "SAMEVOL_X", 0, "X", ""},
{SAMEVOL_Y, "SAMEVOL_Y", 0, "Y", ""},
{SAMEVOL_Z, "SAMEVOL_Z", 0, "Z", ""},
{0, NULL, 0, NULL, NULL},
};
+ static const EnumPropertyItem mode_items[] = {
+ {SAMEVOL_STRICT,
+ "STRICT",
+ 0,
+ "Strict",
+ "Volume is strictly preserved, overriding the scaling of non-free axes"},
+ {SAMEVOL_UNIFORM,
+ "UNIFORM",
+ 0,
+ "Uniform",
+ "Volume is preserved when the object is scaled uniformly. "
+ "Deviations from uniform scale on non-free axes are passed through"},
+ {SAMEVOL_SINGLE_AXIS,
+ "SINGLE_AXIS",
+ 0,
+ "Single Axis",
+ "Volume is preserved when the object is scaled only on the free axis. "
+ "Non-free axis scaling is passed through"},
+ {0, NULL, 0, NULL, NULL},
+ };
+
srna = RNA_def_struct(brna, "MaintainVolumeConstraint", "Constraint");
RNA_def_struct_ui_text(srna,
"Maintain Volume Constraint",
@@ -1360,11 +1396,18 @@ static void rna_def_constraint_same_volume(BlenderRNA *brna)
RNA_def_struct_sdna_from(srna, "bSameVolumeConstraint", "data");
prop = RNA_def_property(srna, "free_axis", PROP_ENUM, PROP_NONE);
- RNA_def_property_enum_sdna(prop, NULL, "flag");
- RNA_def_property_enum_items(prop, volume_items);
+ RNA_def_property_enum_sdna(prop, NULL, "free_axis");
+ RNA_def_property_enum_items(prop, axis_items);
RNA_def_property_ui_text(prop, "Free Axis", "The free scaling axis of the object");
RNA_def_property_update(prop, NC_OBJECT | ND_CONSTRAINT, "rna_Constraint_update");
+ prop = RNA_def_property(srna, "mode", PROP_ENUM, PROP_NONE);
+ RNA_def_property_enum_sdna(prop, NULL, "mode");
+ RNA_def_property_enum_items(prop, mode_items);
+ RNA_def_property_ui_text(
+ prop, "Mode", "The way the constraint treats original non-free axis scaling");
+ RNA_def_property_update(prop, NC_OBJECT | ND_CONSTRAINT, "rna_Constraint_update");
+
prop = RNA_def_property(srna, "volume", PROP_FLOAT, PROP_DISTANCE);
RNA_def_property_range(prop, 0.001f, 100.0f);
RNA_def_property_ui_text(prop, "Volume", "Volume of the bone at rest");
@@ -2576,6 +2619,13 @@ static void rna_def_constraint_spline_ik(BlenderRNA *brna)
"on top of the shape and scaling of the curve itself");
RNA_def_property_update(prop, NC_OBJECT | ND_CONSTRAINT, "rna_Constraint_update");
+ /* take original scaling of the bone into account in volume preservation */
+ prop = RNA_def_property(srna, "use_original_scale", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(prop, NULL, "flag", CONSTRAINT_SPLINEIK_USE_ORIGINAL_SCALE);
+ RNA_def_property_ui_text(
+ prop, "Use Original Scale", "Apply volume preservation over the original scaling");
+ RNA_def_property_update(prop, NC_OBJECT | ND_CONSTRAINT, "rna_Constraint_update");
+
/* volume presevation for "volumetric" scale mode */
prop = RNA_def_property(srna, "bulge", PROP_FLOAT, PROP_NONE);
RNA_def_property_range(prop, 0.0, 100.f);
diff --git a/source/blender/makesrna/intern/rna_context.c b/source/blender/makesrna/intern/rna_context.c
index 75f8b97b99d..a2ac7cb40ba 100644
--- a/source/blender/makesrna/intern/rna_context.c
+++ b/source/blender/makesrna/intern/rna_context.c
@@ -135,12 +135,6 @@ static PointerRNA rna_Context_main_get(PointerRNA *ptr)
return rna_pointer_inherit_refine(ptr, &RNA_BlendData, CTX_data_main(C));
}
-static PointerRNA rna_Context_depsgraph_get(PointerRNA *ptr)
-{
- bContext *C = (bContext *)ptr->data;
- return rna_pointer_inherit_refine(ptr, &RNA_Depsgraph, CTX_data_depsgraph(C));
-}
-
static PointerRNA rna_Context_scene_get(PointerRNA *ptr)
{
bContext *C = (bContext *)ptr->data;
@@ -204,6 +198,11 @@ static int rna_Context_mode_get(PointerRNA *ptr)
return CTX_data_mode_enum(C);
}
+static struct Depsgraph *rna_Context_evaluated_depsgraph_get(bContext *C)
+{
+ return CTX_data_evaluated_depsgraph(C);
+}
+
#else
void RNA_def_context(BlenderRNA *brna)
@@ -211,6 +210,9 @@ void RNA_def_context(BlenderRNA *brna)
StructRNA *srna;
PropertyRNA *prop;
+ FunctionRNA *func;
+ PropertyRNA *parm;
+
srna = RNA_def_struct(brna, "Context", NULL);
RNA_def_struct_ui_text(srna, "Context", "Current windowmanager and data context");
RNA_def_struct_sdna(srna, "bContext");
@@ -267,11 +269,6 @@ void RNA_def_context(BlenderRNA *brna)
RNA_def_property_struct_type(prop, "BlendData");
RNA_def_property_pointer_funcs(prop, "rna_Context_main_get", NULL, NULL, NULL);
- prop = RNA_def_property(srna, "depsgraph", PROP_POINTER, PROP_NONE);
- RNA_def_property_clear_flag(prop, PROP_EDITABLE);
- RNA_def_property_struct_type(prop, "Depsgraph");
- RNA_def_property_pointer_funcs(prop, "rna_Context_depsgraph_get", NULL, NULL, NULL);
-
prop = RNA_def_property(srna, "scene", PROP_POINTER, PROP_NONE);
RNA_def_property_clear_flag(prop, PROP_EDITABLE);
RNA_def_property_struct_type(prop, "Scene");
@@ -310,6 +307,16 @@ void RNA_def_context(BlenderRNA *brna)
RNA_def_property_enum_items(prop, rna_enum_context_mode_items);
RNA_def_property_clear_flag(prop, PROP_EDITABLE);
RNA_def_property_enum_funcs(prop, "rna_Context_mode_get", NULL, NULL);
+
+ func = RNA_def_function(srna, "evaluated_depsgraph_get", "rna_Context_evaluated_depsgraph_get");
+ RNA_def_function_ui_description(
+ func,
+ "Get the dependency graph for the current scene and view layer, to access to data-blocks "
+ "with animation and modifiers applied. If any data-blocks have been edited, the dependency "
+ "graph will be updated. This invalidates all references to evaluated data-blocks from the "
+ "dependency graph.");
+ parm = RNA_def_pointer(func, "depsgraph", "Depsgraph", "", "Evaluated dependency graph");
+ RNA_def_function_return(func, parm);
}
#endif
diff --git a/source/blender/makesrna/intern/rna_curve.c b/source/blender/makesrna/intern/rna_curve.c
index 9c7ad60f378..89200240b08 100644
--- a/source/blender/makesrna/intern/rna_curve.c
+++ b/source/blender/makesrna/intern/rna_curve.c
@@ -438,7 +438,9 @@ static PointerRNA rna_Curve_bevelObject_get(PointerRNA *ptr)
return rna_pointer_inherit_refine(ptr, NULL, NULL);
}
-static void rna_Curve_bevelObject_set(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;
@@ -481,7 +483,9 @@ static PointerRNA rna_Curve_taperObject_get(PointerRNA *ptr)
return rna_pointer_inherit_refine(ptr, NULL, NULL);
}
-static void rna_Curve_taperObject_set(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;
@@ -730,7 +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(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 20fbbed572c..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
@@ -890,9 +898,9 @@ StructRNA *RNA_def_struct_ptr(BlenderRNA *brna, const char *identifier, StructRN
srna->description = "";
/* may be overwritten later RNA_def_struct_translation_context */
srna->translation_context = BLT_I18NCONTEXT_DEFAULT_BPYRNA;
- srna->flag |= STRUCT_UNDO;
if (!srnafrom) {
srna->icon = ICON_DOT;
+ srna->flag |= STRUCT_UNDO;
}
if (DefRNA.preprocess) {
@@ -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 447318da744..df1727ff87c 100644
--- a/source/blender/makesrna/intern/rna_depsgraph.c
+++ b/source/blender/makesrna/intern/rna_depsgraph.c
@@ -36,11 +36,16 @@
#ifdef RNA_RUNTIME
+# ifdef WITH_PYTHON
+# include "BPY_extern.h"
+# endif
+
# include "BLI_iterator.h"
# include "BLI_math.h"
# include "BKE_anim.h"
# include "BKE_object.h"
+# include "BKE_scene.h"
# include "DEG_depsgraph_build.h"
# include "DEG_depsgraph_debug.h"
@@ -256,6 +261,20 @@ static void rna_Depsgraph_debug_stats(Depsgraph *depsgraph, char *result)
outer);
}
+static void rna_Depsgraph_update(Depsgraph *depsgraph, Main *bmain)
+{
+# ifdef WITH_PYTHON
+ /* Allow drivers to be evaluated */
+ BPy_BEGIN_ALLOW_THREADS;
+# endif
+
+ BKE_scene_graph_update_tagged(depsgraph, bmain);
+
+# ifdef WITH_PYTHON
+ BPy_END_ALLOW_THREADS;
+# endif
+}
+
/* Iteration over objects, simple version */
static void rna_Depsgraph_objects_begin(CollectionPropertyIterator *iter, PointerRNA *ptr)
@@ -603,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",
@@ -636,6 +647,15 @@ static void rna_def_depsgraph(BlenderRNA *brna)
RNA_def_parameter_flags(parm, PROP_THICK_WRAP, 0); /* needed for string return value */
RNA_def_function_output(func, parm);
+ /* Updates. */
+
+ func = RNA_def_function(srna, "update", "rna_Depsgraph_update");
+ RNA_def_function_ui_description(
+ func,
+ "Re-evaluate any modified data-blocks, for example for animation or modifiers. "
+ "This invalidates all references to evaluated data-blocks from this dependency graph.");
+ RNA_def_function_flag(func, FUNC_USE_MAIN);
+
/* Queries for original datablockls (the ones depsgraph is built for). */
prop = RNA_def_property(srna, "scene", PROP_POINTER, PROP_NONE);
diff --git a/source/blender/makesrna/intern/rna_fcurve.c b/source/blender/makesrna/intern/rna_fcurve.c
index c8df01a7dc7..741b73f4250 100644
--- a/source/blender/makesrna/intern/rna_fcurve.c
+++ b/source/blender/makesrna/intern/rna_fcurve.c
@@ -239,7 +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(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;
@@ -446,7 +448,9 @@ static void rna_FCurve_RnaPath_set(PointerRNA *ptr, const char *value)
fcu->rna_path = NULL;
}
-static void rna_FCurve_group_set(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;
@@ -520,18 +524,41 @@ static void rna_FCurve_range(FCurve *fcu, float range[2])
calc_fcurve_range(fcu, range, range + 1, false, false);
}
+static bool rna_FCurve_is_empty_get(PointerRNA *ptr)
+{
+ FCurve *fcu = (FCurve *)ptr->data;
+ 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,
@@ -544,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)
@@ -560,7 +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(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);
@@ -659,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)
@@ -897,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;
@@ -921,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);
@@ -938,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;
@@ -984,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;
@@ -999,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 */
@@ -1022,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
@@ -1205,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,
@@ -1222,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);
@@ -1534,6 +1548,7 @@ static void rna_def_fmodifier(BlenderRNA *brna)
prop = RNA_def_property(srna, "type", PROP_ENUM, PROP_NONE);
RNA_def_property_clear_flag(prop, PROP_EDITABLE);
RNA_def_property_enum_items(prop, rna_enum_fmodifier_type_items);
+ RNA_def_property_translation_context(prop, BLT_I18NCONTEXT_ID_ACTION);
RNA_def_property_ui_text(prop, "Type", "F-Curve Modifier Type");
/* settings */
@@ -1645,6 +1660,7 @@ static void rna_def_drivertarget(BlenderRNA *brna)
{DTAR_TRANSCHAN_SCALEX, "SCALE_X", 0, "X Scale", ""},
{DTAR_TRANSCHAN_SCALEY, "SCALE_Y", 0, "Y Scale", ""},
{DTAR_TRANSCHAN_SCALEZ, "SCALE_Z", 0, "Z Scale", ""},
+ {DTAR_TRANSCHAN_SCALE_AVG, "SCALE_AVG", 0, "Average Scale", ""},
{0, NULL, 0, NULL, NULL},
};
@@ -2097,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,
@@ -2129,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);
@@ -2294,6 +2312,14 @@ static void rna_def_fcurve(BlenderRNA *brna)
"when evaluating");
RNA_def_property_update(prop, NC_ANIMATION | ND_KEYFRAME_PROP, NULL);
+ prop = RNA_def_property(srna, "is_empty", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_funcs(prop, "rna_FCurve_is_empty_get", NULL);
+ RNA_def_property_clear_flag(prop, PROP_EDITABLE);
+ RNA_def_property_ui_text(prop,
+ "Empty",
+ "True if the curve contributes no animation due to lack of "
+ "keyframes or useful modifiers, and should be deleted");
+
/* Collections */
prop = RNA_def_property(srna, "sampled_points", PROP_COLLECTION, PROP_NONE);
RNA_def_property_collection_sdna(prop, NULL, "fpt", "totvert");
@@ -2339,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 737dbe36d17..cf6d85adc62 100644
--- a/source/blender/makesrna/intern/rna_gpencil.c
+++ b/source/blender/makesrna/intern/rna_gpencil.c
@@ -76,6 +76,36 @@ static EnumPropertyItem rna_enum_gpencil_onion_modes_items[] = {
{0, NULL, 0, NULL, NULL},
};
+const EnumPropertyItem rna_enum_onion_keyframe_type_items[] = {
+ {-1, "ALL", ICON_ACTION, "All Types", "Include all Keyframe types"},
+ {BEZT_KEYTYPE_KEYFRAME,
+ "KEYFRAME",
+ ICON_KEYTYPE_KEYFRAME_VEC,
+ "Keyframe",
+ "Normal keyframe - e.g. for key poses"},
+ {BEZT_KEYTYPE_BREAKDOWN,
+ "BREAKDOWN",
+ ICON_KEYTYPE_BREAKDOWN_VEC,
+ "Breakdown",
+ "A breakdown pose - e.g. for transitions between key poses"},
+ {BEZT_KEYTYPE_MOVEHOLD,
+ "MOVING_HOLD",
+ ICON_KEYTYPE_MOVING_HOLD_VEC,
+ "Moving Hold",
+ "A keyframe that is part of a moving hold"},
+ {BEZT_KEYTYPE_EXTREME,
+ "EXTREME",
+ ICON_KEYTYPE_EXTREME_VEC,
+ "Extreme",
+ "An 'extreme' pose, or some other purpose as needed"},
+ {BEZT_KEYTYPE_JITTER,
+ "JITTER",
+ ICON_KEYTYPE_JITTER_VEC,
+ "Jitter",
+ "A filler or baked keyframe for keying on ones, or some other purpose as needed"},
+ {0, NULL, 0, NULL, NULL},
+};
+
static const EnumPropertyItem rna_enum_gplayer_move_type_items[] = {
{-1, "UP", 0, "Up", ""},
{1, "DOWN", 0, "Down", ""},
@@ -251,7 +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(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;
@@ -345,7 +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(PointerRNA *ptr, PointerRNA value)
+static void rna_GPencil_active_layer_set(PointerRNA *ptr,
+ PointerRNA value,
+ struct ReportList *UNUSED(reports))
{
bGPdata *gpd = ptr->id.data;
@@ -810,7 +844,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");
@@ -861,11 +895,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,
@@ -1737,6 +1771,7 @@ static void rna_def_gpencil_data(BlenderRNA *brna)
RNA_def_property_int_sdna(prop, NULL, "gstep");
RNA_def_property_range(prop, 0, 120);
RNA_def_property_int_default(prop, 1);
+ RNA_def_parameter_clear_flags(prop, PROP_ANIMATABLE, 0);
RNA_def_property_ui_text(prop,
"Frames Before",
"Maximum number of frames to show before current frame "
@@ -1747,6 +1782,7 @@ static void rna_def_gpencil_data(BlenderRNA *brna)
RNA_def_property_int_sdna(prop, NULL, "gstep_next");
RNA_def_property_range(prop, 0, 120);
RNA_def_property_int_default(prop, 1);
+ RNA_def_parameter_clear_flags(prop, PROP_ANIMATABLE, 0);
RNA_def_property_ui_text(prop,
"Frames After",
"Maximum number of frames to show after current frame "
@@ -1756,6 +1792,7 @@ static void rna_def_gpencil_data(BlenderRNA *brna)
prop = RNA_def_property(srna, "use_ghost_custom_colors", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(
prop, NULL, "onion_flag", GP_ONION_GHOST_PREVCOL | GP_ONION_GHOST_NEXTCOL);
+ RNA_def_parameter_clear_flags(prop, PROP_ANIMATABLE, 0);
RNA_def_property_ui_text(prop, "Use Custom Ghost Colors", "Use custom colors for ghost frames");
RNA_def_property_update(prop, NC_GPENCIL | ND_DATA, "rna_GPencil_update");
@@ -1779,6 +1816,7 @@ static void rna_def_gpencil_data(BlenderRNA *brna)
prop = RNA_def_property(srna, "use_ghosts_always", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "onion_flag", GP_ONION_GHOST_ALWAYS);
+ RNA_def_parameter_clear_flags(prop, PROP_ANIMATABLE, 0);
RNA_def_property_ui_text(prop,
"Always Show Ghosts",
"Ghosts are shown in renders and animation playback. Useful for "
@@ -1788,17 +1826,27 @@ static void rna_def_gpencil_data(BlenderRNA *brna)
prop = RNA_def_property(srna, "onion_mode", PROP_ENUM, PROP_NONE);
RNA_def_property_enum_sdna(prop, NULL, "onion_mode");
RNA_def_property_enum_items(prop, rna_enum_gpencil_onion_modes_items);
+ RNA_def_parameter_clear_flags(prop, PROP_ANIMATABLE, 0);
RNA_def_property_ui_text(prop, "Mode", "Mode to display frames");
RNA_def_property_update(prop, NC_GPENCIL | ND_DATA, "rna_GPencil_update");
+ prop = RNA_def_property(srna, "onion_keyframe_type", PROP_ENUM, PROP_NONE);
+ RNA_def_property_enum_sdna(prop, NULL, "onion_keytype");
+ RNA_def_parameter_clear_flags(prop, PROP_ANIMATABLE, 0);
+ RNA_def_property_enum_items(prop, rna_enum_onion_keyframe_type_items);
+ RNA_def_property_ui_text(prop, "Filter By Type", "Type of keyframe (for filtering)");
+ RNA_def_property_update(prop, NC_GPENCIL | ND_DATA, "rna_GPencil_update");
+
prop = RNA_def_property(srna, "use_onion_fade", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "onion_flag", GP_ONION_FADE);
+ RNA_def_parameter_clear_flags(prop, PROP_ANIMATABLE, 0);
RNA_def_property_ui_text(
prop, "Fade", "Display onion keyframes with a fade in color transparency");
RNA_def_property_update(prop, NC_GPENCIL | ND_DATA, "rna_GPencil_update");
prop = RNA_def_property(srna, "use_onion_loop", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "onion_flag", GP_ONION_LOOP);
+ RNA_def_parameter_clear_flags(prop, PROP_ANIMATABLE, 0);
RNA_def_property_ui_text(prop,
"Loop",
"Display first onion keyframes using next frame color to show "
@@ -1809,6 +1857,7 @@ static void rna_def_gpencil_data(BlenderRNA *brna)
RNA_def_property_float_sdna(prop, NULL, "onion_factor");
RNA_def_property_float_default(prop, 0.5f);
RNA_def_property_range(prop, 0.0, 1.0f);
+ RNA_def_parameter_clear_flags(prop, PROP_ANIMATABLE, 0);
RNA_def_property_ui_text(prop, "Onion Opacity", "Change fade opacity of displayed onion frames");
RNA_def_property_update(prop, NC_GPENCIL | ND_DATA, "rna_GPencil_update");
diff --git a/source/blender/makesrna/intern/rna_gpencil_modifier.c b/source/blender/makesrna/intern/rna_gpencil_modifier.c
index d1ae46a74f7..cca291a0aae 100644
--- a/source/blender/makesrna/intern/rna_gpencil_modifier.c
+++ b/source/blender/makesrna/intern/rna_gpencil_modifier.c
@@ -296,7 +296,8 @@ static void greasepencil_modifier_object_set(Object *self,
}
# define RNA_GP_MOD_OBJECT_SET(_type, _prop, _obtype) \
- static void rna_##_type##GpencilModifier_##_prop##_set(PointerRNA *ptr, PointerRNA value) \
+ static void rna_##_type##GpencilModifier_##_prop##_set( \
+ 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); \
@@ -308,7 +309,9 @@ RNA_GP_MOD_OBJECT_SET(Mirror, object, OB_EMPTY);
# undef RNA_GP_MOD_OBJECT_SET
-static void rna_HookGpencilModifier_object_set(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 34373e469c1..7f2eccf421e 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! */
@@ -406,7 +409,8 @@ static void rna_Image_pixels_set(PointerRNA *ptr, const float *values)
((unsigned char *)ibuf->rect)[i] = unit_float_to_uchar_clamp(values[i]);
}
- ibuf->userflags |= IB_BITMAPDIRTY | IB_DISPLAY_BUFFER_INVALID | IB_MIPMAP_INVALID;
+ ibuf->userflags |= IB_DISPLAY_BUFFER_INVALID | IB_MIPMAP_INVALID;
+ BKE_image_mark_dirty(ima, ibuf);
if (!G.background) {
GPU_free_image(ima);
}
@@ -478,7 +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(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) {
@@ -677,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},
};
@@ -741,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);
diff --git a/source/blender/makesrna/intern/rna_image_api.c b/source/blender/makesrna/intern/rna_image_api.c
index ca75f862b11..553dbeeb97b 100644
--- a/source/blender/makesrna/intern/rna_image_api.c
+++ b/source/blender/makesrna/intern/rna_image_api.c
@@ -211,69 +211,30 @@ static void rna_Image_scale(Image *image, ReportList *reports, int width, int he
}
}
-static int rna_Image_gl_load(Image *image, ReportList *reports, int frame, int filter, int mag)
+static int rna_Image_gl_load(Image *image, ReportList *reports, int frame)
{
- GPUTexture *tex = image->gputexture[TEXTARGET_TEXTURE_2D];
- int error = GL_NO_ERROR;
-
- if (tex)
- return error;
-
ImageUser iuser = {NULL};
iuser.framenr = frame;
iuser.ok = true;
- void *lock;
- ImBuf *ibuf = BKE_image_acquire_ibuf(image, &iuser, &lock);
-
- /* clean glError buffer */
- while (glGetError() != GL_NO_ERROR) {
- }
+ GPUTexture *tex = GPU_texture_from_blender(image, &iuser, GL_TEXTURE_2D);
- if (ibuf == NULL || ibuf->rect == NULL) {
- BKE_reportf(reports, RPT_ERROR, "Image '%s' does not have any image data", image->id.name + 2);
- BKE_image_release_ibuf(image, ibuf, lock);
+ if (tex == NULL) {
+ BKE_reportf(reports, RPT_ERROR, "Failed to load image texture '%s'", image->id.name + 2);
return (int)GL_INVALID_OPERATION;
}
- unsigned int bindcode = 0;
- GPU_create_gl_tex(&bindcode,
- ibuf->rect,
- ibuf->rect_float,
- ibuf->x,
- ibuf->y,
- GL_TEXTURE_2D,
- (filter != GL_NEAREST && filter != GL_LINEAR),
- false,
- image);
-
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, (GLint)filter);
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, (GLint)mag);
-
- /* TODO(merwin): validate input (dimensions, filter, mag) before calling OpenGL
- * instead of trusting input & testing for error after */
- error = glGetError();
-
- if (error) {
- glDeleteTextures(1, (GLuint *)&bindcode);
- }
- else {
- image->gputexture[TEXTARGET_TEXTURE_2D] = GPU_texture_from_bindcode(GL_TEXTURE_2D, bindcode);
- }
-
- BKE_image_release_ibuf(image, ibuf, lock);
-
- return error;
+ return GL_NO_ERROR;
}
-static int rna_Image_gl_touch(Image *image, ReportList *reports, int frame, int filter, int mag)
+static int rna_Image_gl_touch(Image *image, ReportList *reports, int frame)
{
int error = GL_NO_ERROR;
BKE_image_tag_time(image);
if (image->gputexture[TEXTARGET_TEXTURE_2D] == NULL)
- error = rna_Image_gl_load(image, reports, frame, filter, mag);
+ error = rna_Image_gl_load(image, reports, frame);
return error;
}
@@ -367,52 +328,20 @@ void RNA_api_image(StructRNA *srna)
RNA_def_function_flag(func, FUNC_USE_REPORTS);
RNA_def_int(
func, "frame", 0, 0, INT_MAX, "Frame", "Frame of image sequence or movie", 0, INT_MAX);
- RNA_def_int(func,
- "filter",
- GL_LINEAR_MIPMAP_NEAREST,
- -INT_MAX,
- INT_MAX,
- "Filter",
- "The texture minifying function to use if the image wasn't loaded",
- -INT_MAX,
- INT_MAX);
- RNA_def_int(func,
- "mag",
- GL_LINEAR,
- -INT_MAX,
- INT_MAX,
- "Magnification",
- "The texture magnification function to use if the image wasn't loaded",
- -INT_MAX,
- INT_MAX);
/* return value */
parm = RNA_def_int(
func, "error", 0, -INT_MAX, INT_MAX, "Error", "OpenGL error value", -INT_MAX, INT_MAX);
RNA_def_function_return(func, parm);
func = RNA_def_function(srna, "gl_load", "rna_Image_gl_load");
- RNA_def_function_ui_description(func, "Load the image into OpenGL graphics memory");
+ RNA_def_function_ui_description(
+ func,
+ "Load the image into an OpenGL texture. On success, image.bindcode will contain the "
+ "OpenGL texture bindcode. Colors read from the texture will be in scene linear color space "
+ "and have premultiplied alpha.");
RNA_def_function_flag(func, FUNC_USE_REPORTS);
RNA_def_int(
func, "frame", 0, 0, INT_MAX, "Frame", "Frame of image sequence or movie", 0, INT_MAX);
- RNA_def_int(func,
- "filter",
- GL_LINEAR_MIPMAP_NEAREST,
- -INT_MAX,
- INT_MAX,
- "Filter",
- "The texture minifying function",
- -INT_MAX,
- INT_MAX);
- RNA_def_int(func,
- "mag",
- GL_LINEAR,
- -INT_MAX,
- INT_MAX,
- "Magnification",
- "The texture magnification function",
- -INT_MAX,
- INT_MAX);
/* return value */
parm = RNA_def_int(
func, "error", 0, -INT_MAX, INT_MAX, "Error", "OpenGL error value", -INT_MAX, INT_MAX);
diff --git a/source/blender/makesrna/intern/rna_internal.h b/source/blender/makesrna/intern/rna_internal.h
index 3653f28c880..2659cdf227e 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;
@@ -277,7 +287,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 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,
@@ -339,9 +351,14 @@ 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);
+void RNA_api_animdata(struct StructRNA *srna);
void RNA_api_armature_edit_bone(StructRNA *srna);
void RNA_api_bone(StructRNA *srna);
void RNA_api_camera(StructRNA *srna);
@@ -547,13 +564,6 @@ PointerRNA rna_pointer_inherit_refine(struct PointerRNA *ptr, struct StructRNA *
int rna_parameter_size(struct PropertyRNA *parm);
-struct Mesh *rna_Main_meshes_new_from_object(struct Main *bmain,
- struct ReportList *reports,
- struct Depsgraph *depsgraph,
- struct Object *ob,
- bool apply_modifiers,
- bool calc_undeformed);
-
/* XXX, these should not need to be defined here~! */
struct MTex *rna_mtex_texture_slots_add(struct ID *self,
struct bContext *C,
diff --git a/source/blender/makesrna/intern/rna_internal_types.h b/source/blender/makesrna/intern/rna_internal_types.h
index 92c895bd854..ccead626bb6 100644
--- a/source/blender/makesrna/intern/rna_internal_types.h
+++ b/source/blender/makesrna/intern/rna_internal_types.h
@@ -37,6 +37,7 @@ struct IDProperty;
struct Main;
struct PointerRNA;
struct PropertyRNA;
+struct ReportList;
struct Scene;
struct StructRNA;
struct bContext;
@@ -85,7 +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 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 1985099e060..c5997f27dc2 100644
--- a/source/blender/makesrna/intern/rna_key.c
+++ b/source/blender/makesrna/intern/rna_key.c
@@ -316,7 +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(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 a71adec4e5c..cae59fc1285 100644
--- a/source/blender/makesrna/intern/rna_layer.c
+++ b/source/blender/makesrna/intern/rna_layer.c
@@ -67,7 +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(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;
@@ -84,7 +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(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)
@@ -187,6 +191,15 @@ static void rna_ObjectBase_select_update(Main *UNUSED(bmain),
ED_object_base_select(base, mode);
}
+static void rna_ObjectBase_hide_viewport_update(bContext *C, PointerRNA *UNUSED(ptr))
+{
+ Scene *scene = CTX_data_scene(C);
+ ViewLayer *view_layer = CTX_data_view_layer(C);
+ BKE_layer_collection_sync(scene, view_layer);
+ DEG_id_tag_update(&scene->id, ID_RECALC_BASE_FLAGS);
+ WM_event_add_notifier(C, NC_SCENE | ND_OB_SELECT, scene);
+}
+
static void rna_LayerCollection_name_get(struct PointerRNA *ptr, char *value)
{
ID *id = (ID *)((LayerCollection *)ptr->data)->collection;
@@ -199,12 +212,29 @@ int rna_LayerCollection_name_length(PointerRNA *ptr)
return strlen(id->name + 2);
}
+static void rna_LayerCollection_exclude_update_recursive(ListBase *lb, const bool exclude)
+{
+ for (LayerCollection *lc = lb->first; lc; lc = lc->next) {
+ if (exclude) {
+ lc->flag |= LAYER_COLLECTION_EXCLUDE;
+ }
+ else {
+ lc->flag &= ~LAYER_COLLECTION_EXCLUDE;
+ }
+ rna_LayerCollection_exclude_update_recursive(&lc->layer_collections, exclude);
+ }
+}
+
static void rna_LayerCollection_exclude_update(Main *bmain, Scene *UNUSED(scene), PointerRNA *ptr)
{
Scene *scene = (Scene *)ptr->id.data;
LayerCollection *lc = (LayerCollection *)ptr->data;
ViewLayer *view_layer = BKE_view_layer_find_from_collection(scene, lc);
+ /* Set/Unset it recursively to match the behaviour of excluding via the menu or shortcuts. */
+ rna_LayerCollection_exclude_update_recursive(&lc->layer_collections,
+ (lc->flag & LAYER_COLLECTION_EXCLUDE) != 0);
+
BKE_layer_collection_sync(scene, view_layer);
DEG_id_tag_update(&scene->id, ID_RECALC_BASE_FLAGS);
@@ -266,21 +296,26 @@ static void rna_def_layer_collection(BlenderRNA *brna)
RNA_def_property_struct_type(prop, "LayerCollection");
RNA_def_property_ui_text(prop, "Children", "Child layer collections");
+ /* Restriction flags. */
prop = RNA_def_property(srna, "exclude", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "flag", LAYER_COLLECTION_EXCLUDE);
RNA_def_property_clear_flag(prop, PROP_ANIMATABLE);
- RNA_def_property_ui_text(prop, "Exclude", "Exclude collection from view layer");
+ RNA_def_property_ui_text(prop, "Exclude from View Layer", "Exclude from view layer");
+ RNA_def_property_clear_flag(prop, PROP_ANIMATABLE);
+ RNA_def_property_ui_icon(prop, ICON_CHECKBOX_HLT, -1);
RNA_def_property_update(prop, NC_SCENE | ND_LAYER, "rna_LayerCollection_exclude_update");
prop = RNA_def_property(srna, "holdout", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "flag", LAYER_COLLECTION_HOLDOUT);
RNA_def_property_clear_flag(prop, PROP_ANIMATABLE);
+ RNA_def_property_ui_icon(prop, ICON_HOLDOUT_OFF, 1);
RNA_def_property_ui_text(prop, "Holdout", "Mask out objects in collection from view layer");
RNA_def_property_update(prop, NC_SCENE | ND_LAYER, "rna_LayerCollection_update");
prop = RNA_def_property(srna, "indirect_only", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "flag", LAYER_COLLECTION_INDIRECT_ONLY);
RNA_def_property_clear_flag(prop, PROP_ANIMATABLE);
+ RNA_def_property_ui_icon(prop, ICON_INDIRECT_ONLY_OFF, 1);
RNA_def_property_ui_text(
prop,
"Indirect Only",
@@ -289,14 +324,13 @@ static void rna_def_layer_collection(BlenderRNA *brna)
RNA_def_property_update(prop, NC_SCENE | ND_LAYER, "rna_LayerCollection_update");
prop = RNA_def_property(srna, "hide_viewport", PROP_BOOLEAN, PROP_NONE);
- RNA_def_property_boolean_sdna(prop, NULL, "flag", LAYER_COLLECTION_RESTRICT_VIEW);
+ RNA_def_property_boolean_sdna(prop, NULL, "flag", LAYER_COLLECTION_HIDE);
RNA_def_property_override_flag(prop, PROPOVERRIDE_OVERRIDABLE_STATIC);
- RNA_def_property_clear_flag(prop, PROP_ANIMATABLE);
RNA_def_property_ui_icon(prop, ICON_HIDE_OFF, -1);
- RNA_def_property_ui_text(
- prop, "Disable Viewport", "Disable collection in viewport for this view layer");
+ RNA_def_property_ui_text(prop, "Hide in Viewport", "Temporarily hide in viewport");
RNA_def_property_update(prop, NC_SCENE | ND_LAYER_CONTENT, "rna_LayerCollection_update");
+ /* Run-time flags. */
prop = RNA_def_property(srna, "is_visible", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "runtime_flag", LAYER_COLLECTION_VISIBLE);
RNA_def_property_clear_flag(prop, PROP_EDITABLE);
@@ -374,6 +408,14 @@ static void rna_def_object_base(BlenderRNA *brna)
RNA_def_property_boolean_sdna(prop, NULL, "flag", BASE_SELECTED);
RNA_def_property_ui_text(prop, "Select", "Object base selection state");
RNA_def_property_update(prop, NC_OBJECT | ND_DRAW, "rna_ObjectBase_select_update");
+
+ prop = RNA_def_property(srna, "hide_viewport", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(prop, NULL, "flag", BASE_HIDDEN);
+ 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");
+ RNA_def_property_flag(prop, PROP_CONTEXT_UPDATE);
+ RNA_def_property_update(prop, NC_OBJECT | ND_DRAW, "rna_ObjectBase_hide_viewport_update");
}
void RNA_def_view_layer(BlenderRNA *brna)
@@ -428,7 +470,7 @@ void RNA_def_view_layer(BlenderRNA *brna)
/* layer options */
prop = RNA_def_property(srna, "use", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "flag", VIEW_LAYER_RENDER);
- RNA_def_property_ui_text(prop, "Enabled", "Disable or enable the render layer");
+ RNA_def_property_ui_text(prop, "Enabled", "Enable or disable rendering of this View Layer");
RNA_def_property_update(prop, NC_SCENE | ND_LAYER, NULL);
prop = RNA_def_property(srna, "use_freestyle", PROP_BOOLEAN, PROP_NONE);
diff --git a/source/blender/makesrna/intern/rna_light.c b/source/blender/makesrna/intern/rna_light.c
index da2b5752a0f..a271b883e38 100644
--- a/source/blender/makesrna/intern/rna_light.c
+++ b/source/blender/makesrna/intern/rna_light.c
@@ -205,7 +205,7 @@ static void rna_def_light_energy(StructRNA *srna, bool distant)
* scene unit scale. */
prop = RNA_def_property(srna, "energy", PROP_FLOAT, PROP_POWER);
RNA_def_property_float_default(prop, 10.0f);
- RNA_def_property_ui_range(prop, 0.0f, 1000000.0f, 1, 5);
+ RNA_def_property_ui_range(prop, 0.0f, 1000000.0f, 10, 5);
RNA_def_property_ui_text(prop, "Power", "Amount of light emitted");
RNA_def_property_update(prop, 0, "rna_Light_draw_update");
}
@@ -545,12 +545,20 @@ static void rna_def_spot_light(BlenderRNA *brna)
static void rna_def_sun_light(BlenderRNA *brna)
{
StructRNA *srna;
+ PropertyRNA *prop;
srna = RNA_def_struct(brna, "SunLight", "Light");
RNA_def_struct_sdna(srna, "Light");
RNA_def_struct_ui_text(srna, "Sun Light", "Constant direction parallel ray Light");
RNA_def_struct_ui_icon(srna, ICON_LIGHT_SUN);
+ prop = RNA_def_property(srna, "angle", PROP_FLOAT, PROP_ANGLE);
+ RNA_def_property_float_sdna(prop, NULL, "sun_angle");
+ RNA_def_property_float_default(prop, DEG2RADF(0.526f));
+ RNA_def_property_range(prop, DEG2RADF(0.0f), DEG2RADF(180.0f));
+ RNA_def_property_ui_text(prop, "Angle", "Angular diameter of the Sun as seen from the Earth");
+ RNA_def_property_update(prop, 0, "rna_Light_update");
+
rna_def_light_energy(srna, true);
rna_def_light_shadow(srna, true);
}
diff --git a/source/blender/makesrna/intern/rna_lightprobe.c b/source/blender/makesrna/intern/rna_lightprobe.c
index 125d2ade567..8b6b248eac2 100644
--- a/source/blender/makesrna/intern/rna_lightprobe.c
+++ b/source/blender/makesrna/intern/rna_lightprobe.c
@@ -77,7 +77,7 @@ static void rna_def_lightprobe(BlenderRNA *brna)
srna = RNA_def_struct(brna, "LightProbe", "ID");
RNA_def_struct_ui_text(
srna, "LightProbe", "Light Probe data-block for lighting capture objects");
- RNA_def_struct_ui_icon(srna, ICON_OUTLINER_OB_LIGHTPROBE);
+ RNA_def_struct_ui_icon(srna, ICON_OUTLINER_DATA_LIGHTPROBE);
prop = RNA_def_property(srna, "type", PROP_ENUM, PROP_NONE);
RNA_def_property_enum_items(prop, lightprobe_type_items);
diff --git a/source/blender/makesrna/intern/rna_linestyle.c b/source/blender/makesrna/intern/rna_linestyle.c
index 3a6f283e1dc..1ef5fb17ed8 100644
--- a/source/blender/makesrna/intern/rna_linestyle.c
+++ b/source/blender/makesrna/intern/rna_linestyle.c
@@ -356,7 +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(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 d5347e77348..bd06cfc1936 100644
--- a/source/blender/makesrna/intern/rna_main_api.c
+++ b/source/blender/makesrna/intern/rna_main_api.c
@@ -125,6 +125,14 @@ static void rna_Main_ID_remove(Main *bmain,
bool do_ui_user)
{
ID *id = id_ptr->data;
+ if (id->tag & LIB_TAG_NO_MAIN) {
+ BKE_reportf(reports,
+ RPT_ERROR,
+ "%s '%s' is outside of main database and can not be removed from it",
+ BKE_idcode_to_name(GS(id->name)),
+ id->name + 2);
+ return;
+ }
if (do_unlink) {
BKE_id_delete(bmain, id);
RNA_POINTER_INVALIDATE(id_ptr);
@@ -200,6 +208,13 @@ static void rna_Main_scenes_remove(
static Object *rna_Main_objects_new(Main *bmain, ReportList *reports, const char *name, ID *data)
{
+ if (data != NULL && (data->tag & LIB_TAG_NO_MAIN)) {
+ BKE_report(reports,
+ RPT_ERROR,
+ "Can not create object in main database with an evaluated data data-block");
+ return NULL;
+ }
+
char safe_name[MAX_ID_NAME - 2];
rna_idname_validate(name, safe_name);
@@ -273,6 +288,15 @@ static void rna_Main_materials_gpencil_data(Main *UNUSED(bmain), PointerRNA *id_
BKE_material_init_gpencil_settings(ma);
}
+static void rna_Main_materials_gpencil_remove(Main *UNUSED(bmain), PointerRNA *id_ptr)
+{
+ ID *id = id_ptr->data;
+ Material *ma = (Material *)id;
+ if (ma->gp_style) {
+ MEM_SAFE_FREE(ma->gp_style);
+ }
+}
+
static const EnumPropertyItem *rna_Main_nodetree_type_itemf(bContext *UNUSED(C),
PointerRNA *UNUSED(ptr),
PropertyRNA *UNUSED(prop),
@@ -308,16 +332,9 @@ static Mesh *rna_Main_meshes_new(Main *bmain, const char *name)
}
/* copied from Mesh_getFromObject and adapted to RNA interface */
-Mesh *rna_Main_meshes_new_from_object(Main *bmain,
- ReportList *reports,
- Depsgraph *depsgraph,
- Object *ob,
- bool apply_modifiers,
- bool calc_undeformed)
+static Mesh *rna_Main_meshes_new_from_object(Main *bmain, ReportList *reports, Object *object)
{
- Scene *sce = DEG_get_evaluated_scene(depsgraph);
-
- switch (ob->type) {
+ switch (object->type) {
case OB_FONT:
case OB_CURVE:
case OB_SURF:
@@ -329,7 +346,7 @@ Mesh *rna_Main_meshes_new_from_object(Main *bmain,
return NULL;
}
- return BKE_mesh_new_from_object(depsgraph, bmain, sce, ob, apply_modifiers, calc_undeformed);
+ return BKE_mesh_new_from_object_to_bmain(bmain, object);
}
static Light *rna_Main_lights_new(Main *bmain, const char *name, int type)
@@ -850,6 +867,11 @@ void RNA_def_main_materials(BlenderRNA *brna, PropertyRNA *cprop)
parm = RNA_def_pointer(func, "material", "Material", "", "Material");
RNA_def_parameter_flags(parm, PROP_NEVER_NULL, PARM_REQUIRED | PARM_RNAPTR);
+ func = RNA_def_function(srna, "remove_gpencil_data", "rna_Main_materials_gpencil_remove");
+ RNA_def_function_ui_description(func, "Remove grease pencil material settings");
+ parm = RNA_def_pointer(func, "material", "Material", "", "Material");
+ RNA_def_parameter_flags(parm, PROP_NEVER_NULL, PARM_REQUIRED | PARM_RNAPTR);
+
func = RNA_def_function(srna, "remove", "rna_Main_ID_remove");
RNA_def_function_flag(func, FUNC_USE_REPORTS);
RNA_def_function_ui_description(func, "Remove a material from the current blendfile");
@@ -937,24 +959,13 @@ void RNA_def_main_meshes(BlenderRNA *brna, PropertyRNA *cprop)
RNA_def_function_return(func, parm);
func = RNA_def_function(srna, "new_from_object", "rna_Main_meshes_new_from_object");
- RNA_def_function_ui_description(func,
- "Add a new mesh created from object with modifiers applied");
+ RNA_def_function_ui_description(
+ func,
+ "Add a new mesh created from given object (undeformed geometry if object is original, and "
+ "final evaluated geometry, with all modifiers etc., if object is evaluated)");
RNA_def_function_flag(func, FUNC_USE_REPORTS);
- parm = RNA_def_pointer(func,
- "depsgraph",
- "Depsgraph",
- "Dependency Graph",
- "Evaluated dependency graph within which to evaluate modifiers");
- RNA_def_parameter_flags(parm, PROP_NEVER_NULL, PARM_REQUIRED);
parm = RNA_def_pointer(func, "object", "Object", "", "Object to create mesh from");
RNA_def_parameter_flags(parm, PROP_NEVER_NULL, PARM_REQUIRED);
- parm = RNA_def_boolean(func, "apply_modifiers", 0, "", "Apply modifiers");
- RNA_def_parameter_flags(parm, 0, PARM_REQUIRED);
- RNA_def_boolean(func,
- "calc_undeformed",
- false,
- "Calculate Undeformed",
- "Calculate undeformed vertex coordinates");
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 8b27c69604e..7334c5baec0 100644
--- a/source/blender/makesrna/intern/rna_mask.c
+++ b/source/blender/makesrna/intern/rna_mask.c
@@ -116,7 +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(PointerRNA *ptr, PointerRNA value)
+static void rna_MaskParent_id_set(PointerRNA *ptr,
+ PointerRNA value,
+ struct ReportList *UNUSED(reports))
{
MaskParent *mpar = (MaskParent *)ptr->data;
@@ -191,7 +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(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;
@@ -226,7 +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(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;
@@ -245,7 +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(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 d66b4e5be44..df48b679235 100644
--- a/source/blender/makesrna/intern/rna_material.c
+++ b/source/blender/makesrna/intern/rna_material.c
@@ -330,7 +330,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(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;
@@ -339,7 +341,9 @@ static void rna_GpencilColorData_stroke_image_set(PointerRNA *ptr, PointerRNA va
pcolor->sima = (struct Image *)id;
}
-static void rna_GpencilColorData_fill_image_set(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;
@@ -440,6 +444,17 @@ static void rna_def_material_greasepencil(BlenderRNA *brna)
{0, NULL, 0, NULL, NULL},
};
+ static EnumPropertyItem alignment_draw_items[] = {
+ {GP_STYLE_FOLLOW_PATH, "PATH", 0, "Path", "Follow stroke drawing path and object rotation"},
+ {GP_STYLE_FOLLOW_OBJ, "OBJECT", 0, "Object", "Follow object rotation only"},
+ {GP_STYLE_FOLLOW_FIXED,
+ "FIXED",
+ 0,
+ "Fixed",
+ "Do not follow drawing path or object rotation and keeps aligned with viewport"},
+ {0, NULL, 0, NULL, NULL},
+ };
+
srna = RNA_def_struct(brna, "MaterialGPencilStyle", NULL);
RNA_def_struct_sdna(srna, "MaterialGPencilStyle");
RNA_def_struct_ui_text(srna, "Grease Pencil Color", "");
@@ -611,10 +626,12 @@ static void rna_def_material_greasepencil(BlenderRNA *brna)
RNA_def_property_ui_text(prop, "Show Fill", "Show stroke fills of this material");
RNA_def_property_update(prop, NC_GPENCIL | ND_SHADING, "rna_MaterialGpencil_update");
- /* keep Dots and Boxes aligned to screen and not to drawing path */
- prop = RNA_def_property(srna, "use_follow_path", PROP_BOOLEAN, PROP_NONE);
- RNA_def_property_boolean_negative_sdna(prop, NULL, "flag", GP_STYLE_COLOR_LOCK_DOTS);
- RNA_def_property_ui_text(prop, "Follow Path", "Keep Dots and Boxes aligned to drawing path");
+ /* Mode to align Dots and Boxes to drawing path and object rotation */
+ prop = RNA_def_property(srna, "alignment_mode", PROP_ENUM, PROP_NONE);
+ RNA_def_property_enum_bitflag_sdna(prop, NULL, "alignment_mode");
+ RNA_def_property_enum_items(prop, alignment_draw_items);
+ RNA_def_property_ui_text(
+ prop, "Alignment", "Defines how align Dots and Boxes with drawing path and object rotation");
RNA_def_property_update(prop, NC_GPENCIL | ND_SHADING, "rna_MaterialGpencil_nopreview_update");
/* pass index for future compositing and editing tools */
@@ -778,6 +795,12 @@ void RNA_def_material(BlenderRNA *brna)
"(avoids transparency sorting problems)");
RNA_def_property_update(prop, 0, "rna_Material_draw_update");
+ prop = RNA_def_property(srna, "use_backface_culling", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(prop, NULL, "blend_flag", MA_BL_CULL_BACKFACE);
+ RNA_def_property_ui_text(
+ prop, "Backface Culling", "Use back face culling to hide the back side of faces");
+ RNA_def_property_update(prop, 0, "rna_Material_draw_update");
+
prop = RNA_def_property(srna, "use_screen_refraction", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "blend_flag", MA_BL_SS_REFRACTION);
RNA_def_property_ui_text(
diff --git a/source/blender/makesrna/intern/rna_mesh.c b/source/blender/makesrna/intern/rna_mesh.c
index 0b4056121b3..4082222340a 100644
--- a/source/blender/makesrna/intern/rna_mesh.c
+++ b/source/blender/makesrna/intern/rna_mesh.c
@@ -3015,12 +3015,6 @@ static void rna_def_mesh(BlenderRNA *brna)
RNA_def_property_boolean_funcs(prop, "rna_Mesh_has_custom_normals_get", NULL);
RNA_define_verify_sdna(true);
- prop = RNA_def_property(srna, "show_double_sided", PROP_BOOLEAN, PROP_NONE);
- RNA_def_property_boolean_sdna(prop, NULL, "flag", ME_TWOSIDED);
- RNA_def_property_ui_text(
- prop, "Double Sided", "Display the mesh with double or single sided lighting (OpenGL only)");
- RNA_def_property_update(prop, 0, "rna_Mesh_update_data");
-
prop = RNA_def_property(srna, "texco_mesh", PROP_POINTER, PROP_NONE);
RNA_def_property_pointer_sdna(prop, NULL, "texcomesh");
RNA_def_property_flag(prop, PROP_EDITABLE);
diff --git a/source/blender/makesrna/intern/rna_mesh_utils.h b/source/blender/makesrna/intern/rna_mesh_utils.h
index ff148408728..9c5b4f9d5b3 100644
--- a/source/blender/makesrna/intern/rna_mesh_utils.h
+++ b/source/blender/makesrna/intern/rna_mesh_utils.h
@@ -83,7 +83,8 @@
return rna_pointer_inherit_refine(ptr, &RNA_##layer_rna_type, layer); \
} \
\
- static void rna_Mesh_##collection_name##_##active_type##_set(PointerRNA *ptr, PointerRNA value) \
+ static void rna_Mesh_##collection_name##_##active_type##_set( \
+ 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 4f304f97cac..2a09abe5f8d 100644
--- a/source/blender/makesrna/intern/rna_modifier.c
+++ b/source/blender/makesrna/intern/rna_modifier.c
@@ -445,6 +445,8 @@ const EnumPropertyItem rna_enum_axis_flag_xyz_items[] = {
# include "BKE_object.h"
# include "BKE_particle.h"
+# include "BLI_sort_utils.h"
+
# include "DEG_depsgraph.h"
# include "DEG_depsgraph_build.h"
# include "DEG_depsgraph_query.h"
@@ -717,7 +719,8 @@ 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(PointerRNA *ptr, PointerRNA value) \
+ static void rna_##_type##Modifier_##_prop##_set( \
+ 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); \
@@ -739,14 +742,83 @@ 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(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;
Object *ob = (Object *)value.data;
hmd->object = ob;
id_lib_extern((ID *)ob);
- BKE_object_modifier_hook_reset(ob, hmd);
+ BKE_object_modifier_hook_reset(owner, hmd);
+}
+
+static void rna_HookModifier_subtarget_set(PointerRNA *ptr, const char *value)
+{
+ Object *owner = (Object *)ptr->id.data;
+ HookModifierData *hmd = ptr->data;
+
+ BLI_strncpy(hmd->subtarget, value, sizeof(hmd->subtarget));
+ BKE_object_modifier_hook_reset(owner, hmd);
+}
+
+static int rna_HookModifier_vertex_indices_get_length(PointerRNA *ptr,
+ int length[RNA_MAX_ARRAY_DIMENSION])
+{
+ HookModifierData *hmd = ptr->data;
+ int totindex = hmd->indexar ? hmd->totindex : 0;
+ return (length[0] = totindex);
+}
+
+static void rna_HookModifier_vertex_indices_get(PointerRNA *ptr, int *values)
+{
+ HookModifierData *hmd = ptr->data;
+ if (hmd->indexar != NULL) {
+ memcpy(values, hmd->indexar, sizeof(int) * hmd->totindex);
+ }
+}
+
+static void rna_HookModifier_vertex_indices_set(HookModifierData *hmd,
+ ReportList *reports,
+ int indices_len,
+ int *indices)
+{
+ if (indices_len == 0) {
+ MEM_SAFE_FREE(hmd->indexar);
+ hmd->totindex = 0;
+ }
+ else {
+ /* Reject negative indices. */
+ for (int i = 0; i < indices_len; i++) {
+ if (indices[i] < 0) {
+ BKE_reportf(reports, RPT_ERROR, "Negative vertex index in vertex_indices_set");
+ return;
+ }
+ }
+
+ /* Copy and sort the index array. */
+ size_t size = sizeof(int) * indices_len;
+ int *buffer = MEM_mallocN(size, "hook indexar");
+ memcpy(buffer, indices, size);
+
+ qsort(buffer, indices_len, sizeof(int), BLI_sortutil_cmp_int);
+
+ /* Reject duplicate indices. */
+ for (int i = 1; i < indices_len; i++) {
+ if (buffer[i] == buffer[i - 1]) {
+ BKE_reportf(reports, RPT_ERROR, "Duplicate index %d in vertex_indices_set", buffer[i]);
+ MEM_freeN(buffer);
+ return;
+ }
+ }
+
+ /* Success - save the new array. */
+ MEM_SAFE_FREE(hmd->indexar);
+ hmd->indexar = buffer;
+ hmd->totindex = indices_len;
+ }
}
static PointerRNA rna_UVProjector_object_get(PointerRNA *ptr)
@@ -755,7 +827,9 @@ static PointerRNA rna_UVProjector_object_get(PointerRNA *ptr)
return rna_pointer_inherit_refine(ptr, &RNA_Object, *ob);
}
-static void rna_UVProjector_object_set(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;
@@ -1328,7 +1402,8 @@ static PointerRNA rna_ParticleInstanceModifier_particle_system_get(PointerRNA *p
}
static void rna_ParticleInstanceModifier_particle_system_set(PointerRNA *ptr,
- const PointerRNA value)
+ const PointerRNA value,
+ struct ReportList *UNUSED(reports))
{
ParticleInstanceModifierData *psmd = ptr->data;
@@ -2149,6 +2224,8 @@ static void rna_def_modifier_hook(BlenderRNA *brna)
{
StructRNA *srna;
PropertyRNA *prop;
+ FunctionRNA *func;
+ PropertyRNA *parm;
srna = RNA_def_struct(brna, "HookModifier", "Modifier");
RNA_def_struct_ui_text(
@@ -2181,9 +2258,10 @@ static void rna_def_modifier_hook(BlenderRNA *brna)
RNA_def_property_ui_text(prop, "Falloff Curve", "Custom falloff curve");
RNA_def_property_update(prop, 0, "rna_Modifier_update");
- prop = RNA_def_property(srna, "center", PROP_FLOAT, PROP_NONE);
+ prop = RNA_def_property(srna, "center", PROP_FLOAT, PROP_TRANSLATION);
RNA_def_property_float_sdna(prop, NULL, "cent");
- RNA_def_property_ui_text(prop, "Hook Center", "");
+ RNA_def_property_ui_text(
+ prop, "Hook Center", "Center of the hook, used for falloff and display");
RNA_def_property_update(prop, 0, "rna_Modifier_update");
prop = RNA_def_property(srna, "matrix_inverse", PROP_FLOAT, PROP_MATRIX);
@@ -2206,6 +2284,7 @@ static void rna_def_modifier_hook(BlenderRNA *brna)
prop,
"Sub-Target",
"Name of Parent Bone for hook (if applicable), also recalculates and clears offset");
+ RNA_def_property_string_funcs(prop, NULL, NULL, "rna_HookModifier_subtarget_set");
RNA_def_property_update(prop, 0, "rna_Modifier_dependency_update");
prop = RNA_def_property(srna, "use_falloff_uniform", PROP_BOOLEAN, PROP_NONE);
@@ -2221,6 +2300,26 @@ static void rna_def_modifier_hook(BlenderRNA *brna)
"Name of Vertex Group which determines influence of modifier per point");
RNA_def_property_string_funcs(prop, NULL, NULL, "rna_HookModifier_name_set");
RNA_def_property_update(prop, 0, "rna_Modifier_update");
+
+ prop = RNA_def_property(srna, "vertex_indices", PROP_INT, PROP_UNSIGNED);
+ RNA_def_property_array(prop, RNA_MAX_ARRAY_LENGTH);
+ RNA_def_property_flag(prop, PROP_DYNAMIC);
+ RNA_def_property_clear_flag(prop, PROP_EDITABLE);
+ RNA_def_property_dynamic_array_funcs(prop, "rna_HookModifier_vertex_indices_get_length");
+ RNA_def_property_int_funcs(prop, "rna_HookModifier_vertex_indices_get", NULL, NULL);
+ RNA_def_property_ui_text(prop,
+ "Vertex Indices",
+ "Indices of vertices bound to the modifier. For bezier curves, "
+ "handles count as additional vertices");
+
+ func = RNA_def_function(srna, "vertex_indices_set", "rna_HookModifier_vertex_indices_set");
+ RNA_def_function_ui_description(
+ func, "Validates and assigns the array of vertex indices bound to the modifier");
+ RNA_def_function_flag(func, FUNC_USE_REPORTS);
+ parm = RNA_def_int_array(
+ func, "indices", 1, NULL, INT_MIN, INT_MAX, "", "Vertex Indices", 0, INT_MAX);
+ RNA_def_property_array(parm, RNA_MAX_ARRAY_LENGTH);
+ RNA_def_parameter_flags(parm, PROP_DYNAMIC, PARM_REQUIRED);
}
static void rna_def_modifier_softbody(BlenderRNA *brna)
@@ -3100,6 +3199,7 @@ static void rna_def_modifier_particleinstance(BlenderRNA *brna)
prop = RNA_def_property(srna, "use_children", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "flag", eParticleInstanceFlag_Children);
RNA_def_property_ui_text(prop, "Children", "Create instances from child particles");
+ RNA_def_property_translation_context(prop, BLT_I18NCONTEXT_ID_PARTICLESETTINGS);
RNA_def_property_update(prop, 0, "rna_Modifier_update");
prop = RNA_def_property(srna, "use_path", PROP_BOOLEAN, PROP_NONE);
diff --git a/source/blender/makesrna/intern/rna_nodetree.c b/source/blender/makesrna/intern/rna_nodetree.c
index e4270f3854e..d634a34bc5b 100644
--- a/source/blender/makesrna/intern/rna_nodetree.c
+++ b/source/blender/makesrna/intern/rna_nodetree.c
@@ -814,7 +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(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;
@@ -1608,7 +1610,9 @@ static IDProperty *rna_Node_idprops(PointerRNA *ptr, bool create)
return node->prop;
}
-static void rna_Node_parent_set(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;
@@ -2683,7 +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(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;
@@ -2791,7 +2797,9 @@ static void rna_Matte_t2_set(PointerRNA *ptr, float value)
chroma->t2 = value;
}
-static void rna_Node_scene_set(PointerRNA *ptr, PointerRNA value)
+static void rna_Node_scene_set(PointerRNA *ptr,
+ PointerRNA value,
+ struct ReportList *UNUSED(reports))
{
bNode *node = (bNode *)ptr->data;
@@ -3345,7 +3353,9 @@ static PointerRNA rna_ShaderNodePointDensity_psys_get(PointerRNA *ptr)
return value;
}
-static void rna_ShaderNodePointDensity_psys_set(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;
@@ -3987,21 +3997,6 @@ static void def_sh_tex_sky(StructRNA *srna)
RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_update");
}
-static const EnumPropertyItem sh_tex_prop_color_space_items[] = {
- {SHD_COLORSPACE_COLOR,
- "COLOR",
- 0,
- "Color",
- "Image contains color data, and will be converted to linear color for rendering"},
- {SHD_COLORSPACE_NONE,
- "NONE",
- 0,
- "Non-Color Data",
- "Image contains non-color data, for example a displacement or normal map, "
- "and will not be converted"},
- {0, NULL, 0, NULL, NULL},
-};
-
static const EnumPropertyItem sh_tex_prop_interpolation_items[] = {
{SHD_INTERP_LINEAR, "Linear", 0, "Linear", "Linear interpolation"},
{SHD_INTERP_CLOSEST, "Closest", 0, "Closest", "No interpolation (sample closest texel)"},
@@ -4038,12 +4033,6 @@ static void def_sh_tex_environment(StructRNA *srna)
RNA_def_struct_sdna_from(srna, "NodeTexEnvironment", "storage");
def_sh_tex(srna);
- prop = RNA_def_property(srna, "color_space", PROP_ENUM, PROP_NONE);
- RNA_def_property_enum_items(prop, sh_tex_prop_color_space_items);
- RNA_def_property_enum_default(prop, SHD_COLORSPACE_COLOR);
- RNA_def_property_ui_text(prop, "Color Space", "Image file color space");
- RNA_def_property_update(prop, 0, "rna_Node_update");
-
prop = RNA_def_property(srna, "projection", PROP_ENUM, PROP_NONE);
RNA_def_property_enum_items(prop, prop_projection_items);
RNA_def_property_ui_text(prop, "Projection", "Projection of the input image");
@@ -4122,12 +4111,6 @@ static void def_sh_tex_image(StructRNA *srna)
RNA_def_struct_sdna_from(srna, "NodeTexImage", "storage");
def_sh_tex(srna);
- prop = RNA_def_property(srna, "color_space", PROP_ENUM, PROP_NONE);
- RNA_def_property_enum_items(prop, sh_tex_prop_color_space_items);
- RNA_def_property_enum_default(prop, SHD_COLORSPACE_COLOR);
- RNA_def_property_ui_text(prop, "Color Space", "Image file color space");
- RNA_def_property_update(prop, 0, "rna_Node_update");
-
prop = RNA_def_property(srna, "projection", PROP_ENUM, PROP_NONE);
RNA_def_property_enum_items(prop, prop_projection_items);
RNA_def_property_ui_text(
diff --git a/source/blender/makesrna/intern/rna_object.c b/source/blender/makesrna/intern/rna_object.c
index 219445f629f..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(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;
@@ -441,8 +441,13 @@ static void rna_Object_data_set(PointerRNA *ptr, PointerRNA value)
return;
}
- BLI_assert(BKE_id_is_in_global_main(&ob->id));
- BLI_assert(BKE_id_is_in_global_main(id));
+ if ((id->tag & LIB_TAG_NO_MAIN) != (ob->id.tag & LIB_TAG_NO_MAIN)) {
+ BKE_report(reports,
+ RPT_ERROR,
+ "Can only assign evaluated data to to evaluated object, or original data to "
+ "original object");
+ return;
+ }
if (ob->type == OB_EMPTY) {
if (ob->data) {
@@ -529,7 +534,9 @@ static bool rna_Object_data_poll(PointerRNA *ptr, const PointerRNA value)
return true;
}
-static void rna_Object_parent_set(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;
@@ -614,7 +621,9 @@ static const EnumPropertyItem *rna_Object_instance_type_itemf(bContext *UNUSED(C
return item;
}
-static void rna_Object_dup_collection_set(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;
@@ -890,7 +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(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;
@@ -1089,7 +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(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;
@@ -1277,7 +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(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);
@@ -2801,9 +2816,9 @@ static void rna_def_object(BlenderRNA *brna)
/* restrict */
prop = RNA_def_property(srna, "hide_viewport", PROP_BOOLEAN, PROP_NONE);
- RNA_def_property_boolean_sdna(prop, NULL, "restrictflag", OB_RESTRICT_VIEW);
+ RNA_def_property_boolean_sdna(prop, NULL, "restrictflag", OB_RESTRICT_VIEWPORT);
RNA_def_property_override_flag(prop, PROPOVERRIDE_OVERRIDABLE_STATIC);
- RNA_def_property_ui_text(prop, "Disable View", "Disable object in the viewport");
+ RNA_def_property_ui_text(prop, "Disable in Viewports", "Globally disable in viewports");
RNA_def_property_ui_icon(prop, ICON_RESTRICT_VIEW_OFF, -1);
RNA_def_property_update(prop, NC_OBJECT | ND_DRAW, "rna_Object_hide_update");
@@ -2811,14 +2826,14 @@ static void rna_def_object(BlenderRNA *brna)
RNA_def_property_boolean_sdna(prop, NULL, "restrictflag", OB_RESTRICT_SELECT);
RNA_def_property_clear_flag(prop, PROP_ANIMATABLE);
RNA_def_property_override_flag(prop, PROPOVERRIDE_OVERRIDABLE_STATIC);
- RNA_def_property_ui_text(prop, "Disable Select", "Disable object selection in the viewport");
+ RNA_def_property_ui_text(prop, "Disable Selection", "Disable selection in viewport");
RNA_def_property_ui_icon(prop, ICON_RESTRICT_SELECT_OFF, -1);
RNA_def_property_update(prop, NC_OBJECT | ND_DRAW, "rna_Object_hide_update");
prop = RNA_def_property(srna, "hide_render", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "restrictflag", OB_RESTRICT_RENDER);
RNA_def_property_override_flag(prop, PROPOVERRIDE_OVERRIDABLE_STATIC);
- RNA_def_property_ui_text(prop, "Disable Render", "Disable object in renders");
+ RNA_def_property_ui_text(prop, "Disable in Renders", "Globally disable in renders");
RNA_def_property_ui_icon(prop, ICON_RESTRICT_RENDER_OFF, -1);
RNA_def_property_update(prop, NC_OBJECT | ND_DRAW, "rna_Object_hide_update");
diff --git a/source/blender/makesrna/intern/rna_object_api.c b/source/blender/makesrna/intern/rna_object_api.c
index 21300f22b95..7362f6ba610 100644
--- a/source/blender/makesrna/intern/rna_object_api.c
+++ b/source/blender/makesrna/intern/rna_object_api.c
@@ -375,18 +375,28 @@ static void rna_Object_camera_fit_coords(
}
/* copied from Mesh_getFromObject and adapted to RNA interface */
-/* settings: 0 - preview, 1 - render */
-static Mesh *rna_Object_to_mesh(Object *ob,
- bContext *C,
- ReportList *reports,
- Depsgraph *depsgraph,
- bool apply_modifiers,
- bool calc_undeformed)
+static Mesh *rna_Object_to_mesh(Object *object, ReportList *reports)
{
- Main *bmain = CTX_data_main(C);
+ /* TODO(sergey): Make it more re-usable function, de-duplicate with
+ * rna_Main_meshes_new_from_object. */
+ switch (object->type) {
+ case OB_FONT:
+ case OB_CURVE:
+ case OB_SURF:
+ case OB_MBALL:
+ case OB_MESH:
+ break;
+ default:
+ BKE_report(reports, RPT_ERROR, "Object does not have geometry data");
+ return NULL;
+ }
- return rna_Main_meshes_new_from_object(
- bmain, reports, depsgraph, ob, apply_modifiers, calc_undeformed);
+ return BKE_object_to_mesh(object);
+}
+
+static void rna_Object_to_mesh_clear(Object *object)
+{
+ BKE_object_to_mesh_clear(object);
}
static PointerRNA rna_Object_shape_key_add(
@@ -398,7 +408,7 @@ static PointerRNA rna_Object_shape_key_add(
if ((kb = BKE_object_shapekey_insert(bmain, ob, name, from_mix))) {
PointerRNA keyptr;
- RNA_pointer_create((ID *)ob->data, &RNA_ShapeKey, kb, &keyptr);
+ RNA_pointer_create((ID *)BKE_key_from_object(ob), &RNA_ShapeKey, kb, &keyptr);
WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, ob);
return keyptr;
@@ -433,6 +443,14 @@ static void rna_Object_shape_key_remove(Object *ob,
RNA_POINTER_INVALIDATE(kb_ptr);
}
+static void rna_Object_shape_key_clear(Object *ob, Main *bmain)
+{
+ BKE_object_shapekey_free(bmain, ob);
+
+ DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY);
+ WM_main_add_notifier(NC_OBJECT | ND_DRAW, ob);
+}
+
# if 0
static void rna_Mesh_assign_verts_to_group(
Object *ob, bDeformGroup *group, int *indices, int totindex, float weight, int assignmode)
@@ -874,28 +892,18 @@ void RNA_api_object(StructRNA *srna)
/* mesh */
func = RNA_def_function(srna, "to_mesh", "rna_Object_to_mesh");
- RNA_def_function_ui_description(func, "Create a Mesh data-block with modifiers applied");
- RNA_def_function_flag(func, FUNC_USE_REPORTS | FUNC_USE_CONTEXT);
- parm = RNA_def_pointer(func,
- "depsgraph",
- "Depsgraph",
- "Dependency Graph",
- "Evaluated dependency graph within which to evaluate modifiers");
- RNA_def_parameter_flags(parm, PROP_NEVER_NULL, PARM_REQUIRED);
- parm = RNA_def_boolean(func, "apply_modifiers", 0, "", "Apply modifiers");
- RNA_def_parameter_flags(parm, 0, PARM_REQUIRED);
- RNA_def_boolean(func,
- "calc_undeformed",
- false,
- "Calculate Undeformed",
- "Calculate undeformed vertex coordinates");
- parm = RNA_def_pointer(func,
- "mesh",
- "Mesh",
- "",
- "Mesh created from object, remove it if it is only used for export");
+ RNA_def_function_ui_description(
+ func,
+ "Create a Mesh data-block from the current state of the object. The object owns the "
+ "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);
+ parm = RNA_def_pointer(func, "mesh", "Mesh", "", "Mesh created from object");
RNA_def_function_return(func, parm);
+ func = RNA_def_function(srna, "to_mesh_clear", "rna_Object_to_mesh_clear");
+ RNA_def_function_ui_description(func, "Clears mesh data-block created by to_mesh()");
+
/* Armature */
func = RNA_def_function(srna, "find_armature", "modifiers_isDeformedByArmature");
RNA_def_function_ui_description(
@@ -921,6 +929,10 @@ void RNA_api_object(StructRNA *srna)
RNA_def_parameter_flags(parm, PROP_NEVER_NULL, PARM_REQUIRED | PARM_RNAPTR);
RNA_def_parameter_clear_flags(parm, PROP_THICK_WRAP, 0);
+ func = RNA_def_function(srna, "shape_key_clear", "rna_Object_shape_key_clear");
+ RNA_def_function_ui_description(func, "Remove all Shape Keys from this object");
+ RNA_def_function_flag(func, FUNC_USE_MAIN);
+
/* Ray Cast */
func = RNA_def_function(srna, "ray_cast", "rna_Object_ray_cast");
RNA_def_function_ui_description(
diff --git a/source/blender/makesrna/intern/rna_object_force.c b/source/blender/makesrna/intern/rna_object_force.c
index c4f0eb35627..2abb1f3227a 100644
--- a/source/blender/makesrna/intern/rna_object_force.c
+++ b/source/blender/makesrna/intern/rna_object_force.c
@@ -754,7 +754,7 @@ static void rna_def_pointcache_common(StructRNA *srna)
static const EnumPropertyItem point_cache_compress_items[] = {
{PTCACHE_COMPRESS_NO, "NO", 0, "None", "No compression"},
- {PTCACHE_COMPRESS_LZO, "LIGHT", 0, "Light", "Fast but not so effective compression"},
+ {PTCACHE_COMPRESS_LZO, "LIGHT", 0, "Lite", "Fast but not so effective compression"},
{PTCACHE_COMPRESS_LZMA, "HEAVY", 0, "Heavy", "Effective but slow compression"},
{0, NULL, 0, NULL, NULL},
};
diff --git a/source/blender/makesrna/intern/rna_palette.c b/source/blender/makesrna/intern/rna_palette.c
index 7b35092dea4..9af6387389c 100644
--- a/source/blender/makesrna/intern/rna_palette.c
+++ b/source/blender/makesrna/intern/rna_palette.c
@@ -74,7 +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(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 8c3d16f9c8c..641bf4128d0 100644
--- a/source/blender/makesrna/intern/rna_particle.c
+++ b/source/blender/makesrna/intern/rna_particle.c
@@ -792,7 +792,9 @@ static PointerRNA rna_particle_settings_get(PointerRNA *ptr)
return rna_pointer_inherit_refine(ptr, &RNA_ParticleSettings, part);
}
-static void rna_particle_settings_set(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;
@@ -1318,7 +1320,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(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 1b4a7efbdd8..3ab41f72322 100644
--- a/source/blender/makesrna/intern/rna_pose.c
+++ b/source/blender/makesrna/intern/rna_pose.c
@@ -122,6 +122,11 @@ static void rna_Pose_IK_update(Main *UNUSED(bmain), Scene *UNUSED(scene), Pointe
BIK_clear_data(ob->pose);
}
+static char *rna_Pose_path(PointerRNA *UNUSED(ptr))
+{
+ return BLI_strdup("pose");
+}
+
static char *rna_PoseBone_path(PointerRNA *ptr)
{
bPoseChannel *pchan = ptr->data;
@@ -284,6 +289,18 @@ static void rna_PoseChannel_name_set(PointerRNA *ptr, const char *value)
ED_armature_bone_rename(G_MAIN, ob->data, oldname, newname);
}
+static PointerRNA rna_PoseChannel_bone_get(PointerRNA *ptr)
+{
+ Object *ob = (Object *)ptr->id.data;
+ bPoseChannel *pchan = (bPoseChannel *)ptr->data;
+ PointerRNA tmp_ptr = *ptr;
+
+ /* Replace the id_data pointer with the Armature ID. */
+ tmp_ptr.id.data = ob->data;
+
+ return rna_pointer_inherit_refine(&tmp_ptr, &RNA_Bone, pchan->bone);
+}
+
static bool rna_PoseChannel_has_ik_get(PointerRNA *ptr)
{
Object *ob = (Object *)ptr->id.data;
@@ -356,7 +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(PointerRNA *ptr, PointerRNA value)
+static void rna_PoseChannel_bone_custom_set(PointerRNA *ptr,
+ PointerRNA value,
+ struct ReportList *UNUSED(reports))
{
bPoseChannel *pchan = (bPoseChannel *)ptr->data;
@@ -385,7 +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(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;
@@ -426,7 +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(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;
@@ -515,7 +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(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);
@@ -753,7 +778,9 @@ static bPoseChannel *rna_PoseChannel_ensure_own_pchan(Object *ob,
return ref_pchan;
}
-static void rna_PoseChannel_custom_shape_transform_set(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;
@@ -911,6 +938,7 @@ static void rna_def_pose_channel(BlenderRNA *brna)
prop = RNA_def_property(srna, "bone", PROP_POINTER, PROP_NONE);
RNA_def_property_flag(prop, PROP_NEVER_NULL);
RNA_def_property_struct_type(prop, "Bone");
+ RNA_def_property_pointer_funcs(prop, "rna_PoseChannel_bone_get", NULL, NULL, NULL);
RNA_def_property_flag(prop, PROP_PTR_NO_OWNERSHIP);
RNA_def_property_clear_flag(prop, PROP_EDITABLE);
RNA_def_property_ui_text(prop, "Bone", "Bone associated with this PoseBone");
@@ -1551,6 +1579,31 @@ static void rna_def_pose(BlenderRNA *brna)
RNA_def_property_clear_flag(prop, PROP_EDITABLE);
RNA_def_property_ui_text(prop, "IK Param", "Parameters for IK solver");
+ /* pose edit options */
+ prop = RNA_def_property(srna, "use_mirror_x", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(prop, NULL, "flag", POSE_MIRROR_EDIT);
+ RNA_def_property_ui_text(
+ prop, "X-Axis Mirror", "Apply changes to matching bone on opposite side of X-Axis");
+ RNA_def_struct_path_func(srna, "rna_Pose_path");
+ RNA_def_property_update(prop, 0, "rna_Pose_update");
+ RNA_def_property_flag(prop, PROP_LIB_EXCEPTION);
+
+ prop = RNA_def_property(srna, "use_mirror_relative", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(prop, NULL, "flag", POSE_MIRROR_RELATIVE);
+ RNA_def_property_ui_text(
+ prop, "Relative Mirror", "Apply relative transformations in X-mirror mode");
+ RNA_def_struct_path_func(srna, "rna_Pose_path");
+ RNA_def_property_update(prop, 0, "rna_Pose_update");
+ RNA_def_property_flag(prop, PROP_LIB_EXCEPTION);
+
+ prop = RNA_def_property(srna, "use_auto_ik", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(prop, NULL, "flag", POSE_AUTO_IK);
+ RNA_def_property_ui_text(
+ prop, "Auto IK", "Add temporary IK constraints while grabbing bones in Pose Mode");
+ RNA_def_struct_path_func(srna, "rna_Pose_path");
+ RNA_def_property_update(prop, 0, "rna_Pose_update");
+ RNA_def_property_flag(prop, PROP_LIB_EXCEPTION);
+
/* animviz */
rna_def_animviz_common(srna);
diff --git a/source/blender/makesrna/intern/rna_render.c b/source/blender/makesrna/intern/rna_render.c
index 81ec7857487..2dc873ca17d 100644
--- a/source/blender/makesrna/intern/rna_render.c
+++ b/source/blender/makesrna/intern/rna_render.c
@@ -206,7 +206,9 @@ static void engine_bake(RenderEngine *engine,
RNA_parameter_list_free(&list);
}
-static void engine_view_update(RenderEngine *engine, const struct bContext *context)
+static void engine_view_update(RenderEngine *engine,
+ const struct bContext *context,
+ Depsgraph *depsgraph)
{
extern FunctionRNA rna_RenderEngine_view_update_func;
PointerRNA ptr;
@@ -218,12 +220,15 @@ static void engine_view_update(RenderEngine *engine, const struct bContext *cont
RNA_parameter_list_create(&list, &ptr, func);
RNA_parameter_set_lookup(&list, "context", &context);
+ RNA_parameter_set_lookup(&list, "depsgraph", &depsgraph);
engine->type->ext.call(NULL, &ptr, func, &list);
RNA_parameter_list_free(&list);
}
-static void engine_view_draw(RenderEngine *engine, const struct bContext *context)
+static void engine_view_draw(RenderEngine *engine,
+ const struct bContext *context,
+ Depsgraph *depsgraph)
{
extern FunctionRNA rna_RenderEngine_view_draw_func;
PointerRNA ptr;
@@ -235,6 +240,7 @@ static void engine_view_draw(RenderEngine *engine, const struct bContext *contex
RNA_parameter_list_create(&list, &ptr, func);
RNA_parameter_set_lookup(&list, "context", &context);
+ RNA_parameter_set_lookup(&list, "depsgraph", &depsgraph);
engine->type->ext.call(NULL, &ptr, func, &list);
RNA_parameter_list_free(&list);
@@ -554,12 +560,18 @@ static void rna_def_render_engine(BlenderRNA *brna)
func = RNA_def_function(srna, "view_update", NULL);
RNA_def_function_ui_description(func, "Update on data changes for viewport render");
RNA_def_function_flag(func, FUNC_REGISTER_OPTIONAL | FUNC_ALLOW_WRITE);
- RNA_def_pointer(func, "context", "Context", "", "");
+ parm = RNA_def_pointer(func, "context", "Context", "", "");
+ RNA_def_parameter_flags(parm, 0, PARM_REQUIRED);
+ parm = RNA_def_pointer(func, "depsgraph", "Depsgraph", "", "");
+ RNA_def_parameter_flags(parm, 0, PARM_REQUIRED);
func = RNA_def_function(srna, "view_draw", NULL);
RNA_def_function_ui_description(func, "Draw viewport render");
RNA_def_function_flag(func, FUNC_REGISTER_OPTIONAL);
- RNA_def_pointer(func, "context", "Context", "", "");
+ parm = RNA_def_pointer(func, "context", "Context", "", "");
+ RNA_def_parameter_flags(parm, 0, PARM_REQUIRED);
+ parm = RNA_def_pointer(func, "depsgraph", "Depsgraph", "", "");
+ RNA_def_parameter_flags(parm, 0, PARM_REQUIRED);
/* shader script callbacks */
func = RNA_def_function(srna, "update_script_node", NULL);
diff --git a/source/blender/makesrna/intern/rna_rna.c b/source/blender/makesrna/intern/rna_rna.c
index 032a1f86fc0..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(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 6f6699fa81b..894f9bfbe3e 100644
--- a/source/blender/makesrna/intern/rna_scene.c
+++ b/source/blender/makesrna/intern/rna_scene.c
@@ -192,6 +192,45 @@ static const EnumPropertyItem snap_uv_element_items[] = {
{SCE_SNAP_MODE_VERTEX, "VERTEX", ICON_SNAP_VERTEX, "Vertex", "Snap to vertices"},
{0, NULL, 0, NULL, NULL},
};
+
+static const EnumPropertyItem rna_enum_scene_display_aa_methods[] = {
+ {SCE_DISPLAY_AA_OFF,
+ "OFF",
+ 0,
+ "No Anti-Aliasing",
+ "Scene will be rendering without any anti-aliasing"},
+ {SCE_DISPLAY_AA_FXAA,
+ "FXAA",
+ 0,
+ "Single Pass Anti-Aliasing",
+ "Scene will be rendered using a single pass anti-aliasing method (FXAA)"},
+ {SCE_DISPLAY_AA_SAMPLES_5,
+ "5",
+ 0,
+ "5 Samples",
+ "Scene will be rendered using 5 anti-aliasing samples"},
+ {SCE_DISPLAY_AA_SAMPLES_8,
+ "8",
+ 0,
+ "8 Samples",
+ "Scene will be rendered using 8 anti-aliasing samples"},
+ {SCE_DISPLAY_AA_SAMPLES_11,
+ "11",
+ 0,
+ "11 Samples",
+ "Scene will be rendered using 11 anti-aliasing samples"},
+ {SCE_DISPLAY_AA_SAMPLES_16,
+ "16",
+ 0,
+ "16 Samples",
+ "Scene will be rendered using 16 anti-aliasing samples"},
+ {SCE_DISPLAY_AA_SAMPLES_32,
+ "32",
+ 0,
+ "32 Samples",
+ "Scene will be rendered using 32 anti-aliasing samples"},
+ {0, NULL, 0, NULL, NULL},
+};
#endif
const EnumPropertyItem rna_enum_curve_fit_method_items[] = {
@@ -733,7 +772,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(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;
@@ -930,7 +971,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(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;
@@ -1396,7 +1439,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(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;
@@ -1810,6 +1855,20 @@ static void rna_View3DCursor_rotation_axis_angle_set(PointerRNA *ptr, const floa
copy_v3_v3(cursor->rotation_axis, &value[1]);
}
+static void rna_View3DCursor_matrix_get(PointerRNA *ptr, float *values)
+{
+ const View3DCursor *cursor = ptr->data;
+ BKE_scene_cursor_to_mat4(cursor, (float(*)[4])values);
+}
+
+static void rna_View3DCursor_matrix_set(PointerRNA *ptr, const float *values)
+{
+ View3DCursor *cursor = ptr->data;
+ float unit_mat[4][4];
+ normalize_m4_m4(unit_mat, (const float(*)[4])values);
+ BKE_scene_cursor_from_mat4(cursor, unit_mat, false);
+}
+
static char *rna_View3DCursor_path(PointerRNA *UNUSED(ptr))
{
return BLI_strdup("cursor");
@@ -1987,7 +2046,9 @@ PointerRNA rna_FreestyleLineSet_linestyle_get(PointerRNA *ptr)
return rna_pointer_inherit_refine(ptr, &RNA_FreestyleLineStyle, lineset->linestyle);
}
-void rna_FreestyleLineSet_linestyle_set(PointerRNA *ptr, PointerRNA value)
+void rna_FreestyleLineSet_linestyle_set(PointerRNA *ptr,
+ PointerRNA value,
+ struct ReportList *UNUSED(reports))
{
FreestyleLineSet *lineset = (FreestyleLineSet *)ptr->data;
@@ -2094,45 +2155,6 @@ void rna_FreestyleSettings_module_remove(ID *id,
WM_main_add_notifier(NC_SCENE | ND_RENDER_OPTIONS, NULL);
}
-char *rna_GPUDOF_path(PointerRNA *ptr)
-{
- /* if there is ID-data, resolve the path using the index instead of by name,
- * since the name used is the name of the texture assigned, but the texture
- * may be used multiple times in the same stack
- */
- if (ptr->id.data) {
- if (GS(((ID *)ptr->id.data)->name) == ID_CA) {
- return BLI_strdup("gpu_dof");
- }
- }
-
- return BLI_strdup("");
-}
-
-static void rna_GPUDOFSettings_blades_set(PointerRNA *ptr, const int value)
-{
- GPUDOFSettings *dofsettings = (GPUDOFSettings *)ptr->data;
-
- if (value == 1 || value == 2) {
- if (dofsettings->num_blades == 0) {
- dofsettings->num_blades = 3;
- }
- else {
- dofsettings->num_blades = 0;
- }
- }
- else {
- dofsettings->num_blades = value;
- }
-}
-
-static void rna_GPUDOFSettings_update(Main *bmain, Scene *scene, PointerRNA *UNUSED(ptr))
-{
- /* TODO(sergey): Can be more selective here. */
- BKE_sequencer_cache_cleanup_all(bmain);
- WM_main_add_notifier(NC_SCENE | ND_SEQUENCER, scene);
-}
-
static void rna_Stereo3dFormat_update(Main *bmain, Scene *UNUSED(scene), PointerRNA *ptr)
{
ID *id = ptr->id.data;
@@ -2547,6 +2569,14 @@ static void rna_def_view3d_cursor(BlenderRNA *brna)
RNA_def_property_enum_funcs(prop, NULL, "rna_View3DCursor_rotation_mode_set", NULL);
RNA_def_property_ui_text(prop, "Rotation Mode", "");
RNA_def_property_update(prop, NC_WINDOW, NULL);
+
+ /* Matrix access to avoid having to check current rotation mode. */
+ prop = RNA_def_property(srna, "matrix", PROP_FLOAT, PROP_MATRIX);
+ RNA_def_property_multi_array(prop, 2, rna_matrix_dimsize_4x4);
+ RNA_def_property_flag(prop, PROP_THICK_WRAP); /* no reference to original data */
+ RNA_def_property_ui_text(prop, "Transform Matrix", "Matrix combining loc/rot of the cursor");
+ RNA_def_property_float_funcs(
+ prop, "rna_View3DCursor_matrix_get", "rna_View3DCursor_matrix_set", NULL);
}
static void rna_def_tool_settings(BlenderRNA *brna)
@@ -2564,23 +2594,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,
@@ -2766,7 +2779,7 @@ static void rna_def_tool_settings(BlenderRNA *brna)
RNA_def_property_boolean_sdna(prop, NULL, "proportional_objects", 0);
RNA_def_property_ui_text(
prop, "Proportional Editing Objects", "Proportional editing object mode");
- RNA_def_property_ui_icon(prop, ICON_PROP_ON, 0);
+ RNA_def_property_ui_icon(prop, ICON_PROP_OFF, 1);
RNA_def_property_update(prop, NC_SCENE | ND_TOOLSETTINGS, NULL); /* header redraw */
prop = RNA_def_property(srna, "use_proportional_projected", PROP_BOOLEAN, PROP_NONE);
@@ -2810,6 +2823,8 @@ static void rna_def_tool_settings(BlenderRNA *brna)
RNA_def_property_enum_items(prop, rna_enum_proportional_falloff_items);
RNA_def_property_ui_text(
prop, "Proportional Editing Falloff", "Falloff type for proportional editing mode");
+ /* Abusing id_curve :/ */
+ RNA_def_property_translation_context(prop, BLT_I18NCONTEXT_ID_CURVE);
RNA_def_property_update(prop, NC_SCENE | ND_TOOLSETTINGS, NULL); /* header redraw */
prop = RNA_def_property(srna, "proportional_size", PROP_FLOAT, PROP_DISTANCE);
@@ -2820,8 +2835,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);
@@ -2842,7 +2856,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);
@@ -3120,13 +3135,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");
@@ -3135,10 +3143,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);
@@ -3529,7 +3533,8 @@ static void rna_def_unit_settings(BlenderRNA *brna)
/* Units */
prop = RNA_def_property(srna, "system", PROP_ENUM, PROP_NONE);
RNA_def_property_enum_items(prop, unit_systems);
- RNA_def_property_ui_text(prop, "Unit System", "The unit system to use for button display");
+ RNA_def_property_ui_text(
+ prop, "Unit System", "The unit system to use for user interface controls");
RNA_def_property_update(prop, NC_WINDOW, "rna_UnitSettings_system_update");
prop = RNA_def_property(srna, "system_rotation", PROP_ENUM, PROP_NONE);
@@ -4662,60 +4667,6 @@ static void rna_def_bake_data(BlenderRNA *brna)
RNA_def_property_clear_flag(prop, PROP_EDITABLE);
}
-static void rna_def_gpu_dof_fx(BlenderRNA *brna)
-{
- StructRNA *srna;
- PropertyRNA *prop;
-
- srna = RNA_def_struct(brna, "GPUDOFSettings", NULL);
- RNA_def_struct_ui_text(srna, "GPU DOF", "Settings for GPU based depth of field");
- RNA_def_struct_path_func(srna, "rna_GPUDOF_path");
-
- prop = RNA_def_property(srna, "focus_distance", PROP_FLOAT, PROP_DISTANCE);
- RNA_def_property_ui_text(prop, "Focus distance", "Viewport depth of field focus distance");
- RNA_def_property_range(prop, 0.0f, FLT_MAX);
- RNA_def_property_ui_range(prop, 0.0f, 5000.0f, 1, 2);
- RNA_def_property_update(prop, NC_SPACE | ND_SPACE_VIEW3D, "rna_GPUDOFSettings_update");
-
- prop = RNA_def_property(srna, "focal_length", PROP_FLOAT, PROP_DISTANCE_CAMERA);
- RNA_def_property_ui_text(prop, "Focal Length", "Focal length for dof effect");
- RNA_def_property_range(prop, 1.0f, FLT_MAX);
- RNA_def_property_ui_range(prop, 1.0f, 5000.0f, 1, 2);
- RNA_def_property_update(prop, NC_SPACE | ND_SPACE_VIEW3D, "rna_GPUDOFSettings_update");
-
- prop = RNA_def_property(srna, "sensor", PROP_FLOAT, PROP_DISTANCE_CAMERA);
- RNA_def_property_ui_text(prop, "Sensor", "Size of sensor");
- RNA_def_property_range(prop, 1.0f, FLT_MAX);
- RNA_def_property_ui_range(prop, 1.0f, 5000.0f, 1, 2);
- RNA_def_property_update(prop, NC_SPACE | ND_SPACE_VIEW3D, "rna_GPUDOFSettings_update");
-
- prop = RNA_def_property(srna, "fstop", PROP_FLOAT, PROP_NONE);
- RNA_def_property_ui_text(prop, "F-stop", "F-stop for dof effect");
- RNA_def_property_float_default(prop, 128.0f);
- RNA_def_property_range(prop, 0.0f, FLT_MAX);
- RNA_def_property_ui_range(prop, 0.1f, 128.0f, 10, 1);
- RNA_def_property_update(prop, NC_SPACE | ND_SPACE_VIEW3D, "rna_GPUDOFSettings_update");
-
- prop = RNA_def_property(srna, "blades", PROP_INT, PROP_NONE);
- RNA_def_property_int_sdna(prop, NULL, "num_blades");
- RNA_def_property_ui_text(prop, "Blades", "Blades for dof effect");
- RNA_def_property_range(prop, 0, 16);
- RNA_def_property_int_funcs(prop, NULL, "rna_GPUDOFSettings_blades_set", NULL);
- RNA_def_property_update(prop, NC_SPACE | ND_SPACE_VIEW3D, "rna_GPUDOFSettings_update");
-
- prop = RNA_def_property(srna, "rotation", PROP_FLOAT, PROP_ANGLE);
- RNA_def_property_ui_text(prop, "Rotation", "Rotation of blades in aperture");
- RNA_def_property_range(prop, -M_PI, M_PI);
- RNA_def_property_update(prop, NC_SPACE | ND_SPACE_VIEW3D, NULL);
-
- prop = RNA_def_property(srna, "ratio", PROP_FLOAT, PROP_NONE);
- RNA_def_property_ui_text(prop, "Ratio", "Distortion to simulate anamorphic lens bokeh");
- RNA_def_property_float_default(prop, 1.0f);
- RNA_def_property_range(prop, 0.01f, FLT_MAX);
- RNA_def_property_ui_range(prop, 1.0f, 2.0f, 0.1, 3);
- RNA_def_property_update(prop, NC_SPACE | ND_SPACE_VIEW3D, NULL);
-}
-
static void rna_def_gpu_ssao_fx(BlenderRNA *brna)
{
StructRNA *srna;
@@ -4760,23 +4711,10 @@ static void rna_def_gpu_fx(BlenderRNA *brna)
PropertyRNA *prop;
rna_def_gpu_ssao_fx(brna);
- rna_def_gpu_dof_fx(brna);
srna = RNA_def_struct(brna, "GPUFXSettings", NULL);
RNA_def_struct_ui_text(srna, "GPU FX Settings", "Settings for GPU based compositing");
- prop = RNA_def_property(srna, "dof", PROP_POINTER, PROP_NONE);
- RNA_def_property_flag(prop, PROP_NEVER_NULL);
- RNA_def_property_struct_type(prop, "GPUDOFSettings");
- RNA_def_property_ui_text(prop, "Depth Of Field settings", "");
-
- prop = RNA_def_property(srna, "use_dof", PROP_BOOLEAN, PROP_NONE);
- RNA_def_property_boolean_sdna(prop, NULL, "fx_flag", GPU_FX_FLAG_DOF);
- RNA_def_property_ui_text(prop,
- "Depth Of Field",
- "Use depth of field on viewport using the values from active camera");
- RNA_def_property_update(prop, NC_SPACE | ND_SPACE_VIEW3D, NULL);
-
prop = RNA_def_property(srna, "ssao", PROP_POINTER, PROP_NONE);
RNA_def_property_flag(prop, PROP_NEVER_NULL);
RNA_def_property_struct_type(prop, "GPUSSAOSettings");
@@ -5434,16 +5372,6 @@ static void rna_def_scene_render_data(BlenderRNA *brna)
StructRNA *srna;
PropertyRNA *prop;
- static const EnumPropertyItem alpha_mode_items[] = {
- {R_ADDSKY, "SKY", 0, "Sky", "Transparent pixels are filled with sky color"},
- {R_ALPHAPREMUL,
- "TRANSPARENT",
- 0,
- "Transparent",
- "World background is transparent with premultiplied alpha"},
- {0, NULL, 0, NULL, NULL},
- };
-
static const EnumPropertyItem display_mode_items[] = {
{R_OUTPUT_SCREEN,
"SCREEN",
@@ -5477,14 +5405,6 @@ static void rna_def_scene_render_data(BlenderRNA *brna)
{0, NULL, 0, NULL, NULL},
};
- static const EnumPropertyItem fixed_oversample_items[] = {
- {5, "5", 0, "5", ""},
- {8, "8", 0, "8", ""},
- {11, "11", 0, "11", ""},
- {16, "16", 0, "16", ""},
- {0, NULL, 0, NULL, NULL},
- };
-
static const EnumPropertyItem threads_mode_items[] = {
{0,
"AUTO",
@@ -5679,27 +5599,13 @@ static void rna_def_scene_render_data(BlenderRNA *brna)
prop, "Filter Size", "Width over which the reconstruction filter combines samples");
RNA_def_property_update(prop, NC_SCENE | ND_RENDER_OPTIONS, NULL);
- prop = RNA_def_property(srna, "alpha_mode", PROP_ENUM, PROP_NONE);
- RNA_def_property_enum_sdna(prop, NULL, "alphamode");
- 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_RENDER_OPTIONS, "rna_Scene_glsl_update");
-
- prop = RNA_def_property(srna, "use_antialiasing", PROP_BOOLEAN, PROP_NONE);
- RNA_def_property_boolean_sdna(prop, NULL, "mode", R_OSA);
+ prop = RNA_def_property(srna, "film_transparent", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(prop, NULL, "alphamode", R_ALPHAPREMUL);
RNA_def_property_ui_text(
prop,
- "Anti-Aliasing",
- "Render and combine multiple samples per pixel to prevent jagged edges");
- RNA_def_property_update(prop, NC_SCENE | ND_RENDER_OPTIONS, NULL);
-
- prop = RNA_def_property(srna, "antialiasing_samples", PROP_ENUM, PROP_NONE);
- RNA_def_property_enum_sdna(prop, NULL, "osa");
- RNA_def_property_enum_items(prop, fixed_oversample_items);
- RNA_def_property_ui_text(
- prop, "Anti-Aliasing Samples", "Amount of anti-aliasing samples per pixel");
- RNA_def_property_update(prop, NC_SCENE | ND_RENDER_OPTIONS, NULL);
+ "Transparent",
+ "World background is transparent, for compositing the render over another background");
+ RNA_def_property_update(prop, NC_SCENE | ND_RENDER_OPTIONS, "rna_Scene_glsl_update");
prop = RNA_def_property(srna, "use_freestyle", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_clear_flag(prop, PROP_ANIMATABLE);
@@ -6573,6 +6479,18 @@ static void rna_def_scene_display(BlenderRNA *brna)
RNA_def_property_ui_text(prop, "Samples", "Number of samples");
RNA_def_property_range(prop, 1, 500);
+ prop = RNA_def_property(srna, "render_aa", PROP_ENUM, PROP_NONE);
+ RNA_def_property_enum_items(prop, rna_enum_scene_display_aa_methods);
+ RNA_def_property_ui_text(
+ prop, "Render Anti-Aliasing", "Method of anti-aliasing when rendering final image");
+ RNA_def_property_clear_flag(prop, PROP_ANIMATABLE);
+
+ prop = RNA_def_property(srna, "viewport_aa", PROP_ENUM, PROP_NONE);
+ RNA_def_property_enum_items(prop, rna_enum_scene_display_aa_methods);
+ RNA_def_property_ui_text(
+ prop, "Viewport Anti-Aliasing", "Method of anti-aliasing when rendering 3d viewport");
+ RNA_def_property_clear_flag(prop, PROP_ANIMATABLE);
+
/* OpenGL render engine settings. */
prop = RNA_def_property(srna, "shading", PROP_POINTER, PROP_NONE);
RNA_def_property_ui_text(prop, "Shading Settings", "Shading settings for OpenGL render engine");
@@ -6743,14 +6661,6 @@ static void rna_def_scene_eevee(BlenderRNA *brna)
RNA_def_property_update(prop, NC_SCENE | ND_RENDER_OPTIONS, NULL);
/* Screen Space Subsurface Scattering */
- prop = RNA_def_property(srna, "use_sss", PROP_BOOLEAN, PROP_NONE);
- RNA_def_property_boolean_sdna(prop, NULL, "flag", SCE_EEVEE_SSS_ENABLED);
- RNA_def_property_boolean_default(prop, 0);
- RNA_def_property_ui_text(
- prop, "Subsurface Scattering", "Enable screen space subsurface scattering");
- RNA_def_property_override_flag(prop, PROPOVERRIDE_OVERRIDABLE_STATIC);
- RNA_def_property_update(prop, NC_SCENE | ND_RENDER_OPTIONS, NULL);
-
prop = RNA_def_property(srna, "sss_samples", PROP_INT, PROP_NONE);
RNA_def_property_int_default(prop, 7);
RNA_def_property_ui_text(prop, "Samples", "Number of samples to compute the scattering effect");
@@ -6836,14 +6746,6 @@ static void rna_def_scene_eevee(BlenderRNA *brna)
RNA_def_property_update(prop, NC_SCENE | ND_RENDER_OPTIONS, NULL);
/* Volumetrics */
- prop = RNA_def_property(srna, "use_volumetric", PROP_BOOLEAN, PROP_NONE);
- RNA_def_property_boolean_sdna(prop, NULL, "flag", SCE_EEVEE_VOLUMETRIC_ENABLED);
- RNA_def_property_boolean_default(prop, 0);
- RNA_def_property_ui_text(
- prop, "Volumetrics", "Enable scattering and absorbance of volumetric material");
- RNA_def_property_override_flag(prop, PROPOVERRIDE_OVERRIDABLE_STATIC);
- RNA_def_property_update(prop, NC_SCENE | ND_RENDER_OPTIONS, NULL);
-
prop = RNA_def_property(srna, "volumetric_start", PROP_FLOAT, PROP_DISTANCE);
RNA_def_property_float_default(prop, 0.1f);
RNA_def_property_ui_text(prop, "Start", "Start distance of the volumetric effect");
@@ -6968,14 +6870,6 @@ static void rna_def_scene_eevee(BlenderRNA *brna)
RNA_def_property_update(prop, NC_SCENE | ND_RENDER_OPTIONS, NULL);
/* Depth of Field */
- prop = RNA_def_property(srna, "use_dof", PROP_BOOLEAN, PROP_NONE);
- RNA_def_property_boolean_sdna(prop, NULL, "flag", SCE_EEVEE_DOF_ENABLED);
- RNA_def_property_boolean_default(prop, 0);
- RNA_def_property_ui_text(
- prop, "Depth of Field", "Enable depth of field using the values from the active camera");
- RNA_def_property_override_flag(prop, PROPOVERRIDE_OVERRIDABLE_STATIC);
- RNA_def_property_update(prop, NC_SCENE | ND_RENDER_OPTIONS, NULL);
-
prop = RNA_def_property(srna, "bokeh_max_size", PROP_FLOAT, PROP_PIXEL);
RNA_def_property_float_default(prop, 100.0f);
RNA_def_property_ui_text(
diff --git a/source/blender/makesrna/intern/rna_scene_api.c b/source/blender/makesrna/intern/rna_scene_api.c
index e29891b60db..1d4d2e9cdd9 100644
--- a/source/blender/makesrna/intern/rna_scene_api.c
+++ b/source/blender/makesrna/intern/rna_scene_api.c
@@ -116,23 +116,6 @@ static void rna_Scene_uvedit_aspect(Scene *scene, Object *ob, float *aspect)
aspect[0] = aspect[1] = 1.0f;
}
-static void rna_Scene_update_tagged(Scene *scene, Main *bmain)
-{
-# ifdef WITH_PYTHON
- BPy_BEGIN_ALLOW_THREADS;
-# endif
-
- for (ViewLayer *view_layer = scene->view_layers.first; view_layer != NULL;
- view_layer = view_layer->next) {
- Depsgraph *depsgraph = BKE_scene_get_depsgraph(scene, view_layer, true);
- BKE_scene_graph_update_tagged(depsgraph, bmain);
- }
-
-# ifdef WITH_PYTHON
- BPy_END_ALLOW_THREADS;
-# endif
-}
-
static void rna_SceneRender_get_frame_path(
RenderData *rd, Main *bmain, int frame, bool preview, const char *view, char *name)
{
@@ -303,11 +286,6 @@ void RNA_api_scene(StructRNA *srna)
func, "subframe", 0.0, 0.0, 1.0, "", "Sub-frame time, between 0.0 and 1.0", 0.0, 1.0);
RNA_def_function_flag(func, FUNC_USE_MAIN);
- func = RNA_def_function(srna, "update", "rna_Scene_update_tagged");
- RNA_def_function_ui_description(
- func, "Update data tagged to be updated from previous access to data or operators");
- RNA_def_function_flag(func, FUNC_USE_MAIN);
-
func = RNA_def_function(srna, "uvedit_aspect", "rna_Scene_uvedit_aspect");
RNA_def_function_ui_description(func, "Get uv aspect for current object");
parm = RNA_def_pointer(func, "object", "Object", "", "Object");
diff --git a/source/blender/makesrna/intern/rna_screen.c b/source/blender/makesrna/intern/rna_screen.c
index 3de946c1c8f..9c349d64953 100644
--- a/source/blender/makesrna/intern/rna_screen.c
+++ b/source/blender/makesrna/intern/rna_screen.c
@@ -93,7 +93,7 @@ static bool rna_Screen_is_animation_playing_get(PointerRNA *UNUSED(ptr))
static int rna_region_alignment_get(PointerRNA *ptr)
{
ARegion *region = ptr->data;
- return (region->alignment & ~RGN_SPLIT_PREV);
+ return RGN_ALIGN_ENUM_FROM_MASK(region->alignment);
}
static bool rna_Screen_fullscreen_get(PointerRNA *ptr)
diff --git a/source/blender/makesrna/intern/rna_sequencer.c b/source/blender/makesrna/intern/rna_sequencer.c
index 0b1e35e3a74..713ffe2fb08 100644
--- a/source/blender/makesrna/intern/rna_sequencer.c
+++ b/source/blender/makesrna/intern/rna_sequencer.c
@@ -465,7 +465,9 @@ static void rna_SequenceCrop_update(Main *UNUSED(bmain), Scene *UNUSED(scene), P
BKE_sequence_invalidate_cache(scene, seq);
}
-static void rna_Sequence_text_font_set(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;
@@ -1189,25 +1191,25 @@ static void rna_def_strip_crop(BlenderRNA *brna)
RNA_def_struct_ui_text(srna, "Sequence Crop", "Cropping parameters for a sequence strip");
RNA_def_struct_sdna(srna, "StripCrop");
- prop = RNA_def_property(srna, "max_y", PROP_INT, PROP_UNSIGNED);
+ prop = RNA_def_property(srna, "max_y", PROP_INT, PROP_PIXEL);
RNA_def_property_int_sdna(prop, NULL, "top");
RNA_def_property_ui_text(prop, "Top", "Number of pixels to crop from the top");
RNA_def_property_ui_range(prop, 0, 4096, 1, -1);
RNA_def_property_update(prop, NC_SCENE | ND_SEQUENCER, "rna_SequenceCrop_update");
- prop = RNA_def_property(srna, "min_y", PROP_INT, PROP_UNSIGNED);
+ prop = RNA_def_property(srna, "min_y", PROP_INT, PROP_PIXEL);
RNA_def_property_int_sdna(prop, NULL, "bottom");
RNA_def_property_ui_text(prop, "Bottom", "Number of pixels to crop from the bottom");
RNA_def_property_ui_range(prop, 0, 4096, 1, -1);
RNA_def_property_update(prop, NC_SCENE | ND_SEQUENCER, "rna_SequenceCrop_update");
- prop = RNA_def_property(srna, "min_x", PROP_INT, PROP_UNSIGNED);
+ prop = RNA_def_property(srna, "min_x", PROP_INT, PROP_PIXEL);
RNA_def_property_int_sdna(prop, NULL, "left");
RNA_def_property_ui_text(prop, "Left", "Number of pixels to crop from the left side");
RNA_def_property_ui_range(prop, 0, 4096, 1, -1);
RNA_def_property_update(prop, NC_SCENE | ND_SEQUENCER, "rna_SequenceCrop_update");
- prop = RNA_def_property(srna, "max_x", PROP_INT, PROP_UNSIGNED);
+ prop = RNA_def_property(srna, "max_x", PROP_INT, PROP_PIXEL);
RNA_def_property_int_sdna(prop, NULL, "right");
RNA_def_property_ui_text(prop, "Right", "Number of pixels to crop from the right side");
RNA_def_property_ui_range(prop, 0, 4096, 1, -1);
@@ -1225,14 +1227,14 @@ static void rna_def_strip_transform(BlenderRNA *brna)
RNA_def_struct_ui_text(srna, "Sequence Transform", "Transform parameters for a sequence strip");
RNA_def_struct_sdna(srna, "StripTransform");
- prop = RNA_def_property(srna, "offset_x", PROP_INT, PROP_NONE);
+ prop = RNA_def_property(srna, "offset_x", PROP_INT, PROP_PIXEL);
RNA_def_property_int_sdna(prop, NULL, "xofs");
RNA_def_property_ui_text(
prop, "Offset X", "Amount to move the input on the X axis within its boundaries");
RNA_def_property_ui_range(prop, -4096, 4096, 1, -1);
RNA_def_property_update(prop, NC_SCENE | ND_SEQUENCER, "rna_SequenceTransform_update");
- prop = RNA_def_property(srna, "offset_y", PROP_INT, PROP_NONE);
+ prop = RNA_def_property(srna, "offset_y", PROP_INT, PROP_PIXEL);
RNA_def_property_int_sdna(prop, NULL, "yofs");
RNA_def_property_ui_text(
prop, "Offset Y", "Amount to move the input on the Y axis within its boundaries");
diff --git a/source/blender/makesrna/intern/rna_shader_fx.c b/source/blender/makesrna/intern/rna_shader_fx.c
index 06c968534cc..4aa87055e1b 100644
--- a/source/blender/makesrna/intern/rna_shader_fx.c
+++ b/source/blender/makesrna/intern/rna_shader_fx.c
@@ -185,7 +185,8 @@ 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(PointerRNA *ptr, PointerRNA value) \
+ static void rna_##_type##ShaderFx_##_prop##_set( \
+ 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_smoke.c b/source/blender/makesrna/intern/rna_smoke.c
index b6486d7a3f4..f4fba02efe5 100644
--- a/source/blender/makesrna/intern/rna_smoke.c
+++ b/source/blender/makesrna/intern/rna_smoke.c
@@ -463,7 +463,7 @@ static void rna_def_smoke_domain_settings(BlenderRNA *brna)
{0, NULL, 0, NULL, NULL}};
static const EnumPropertyItem smoke_cache_comp_items[] = {
- {SM_CACHE_LIGHT, "CACHELIGHT", 0, "Light", "Fast but not so effective compression"},
+ {SM_CACHE_LIGHT, "CACHELIGHT", 0, "Lite", "Fast but not so effective compression"},
{SM_CACHE_HEAVY, "CACHEHEAVY", 0, "Heavy", "Effective but slow compression"},
{0, NULL, 0, NULL, NULL},
};
diff --git a/source/blender/makesrna/intern/rna_space.c b/source/blender/makesrna/intern/rna_space.c
index 633164238e0..3e8b4274042 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_STUDIO, "STUDIO", 0, "Studio", "Display using studio 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"},
@@ -633,7 +633,7 @@ static void rna_Space_show_region_header_set(PointerRNA *ptr, bool value)
ScrArea *sa = rna_area_from_space(ptr);
ARegion *ar_tool_header = BKE_area_find_region_type(sa, RGN_TYPE_TOOL_HEADER);
if (ar_tool_header != NULL) {
- value = !(ar_tool_header->flag & RGN_FLAG_HIDDEN_BY_USER);
+ value_for_tool_header = !(ar_tool_header->flag & RGN_FLAG_HIDDEN_BY_USER);
}
}
rna_Space_bool_from_region_flag_set_by_type(
@@ -644,6 +644,20 @@ static void rna_Space_show_region_header_update(bContext *C, PointerRNA *ptr)
rna_Space_bool_from_region_flag_update_by_type(C, ptr, RGN_TYPE_HEADER, RGN_FLAG_HIDDEN);
}
+/* Footer Region. */
+static bool rna_Space_show_region_footer_get(PointerRNA *ptr)
+{
+ return !rna_Space_bool_from_region_flag_get_by_type(ptr, RGN_TYPE_FOOTER, RGN_FLAG_HIDDEN);
+}
+static void rna_Space_show_region_footer_set(PointerRNA *ptr, bool value)
+{
+ rna_Space_bool_from_region_flag_set_by_type(ptr, RGN_TYPE_FOOTER, RGN_FLAG_HIDDEN, !value);
+}
+static void rna_Space_show_region_footer_update(bContext *C, PointerRNA *ptr)
+{
+ rna_Space_bool_from_region_flag_update_by_type(C, ptr, RGN_TYPE_FOOTER, RGN_FLAG_HIDDEN);
+}
+
/* Tool Header Region.
*
* This depends on the 'RGN_TYPE_TOOL_HEADER'
@@ -1069,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);
@@ -1315,7 +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(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;
@@ -1327,7 +1343,9 @@ static void rna_SpaceImageEditor_image_set(PointerRNA *ptr, PointerRNA value)
ED_space_image_set(G_MAIN, sima, obedit, (Image *)value.data, false);
}
-static void rna_SpaceImageEditor_mask_set(PointerRNA *ptr, PointerRNA value)
+static void rna_SpaceImageEditor_mask_set(PointerRNA *ptr,
+ PointerRNA value,
+ struct ReportList *UNUSED(reports))
{
SpaceImage *sima = (SpaceImage *)(ptr->data);
@@ -1493,7 +1511,9 @@ static void rna_SpaceTextEditor_word_wrap_set(PointerRNA *ptr, bool value)
st->left = 0;
}
-static void rna_SpaceTextEditor_text_set(PointerRNA *ptr, PointerRNA value)
+static void rna_SpaceTextEditor_text_set(PointerRNA *ptr,
+ PointerRNA value,
+ struct ReportList *UNUSED(reports))
{
SpaceText *st = (SpaceText *)(ptr->data);
@@ -1515,7 +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(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;
@@ -1717,7 +1739,9 @@ static void rna_ConsoleLine_cursor_index_range(
/* Space Dopesheet */
-static void rna_SpaceDopeSheetEditor_action_set(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;
@@ -1939,7 +1963,9 @@ static void rna_Sequencer_view_type_update(Main *UNUSED(bmain),
/* Space Node Editor */
-static void rna_SpaceNodeEditor_node_tree_set(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);
@@ -2050,7 +2076,9 @@ static void rna_SpaceNodeEditor_cursor_location_from_region(SpaceNode *snode,
snode->cursor[1] /= UI_DPI_FAC;
}
-static void rna_SpaceClipEditor_clip_set(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;
@@ -2058,7 +2086,9 @@ static void rna_SpaceClipEditor_clip_set(PointerRNA *ptr, PointerRNA value)
ED_space_clip_set_clip(NULL, screen, sc, (MovieClip *)value.data);
}
-static void rna_SpaceClipEditor_mask_set(PointerRNA *ptr, PointerRNA value)
+static void rna_SpaceClipEditor_mask_set(PointerRNA *ptr,
+ PointerRNA value,
+ struct ReportList *UNUSED(reports))
{
SpaceClip *sc = (SpaceClip *)(ptr->data);
@@ -2454,12 +2484,16 @@ 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);
DEF_SHOW_REGION_PROPERTY(show_region_header, "Header", "");
}
+ if (region_type_mask & (1 << RGN_TYPE_FOOTER)) {
+ region_type_mask &= ~(1 << RGN_TYPE_FOOTER);
+ DEF_SHOW_REGION_PROPERTY(show_region_footer, "Footer", "");
+ }
if (region_type_mask & (1 << RGN_TYPE_TOOLS)) {
region_type_mask &= ~(1 << RGN_TYPE_TOOLS);
DEF_SHOW_REGION_PROPERTY(show_region_toolbar, "Toolbar", "");
@@ -2608,7 +2642,7 @@ static void rna_def_space_image_uv(BlenderRNA *brna)
prop = RNA_def_property(srna, "edge_display_type", PROP_ENUM, PROP_NONE);
RNA_def_property_enum_sdna(prop, NULL, "dt_uv");
RNA_def_property_enum_items(prop, dt_uv_items);
- RNA_def_property_ui_text(prop, "Edge Display Type", "Display type for drawing UV edges");
+ RNA_def_property_ui_text(prop, "Display As", "Display style for UV edges");
RNA_def_property_update(prop, NC_SPACE | ND_SPACE_IMAGE, NULL);
prop = RNA_def_property(srna, "show_smooth_edges", PROP_BOOLEAN, PROP_NONE);
@@ -2750,25 +2784,60 @@ static void rna_def_space_outliner(BlenderRNA *brna)
RNA_def_property_boolean_sdna(prop, NULL, "search_flags", SO_FIND_CASE_SENSITIVE);
RNA_def_property_ui_text(
prop, "Case Sensitive Matches Only", "Only use case sensitive matches of search string");
- RNA_def_property_ui_icon(prop, ICON_SYNTAX_OFF, 0);
RNA_def_property_update(prop, NC_SPACE | ND_SPACE_OUTLINER, NULL);
prop = RNA_def_property(srna, "use_filter_complete", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "search_flags", SO_FIND_COMPLETE);
RNA_def_property_ui_text(
prop, "Complete Matches Only", "Only use complete matches of search string");
- RNA_def_property_ui_icon(prop, ICON_OUTLINER_DATA_FONT, 0);
RNA_def_property_update(prop, NC_SPACE | ND_SPACE_OUTLINER, NULL);
prop = RNA_def_property(srna, "use_sort_alpha", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_negative_sdna(prop, NULL, "flag", SO_SKIP_SORT_ALPHA);
RNA_def_property_ui_text(prop, "Sort Alphabetically", "");
- RNA_def_property_ui_icon(prop, ICON_SORTALPHA, 0);
RNA_def_property_update(prop, NC_SPACE | ND_SPACE_OUTLINER, NULL);
- prop = RNA_def_property(srna, "show_restrict_columns", PROP_BOOLEAN, PROP_NONE);
- RNA_def_property_boolean_negative_sdna(prop, NULL, "flag", SO_HIDE_RESTRICTCOLS);
- RNA_def_property_ui_text(prop, "Show Restriction Columns", "Show column");
+ /* Granular restriction column option. */
+ prop = RNA_def_property(srna, "show_restrict_column_enable", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(prop, NULL, "show_restrict_flags", SO_RESTRICT_ENABLE);
+ RNA_def_property_ui_text(prop, "Exclude from View Layer", "Exclude from view layer");
+ RNA_def_property_ui_icon(prop, ICON_CHECKBOX_HLT, 0);
+ RNA_def_property_update(prop, NC_SPACE | ND_SPACE_OUTLINER, NULL);
+
+ prop = RNA_def_property(srna, "show_restrict_column_select", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(prop, NULL, "show_restrict_flags", SO_RESTRICT_SELECT);
+ RNA_def_property_ui_text(prop, "Selectable", "Selectable");
+ RNA_def_property_ui_icon(prop, ICON_RESTRICT_SELECT_OFF, 0);
+ RNA_def_property_update(prop, NC_SPACE | ND_SPACE_OUTLINER, NULL);
+
+ prop = RNA_def_property(srna, "show_restrict_column_hide", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(prop, NULL, "show_restrict_flags", SO_RESTRICT_HIDE);
+ RNA_def_property_ui_text(prop, "Hide in Viewport", "Temporarily hide in viewport");
+ RNA_def_property_ui_icon(prop, ICON_HIDE_OFF, 0);
+ RNA_def_property_update(prop, NC_SPACE | ND_SPACE_OUTLINER, NULL);
+
+ prop = RNA_def_property(srna, "show_restrict_column_viewport", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(prop, NULL, "show_restrict_flags", SO_RESTRICT_VIEWPORT);
+ RNA_def_property_ui_text(prop, "Disable in Viewports", "Globally disable in viewports");
+ RNA_def_property_ui_icon(prop, ICON_RESTRICT_VIEW_OFF, 0);
+ RNA_def_property_update(prop, NC_SPACE | ND_SPACE_OUTLINER, NULL);
+
+ prop = RNA_def_property(srna, "show_restrict_column_render", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(prop, NULL, "show_restrict_flags", SO_RESTRICT_RENDER);
+ RNA_def_property_ui_text(prop, "Disable in Renders", "Globally disable in renders");
+ RNA_def_property_ui_icon(prop, ICON_RESTRICT_RENDER_OFF, 0);
+ RNA_def_property_update(prop, NC_SPACE | ND_SPACE_OUTLINER, NULL);
+
+ prop = RNA_def_property(srna, "show_restrict_column_holdout", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(prop, NULL, "show_restrict_flags", SO_RESTRICT_HOLDOUT);
+ RNA_def_property_ui_text(prop, "Holdout", "Holdout");
+ RNA_def_property_ui_icon(prop, ICON_HOLDOUT_ON, 0);
+ RNA_def_property_update(prop, NC_SPACE | ND_SPACE_OUTLINER, NULL);
+
+ prop = RNA_def_property(srna, "show_restrict_column_indirect_only", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(prop, NULL, "show_restrict_flags", SO_RESTRICT_INDIRECT_ONLY);
+ RNA_def_property_ui_text(prop, "Indirect Only", "Indirect only");
+ RNA_def_property_ui_icon(prop, ICON_INDIRECT_ONLY_ON, 0);
RNA_def_property_update(prop, NC_SPACE | ND_SPACE_OUTLINER, NULL);
/* Filters. */
@@ -3275,7 +3344,7 @@ static void rna_def_space_view3d_overlay(BlenderRNA *brna)
prop = RNA_def_property(srna, "show_look_dev", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "overlay.flag", V3D_OVERLAY_LOOK_DEV);
RNA_def_property_clear_flag(prop, PROP_ANIMATABLE);
- RNA_def_property_ui_text(prop, "Look Dev Preview", "Show look development balls and palette");
+ RNA_def_property_ui_text(prop, "Look Dev Preview", "Show look development spheres and palette");
RNA_def_property_update(prop, NC_SPACE | ND_SPACE_VIEW3D, NULL);
prop = RNA_def_property(srna, "show_wireframes", PROP_BOOLEAN, PROP_NONE);
@@ -4473,7 +4542,7 @@ static void rna_def_space_text(BlenderRNA *brna)
RNA_def_struct_sdna(srna, "SpaceText");
RNA_def_struct_ui_text(srna, "Space Text Editor", "Text editor space data");
- rna_def_space_generic_show_region_toggles(srna, (1 << RGN_TYPE_UI));
+ rna_def_space_generic_show_region_toggles(srna, (1 << RGN_TYPE_UI) | (1 << RGN_TYPE_FOOTER));
/* text */
prop = RNA_def_property(srna, "text", PROP_POINTER, PROP_NONE);
@@ -5146,7 +5215,7 @@ static void rna_def_fileselect_params(BlenderRNA *brna)
"Show/hide Paint Curve data-blocks"},
{FILTER_ID_LP,
"LIGHT_PROBE",
- ICON_LIGHTPROBE_CUBEMAP,
+ ICON_OUTLINER_DATA_LIGHTPROBE,
"Light Probes",
"Show/hide Light Probe data-blocks"},
{FILTER_ID_SCE, "SCENE", ICON_SCENE_DATA, "Scenes", "Show/hide Scene data-blocks"},
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 1fbdac9df38..d08f7bc6035 100644
--- a/source/blender/makesrna/intern/rna_tracking.c
+++ b/source/blender/makesrna/intern/rna_tracking.c
@@ -144,7 +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(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;
@@ -165,7 +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(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;
@@ -476,7 +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(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 eade12be631..1f48e19d09a 100644
--- a/source/blender/makesrna/intern/rna_userdef.c
+++ b/source/blender/makesrna/intern/rna_userdef.c
@@ -42,6 +42,8 @@
#include "RNA_define.h"
#include "RNA_enum_types.h"
+#include "UI_interface_icons.h"
+
#include "rna_internal.h"
#include "WM_api.h"
@@ -99,6 +101,45 @@ static const EnumPropertyItem rna_enum_studio_light_type_items[] = {
{0, NULL, 0, NULL, NULL},
};
+static const EnumPropertyItem rna_enum_userdef_viewport_aa_items[] = {
+ {SCE_DISPLAY_AA_OFF,
+ "OFF",
+ 0,
+ "No Anti-Aliasing",
+ "Scene will be rendering without any anti-aliasing"},
+ {SCE_DISPLAY_AA_FXAA,
+ "FXAA",
+ 0,
+ "Single Pass Anti-Aliasing",
+ "Scene will be rendered using a single pass anti-aliasing method (FXAA)"},
+ {SCE_DISPLAY_AA_SAMPLES_5,
+ "5",
+ 0,
+ "5 Samples",
+ "Scene will be rendered using 5 anti-aliasing samples"},
+ {SCE_DISPLAY_AA_SAMPLES_8,
+ "8",
+ 0,
+ "8 Samples",
+ "Scene will be rendered using 8 anti-aliasing samples"},
+ {SCE_DISPLAY_AA_SAMPLES_11,
+ "11",
+ 0,
+ "11 Samples",
+ "Scene will be rendered using 11 anti-aliasing samples"},
+ {SCE_DISPLAY_AA_SAMPLES_16,
+ "16",
+ 0,
+ "16 Samples",
+ "Scene will be rendered using 16 anti-aliasing samples"},
+ {SCE_DISPLAY_AA_SAMPLES_32,
+ "32",
+ 0,
+ "32 Samples",
+ "Scene will be rendered using 32 anti-aliasing samples"},
+ {0, NULL, 0, NULL, NULL},
+};
+
#ifdef RNA_RUNTIME
# include "BLI_math_vector.h"
@@ -143,9 +184,42 @@ 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))
+{
+ WM_main_add_notifier(NC_WINDOW, NULL);
+}
+
static void rna_userdef_update(Main *UNUSED(bmain), Scene *UNUSED(scene), PointerRNA *UNUSED(ptr))
{
WM_main_add_notifier(NC_WINDOW, NULL);
+ USERDEF_TAG_DIRTY;
}
static void rna_userdef_theme_update(Main *bmain, Scene *scene, PointerRNA *ptr)
@@ -156,6 +230,12 @@ static void rna_userdef_theme_update(Main *bmain, Scene *scene, PointerRNA *ptr)
rna_userdef_update(bmain, scene, ptr);
}
+static void rna_userdef_theme_update_icons(Main *bmain, Scene *scene, PointerRNA *ptr)
+{
+ UI_icons_reload_internal_textures();
+ rna_userdef_theme_update(bmain, scene, ptr);
+}
+
/* also used by buffer swap switching */
static void rna_userdef_dpi_update(Main *UNUSED(bmain),
Scene *UNUSED(scene),
@@ -166,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),
@@ -193,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),
@@ -204,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)
@@ -213,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)
@@ -265,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
@@ -274,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
@@ -283,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)
@@ -352,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),
@@ -359,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)
@@ -401,6 +494,7 @@ static bAddon *rna_userdef_addon_new(void)
ListBase *addons_list = &U.addons;
bAddon *addon = BKE_addon_new();
BLI_addtail(addons_list, addon);
+ USERDEF_TAG_DIRTY;
return addon;
}
@@ -415,12 +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);
+ 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);
+ USERDEF_TAG_DIRTY;
return path_cmp;
}
@@ -434,6 +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);
+ USERDEF_TAG_DIRTY;
}
static void rna_userdef_temp_update(Main *UNUSED(bmain),
@@ -441,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),
@@ -450,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)
@@ -516,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
@@ -1338,6 +1438,12 @@ static void rna_def_userdef_theme_ui(BlenderRNA *brna)
RNA_def_property_update(prop, 0, "rna_userdef_theme_update");
/* Icon colors. */
+ prop = RNA_def_property(srna, "icon_scene", PROP_FLOAT, PROP_COLOR_GAMMA);
+ RNA_def_property_float_sdna(prop, NULL, "icon_scene");
+ RNA_def_property_array(prop, 4);
+ RNA_def_property_ui_text(prop, "Scene", "");
+ RNA_def_property_update(prop, 0, "rna_userdef_theme_update");
+
prop = RNA_def_property(srna, "icon_collection", PROP_FLOAT, PROP_COLOR_GAMMA);
RNA_def_property_float_sdna(prop, NULL, "icon_collection");
RNA_def_property_array(prop, 4);
@@ -1367,6 +1473,13 @@ static void rna_def_userdef_theme_ui(BlenderRNA *brna)
RNA_def_property_array(prop, 4);
RNA_def_property_ui_text(prop, "Shading", "");
RNA_def_property_update(prop, 0, "rna_userdef_theme_update");
+
+ prop = RNA_def_property(srna, "icon_border_intensity", PROP_FLOAT, PROP_FACTOR);
+ RNA_def_property_float_sdna(prop, NULL, "icon_border_intensity");
+ RNA_def_property_ui_text(
+ prop, "Icon Border", "Control the intensity of the border around themes icons");
+ RNA_def_property_ui_range(prop, 0.0, 1.0, 0.1, 2);
+ RNA_def_property_update(prop, 0, "rna_userdef_theme_update_icons");
}
static void rna_def_userdef_theme_space_common(StructRNA *srna)
@@ -2065,6 +2178,11 @@ 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);
+ 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");
+
prop = RNA_def_property(srna, "window_sliders", PROP_FLOAT, PROP_COLOR_GAMMA);
RNA_def_property_float_sdna(prop, NULL, "shade1");
RNA_def_property_array(prop, 3);
@@ -2155,6 +2273,26 @@ static void rna_def_userdef_theme_space_outliner(BlenderRNA *brna)
RNA_def_property_array(prop, 3);
RNA_def_property_ui_text(prop, "Selected Highlight", "");
RNA_def_property_update(prop, 0, "rna_userdef_theme_update");
+
+ prop = RNA_def_property(srna, "selected_object", PROP_FLOAT, PROP_COLOR_GAMMA);
+ RNA_def_property_array(prop, 3);
+ RNA_def_property_ui_text(prop, "Selected Objects", "");
+ RNA_def_property_update(prop, 0, "rna_userdef_theme_update");
+
+ prop = RNA_def_property(srna, "active_object", PROP_FLOAT, PROP_COLOR_GAMMA);
+ RNA_def_property_array(prop, 3);
+ RNA_def_property_ui_text(prop, "Active Object", "");
+ RNA_def_property_update(prop, 0, "rna_userdef_theme_update");
+
+ prop = RNA_def_property(srna, "edited_object", PROP_FLOAT, PROP_COLOR_GAMMA);
+ RNA_def_property_array(prop, 4);
+ RNA_def_property_ui_text(prop, "Edited Object", "");
+ RNA_def_property_update(prop, 0, "rna_userdef_theme_update");
+
+ prop = RNA_def_property(srna, "row_alternate", PROP_FLOAT, PROP_COLOR_GAMMA);
+ RNA_def_property_array(prop, 4);
+ RNA_def_property_ui_text(prop, "Alternate Rows", "Overlay color on every other row");
+ RNA_def_property_update(prop, 0, "rna_userdef_theme_update");
}
static void rna_def_userdef_theme_space_userpref(BlenderRNA *brna)
@@ -2402,8 +2540,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);
@@ -2578,7 +2714,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);
@@ -2687,7 +2822,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);
@@ -2759,6 +2893,11 @@ 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);
+ 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");
+
prop = RNA_def_property(srna, "keyframe", PROP_FLOAT, PROP_COLOR_GAMMA);
RNA_def_property_float_sdna(prop, NULL, "vertex_select");
RNA_def_property_array(prop, 3);
@@ -2816,6 +2955,11 @@ 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);
+ 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");
+
prop = RNA_def_property(srna, "value_sliders", PROP_FLOAT, PROP_COLOR_GAMMA);
RNA_def_property_float_sdna(prop, NULL, "face");
RNA_def_property_array(prop, 3);
@@ -3108,6 +3252,11 @@ static void rna_def_userdef_theme_space_nla(BlenderRNA *brna)
RNA_def_property_array(prop, 3);
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);
+ 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");
}
static void rna_def_userdef_theme_colorset(BlenderRNA *brna)
@@ -3159,8 +3308,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);
@@ -3215,6 +3362,11 @@ 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);
+ 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");
+
prop = RNA_def_property(srna, "strips", PROP_FLOAT, PROP_COLOR_GAMMA);
RNA_def_property_float_sdna(prop, NULL, "strip");
RNA_def_property_array(prop, 3);
@@ -3945,7 +4097,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);
@@ -4046,7 +4198,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", ""},
@@ -4108,6 +4260,15 @@ static void rna_def_userdef_view(BlenderRNA *brna)
RNA_def_property_ui_text(prop, "Gizmo Size", "Diameter of the gizmo");
RNA_def_property_update(prop, 0, "rna_userdef_update");
+ /* Lookdev */
+ prop = RNA_def_property(srna, "lookdev_sphere_size", PROP_INT, PROP_PIXEL);
+ RNA_def_property_int_sdna(prop, NULL, "lookdev_sphere_size");
+ RNA_def_property_range(prop, 50, 400);
+ RNA_def_property_int_default(prop, 150);
+ RNA_def_property_ui_text(
+ prop, "Look Dev Spheres Size", "Maximum diameter of the look development sphere size");
+ RNA_def_property_update(prop, 0, "rna_userdef_update");
+
/* View2D Grid Displays */
prop = RNA_def_property(srna, "view2d_grid_spacing_min", PROP_INT, PROP_PIXEL);
RNA_def_property_int_sdna(prop, NULL, "v2d_min_gridsize");
@@ -4238,7 +4399,12 @@ static void rna_def_userdef_edit(BlenderRNA *brna)
"VIEW",
0,
"View",
- "Align newly added objects facing the active 3D View direction"},
+ "Align newly added objects to the active 3D View direction"},
+ {USER_ADD_CURSORALIGNED,
+ "CURSOR",
+ 0,
+ "3D Cursor",
+ "Align newly added objects to the 3D Cursor's rotation"},
{0, NULL, 0, NULL, NULL},
};
@@ -4697,12 +4863,11 @@ static void rna_def_userdef_system(BlenderRNA *brna)
prop, "Region Overlap", "Draw tool/property regions over the main region");
RNA_def_property_update(prop, 0, "rna_userdef_dpi_update");
- prop = RNA_def_property(srna, "gpu_viewport_quality", PROP_FLOAT, PROP_FACTOR);
- RNA_def_property_float_sdna(prop, NULL, "gpu_viewport_quality");
- RNA_def_property_float_default(prop, 0.6f);
- RNA_def_property_range(prop, 0.0f, 1.0f);
+ prop = RNA_def_property(srna, "viewport_aa", PROP_ENUM, PROP_NONE);
+ RNA_def_property_enum_items(prop, rna_enum_userdef_viewport_aa_items);
RNA_def_property_ui_text(
- prop, "Viewport Quality", "Quality setting for Solid mode rendering in the 3d viewport");
+ prop, "Viewport Anti-Aliasing", "Method of anti-aliasing in 3d viewport");
+ RNA_def_property_clear_flag(prop, PROP_ANIMATABLE);
RNA_def_property_update(prop, 0, "rna_userdef_update");
prop = RNA_def_property(srna, "solid_lights", PROP_COLLECTION, PROP_NONE);
@@ -5447,6 +5612,8 @@ static void rna_def_userdef_autoexec_path_collection(BlenderRNA *brna, PropertyR
void RNA_def_userdef(BlenderRNA *brna)
{
+ RNA_define_fallback_property_update(0, "rna_userdef_is_dirty_update");
+
StructRNA *srna;
PropertyRNA *prop;
@@ -5490,7 +5657,7 @@ void RNA_def_userdef(BlenderRNA *brna)
RNA_def_property_enum_items(prop, preference_section_items);
RNA_def_property_ui_text(
prop, "Active Section", "Active section of the preferences shown in the user interface");
- RNA_def_property_update(prop, 0, "rna_userdef_update");
+ RNA_def_property_update(prop, 0, "rna_userdef_ui_update");
/* don't expose this directly via the UI, modify via an operator */
prop = RNA_def_property(srna, "app_template", PROP_STRING, PROP_NONE);
@@ -5586,6 +5753,16 @@ void RNA_def_userdef(BlenderRNA *brna)
NULL);
RNA_def_property_ui_text(prop, "Studio Lights", "");
+ /* Preferences Flags */
+ prop = RNA_def_property(srna, "use_preferences_save", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(prop, NULL, "pref_flag", USER_PREF_FLAG_SAVE);
+ RNA_def_property_ui_text(prop, "Save on Exit", "Save modified preferences on exit");
+
+ prop = RNA_def_property(srna, "is_dirty", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(prop, NULL, "runtime.is_dirty", 0);
+ RNA_def_property_clear_flag(prop, PROP_EDITABLE);
+ RNA_def_property_ui_text(prop, "Dirty", "Preferences have changed");
+
rna_def_userdef_view(brna);
rna_def_userdef_edit(brna);
rna_def_userdef_input(brna);
@@ -5597,6 +5774,8 @@ void RNA_def_userdef(BlenderRNA *brna)
rna_def_userdef_studiolights(brna);
rna_def_userdef_studiolight(brna);
rna_def_userdef_pathcompare(brna);
+
+ RNA_define_fallback_property_update(0, NULL);
}
#endif
diff --git a/source/blender/makesrna/intern/rna_wm.c b/source/blender/makesrna/intern/rna_wm.c
index 3f904df6e00..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,7 +691,9 @@ static PointerRNA rna_PieMenu_layout_get(PointerRNA *ptr)
return rptr;
}
-static void rna_Window_scene_set(PointerRNA *ptr, PointerRNA value)
+static void rna_Window_scene_set(PointerRNA *ptr,
+ PointerRNA value,
+ struct ReportList *UNUSED(reports))
{
wmWindow *win = ptr->data;
@@ -738,7 +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(PointerRNA *ptr, PointerRNA value)
+static void rna_Window_workspace_set(PointerRNA *ptr,
+ PointerRNA value,
+ struct ReportList *UNUSED(reports))
{
wmWindow *win = (wmWindow *)ptr->data;
@@ -774,7 +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(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);
@@ -824,7 +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(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;
@@ -1028,7 +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(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;
@@ -1868,6 +1875,7 @@ static void rna_def_operator(BlenderRNA *brna)
RNA_def_struct_idprops_func(srna, "rna_OperatorProperties_idprops");
RNA_def_struct_property_tags(srna, rna_enum_operator_property_tags);
RNA_def_struct_flag(srna, STRUCT_NO_DATABLOCK_IDPROPERTIES);
+ RNA_def_struct_clear_flag(srna, STRUCT_UNDO);
}
static void rna_def_macro_operator(BlenderRNA *brna)
@@ -2105,6 +2113,7 @@ static void rna_def_event(BlenderRNA *brna)
RNA_def_property_boolean_sdna(prop, NULL, "shift", 1);
RNA_def_property_clear_flag(prop, PROP_EDITABLE);
RNA_def_property_ui_text(prop, "Shift", "True when the Shift key is held");
+ RNA_def_property_translation_context(prop, BLT_I18NCONTEXT_ID_WINDOWMANAGER);
prop = RNA_def_property(srna, "ctrl", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "ctrl", 1);
@@ -2601,6 +2610,7 @@ static void rna_def_keyconfig(BlenderRNA *brna)
/* RNA_def_property_enum_sdna(prop, NULL, "shift"); */
/* RNA_def_property_enum_items(prop, keymap_modifiers_items); */
RNA_def_property_ui_text(prop, "Shift", "Shift key pressed");
+ RNA_def_property_translation_context(prop, BLT_I18NCONTEXT_ID_WINDOWMANAGER);
RNA_def_property_update(prop, 0, "rna_KeyMapItem_update");
prop = RNA_def_property(srna, "ctrl", PROP_BOOLEAN, PROP_NONE);
diff --git a/source/blender/makesrna/intern/rna_wm_gizmo.c b/source/blender/makesrna/intern/rna_wm_gizmo.c
index a473f97d554..22162aa017b 100644
--- a/source/blender/makesrna/intern/rna_wm_gizmo.c
+++ b/source/blender/makesrna/intern/rna_wm_gizmo.c
@@ -384,6 +384,7 @@ static void rna_Gizmo_matrix_world_get(PointerRNA *ptr, float value[16])
RNA_GIZMO_GENERIC_FLOAT_RW_DEF(scale_basis, scale_basis);
RNA_GIZMO_GENERIC_FLOAT_RW_DEF(line_width, line_width);
+RNA_GIZMO_GENERIC_FLOAT_RW_DEF(select_bias, select_bias);
RNA_GIZMO_GENERIC_FLAG_RW_DEF(flag_use_draw_hover, flag, WM_GIZMO_DRAW_HOVER);
RNA_GIZMO_GENERIC_FLAG_RW_DEF(flag_use_draw_modal, flag, WM_GIZMO_DRAW_MODAL);
@@ -1159,6 +1160,12 @@ static void rna_def_gizmo(BlenderRNA *brna, PropertyRNA *cprop)
RNA_def_property_range(prop, 0.0f, FLT_MAX);
RNA_def_property_update(prop, NC_SCREEN | NA_EDITED, NULL);
+ prop = RNA_def_property(srna, "select_bias", PROP_FLOAT, PROP_NONE);
+ RNA_def_property_ui_text(prop, "Select Bias", "Depth bias used for selection");
+ RNA_def_property_float_funcs(
+ prop, "rna_Gizmo_select_bias_get", "rna_Gizmo_select_bias_set", NULL);
+ RNA_def_property_range(prop, -FLT_MAX, FLT_MAX);
+
/* wmGizmo.flag */
/* WM_GIZMO_HIDDEN */
prop = RNA_def_property(srna, "hide", PROP_BOOLEAN, PROP_NONE);
diff --git a/source/blender/modifiers/intern/MOD_multires.c b/source/blender/modifiers/intern/MOD_multires.c
index 6e5426bbf40..c61ebe0448c 100644
--- a/source/blender/modifiers/intern/MOD_multires.c
+++ b/source/blender/modifiers/intern/MOD_multires.c
@@ -195,7 +195,14 @@ static Mesh *applyModifier(ModifierData *md, const ModifierEvalContext *ctx, Mes
* Annoying and not so much black-boxed as far as sculpting goes, and
* surely there is a better way of solving this. */
if (ctx->object->sculpt != NULL) {
- ctx->object->sculpt->subdiv_ccg = result->runtime.subdiv_ccg;
+ SculptSession *sculpt_session = ctx->object->sculpt;
+ sculpt_session->subdiv_ccg = result->runtime.subdiv_ccg;
+ sculpt_session->multires = mmd;
+ sculpt_session->totvert = mesh->totvert;
+ sculpt_session->totpoly = mesh->totpoly;
+ sculpt_session->mvert = NULL;
+ sculpt_session->mpoly = NULL;
+ sculpt_session->mloop = NULL;
}
/* NOTE: CCG becomes an owner of Subdiv descriptor, so can not share
* this pointer. Not sure if it's needed, but might have a second look
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/node_shader_util.h b/source/blender/nodes/shader/node_shader_util.h
index 916cb81953e..a3c553b983b 100644
--- a/source/blender/nodes/shader/node_shader_util.h
+++ b/source/blender/nodes/shader/node_shader_util.h
@@ -60,13 +60,13 @@
#include "BLT_translation.h"
-#include "IMB_imbuf_types.h"
-#include "IMB_imbuf.h"
+#include "IMB_colormanagement.h"
#include "RE_pipeline.h"
#include "RE_shader_ext.h"
#include "GPU_material.h"
+#include "GPU_texture.h"
#include "GPU_uniformbuffer.h"
bool sh_node_poll_default(struct bNodeType *ntype, struct bNodeTree *ntree);
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 37c35c0adc8..6c3e082f36a 100644
--- a/source/blender/nodes/shader/nodes/node_shader_bsdf_principled.c
+++ b/source/blender/nodes/shader/nodes/node_shader_bsdf_principled.c
@@ -39,6 +39,8 @@ static bNodeSocketTemplate sh_node_bsdf_principled_in[] = {
{SOCK_FLOAT, 1, N_("IOR"), 1.45f, 0.0f, 0.0f, 0.0f, 0.0f, 1000.0f},
{SOCK_FLOAT, 1, N_("Transmission"), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, PROP_FACTOR},
{SOCK_FLOAT, 1, N_("Transmission Roughness"), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, PROP_FACTOR},
+ {SOCK_RGBA, 1, N_("Emission"), 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f},
+ {SOCK_FLOAT, 1, N_("Alpha"), 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, PROP_FACTOR},
{SOCK_VECTOR,
1,
N_("Normal"),
@@ -99,26 +101,25 @@ static int node_shader_gpu_bsdf_principled(GPUMaterial *mat,
GPUNodeLink *sss_scale;
/* Normals */
- if (!in[17].link) {
- GPU_link(mat, "world_normals_get", &in[17].link);
+ if (!in[19].link) {
+ GPU_link(mat, "world_normals_get", &in[19].link);
}
/* Clearcoat Normals */
- if (!in[18].link) {
- GPU_link(mat, "world_normals_get", &in[18].link);
+ if (!in[20].link) {
+ GPU_link(mat, "world_normals_get", &in[20].link);
}
/* Tangents */
- if (!in[19].link) {
+ if (!in[21].link) {
GPUNodeLink *orco = GPU_attribute(CD_ORCO, "");
- GPU_link(mat, "tangent_orco_z", orco, &in[19].link);
+ GPU_link(mat, "tangent_orco_z", orco, &in[21].link);
GPU_link(mat,
"node_tangent",
- GPU_builtin(GPU_VIEW_NORMAL),
- in[19].link,
+ GPU_builtin(GPU_WORLD_NORMAL),
+ in[21].link,
GPU_builtin(GPU_OBJECT_MATRIX),
- GPU_builtin(GPU_INVERSE_VIEW_MATRIX),
- &in[19].link);
+ &in[21].link);
}
/* SSS Profile */
diff --git a/source/blender/nodes/shader/nodes/node_shader_geometry.c b/source/blender/nodes/shader/nodes/node_shader_geometry.c
index 6f97efe9f73..df9a8ac8318 100644
--- a/source/blender/nodes/shader/nodes/node_shader_geometry.c
+++ b/source/blender/nodes/shader/nodes/node_shader_geometry.c
@@ -51,7 +51,7 @@ static int node_shader_gpu_geometry(GPUMaterial *mat,
in,
out,
GPU_builtin(GPU_VIEW_POSITION),
- GPU_builtin(GPU_VIEW_NORMAL),
+ GPU_builtin(GPU_WORLD_NORMAL),
GPU_attribute(CD_ORCO, ""),
GPU_builtin(GPU_OBJECT_MATRIX),
GPU_builtin(GPU_INVERSE_VIEW_MATRIX),
diff --git a/source/blender/nodes/shader/nodes/node_shader_normal_map.c b/source/blender/nodes/shader/nodes/node_shader_normal_map.c
index d769a219fa0..4976d038065 100644
--- a/source/blender/nodes/shader/nodes/node_shader_normal_map.c
+++ b/source/blender/nodes/shader/nodes/node_shader_normal_map.c
@@ -84,52 +84,33 @@ static int gpu_shader_normal_map(GPUMaterial *mat,
realnorm = GPU_constant(in[1].vec);
}
- negnorm = GPU_builtin(GPU_VIEW_NORMAL);
+ negnorm = GPU_builtin(GPU_WORLD_NORMAL);
GPU_link(mat, "math_max", strength, GPU_constant(d), &strength);
const char *color_to_normal_fnc_name = "color_to_normal_new_shading";
if (nm->space == SHD_SPACE_BLENDER_OBJECT || nm->space == SHD_SPACE_BLENDER_WORLD) {
color_to_normal_fnc_name = "color_to_blender_normal_new_shading";
}
+
+ GPU_link(mat, color_to_normal_fnc_name, realnorm, &realnorm);
switch (nm->space) {
case SHD_SPACE_TANGENT:
- GPU_link(mat, "color_to_normal_new_shading", realnorm, &realnorm);
GPU_link(mat,
"node_normal_map",
GPU_builtin(GPU_OBJECT_INFO),
GPU_attribute(CD_TANGENT, nm->uv_map),
- negnorm,
+ GPU_builtin(GPU_WORLD_NORMAL),
realnorm,
&realnorm);
- GPU_link(
- mat, "vec_math_mix", strength, realnorm, GPU_builtin(GPU_VIEW_NORMAL), &out[0].link);
- /* for uniform scale this is sufficient to match Cycles */
- GPU_link(mat,
- "direction_transform_m4v3",
- out[0].link,
- GPU_builtin(GPU_INVERSE_VIEW_MATRIX),
- &out[0].link);
- GPU_link(mat, "vect_normalize", out[0].link, &out[0].link);
- return true;
+ break;
case SHD_SPACE_OBJECT:
case SHD_SPACE_BLENDER_OBJECT:
- GPU_link(mat,
- "direction_transform_m4v3",
- negnorm,
- GPU_builtin(GPU_INVERSE_VIEW_MATRIX),
- &negnorm);
- GPU_link(mat, color_to_normal_fnc_name, realnorm, &realnorm);
GPU_link(
mat, "direction_transform_m4v3", realnorm, GPU_builtin(GPU_OBJECT_MATRIX), &realnorm);
break;
case SHD_SPACE_WORLD:
case SHD_SPACE_BLENDER_WORLD:
- GPU_link(mat,
- "direction_transform_m4v3",
- negnorm,
- GPU_builtin(GPU_INVERSE_VIEW_MATRIX),
- &negnorm);
- GPU_link(mat, color_to_normal_fnc_name, realnorm, &realnorm);
+ /* Nothing to do. */
break;
}
diff --git a/source/blender/nodes/shader/nodes/node_shader_object_info.c b/source/blender/nodes/shader/nodes/node_shader_object_info.c
index 5520f6f325f..118b8136693 100644
--- a/source/blender/nodes/shader/nodes/node_shader_object_info.c
+++ b/source/blender/nodes/shader/nodes/node_shader_object_info.c
@@ -35,13 +35,17 @@ static int node_shader_gpu_object_info(GPUMaterial *mat,
GPUNodeStack *in,
GPUNodeStack *out)
{
+ Material *ma = GPU_material_get_material(mat);
+ /* Convert to float. */
+ float index = ma ? ma->index : 0;
return GPU_stack_link(mat,
node,
"node_object_info",
in,
out,
GPU_builtin(GPU_OBJECT_MATRIX),
- GPU_builtin(GPU_OBJECT_INFO));
+ GPU_builtin(GPU_OBJECT_INFO),
+ GPU_constant(&index));
}
static void node_shader_exec_object_info(void *UNUSED(data),
diff --git a/source/blender/nodes/shader/nodes/node_shader_tangent.c b/source/blender/nodes/shader/nodes/node_shader_tangent.c
index 5512754d9a2..6795f48edb3 100644
--- a/source/blender/nodes/shader/nodes/node_shader_tangent.c
+++ b/source/blender/nodes/shader/nodes/node_shader_tangent.c
@@ -42,13 +42,7 @@ static int node_shader_gpu_tangent(GPUMaterial *mat,
NodeShaderTangent *attr = node->storage;
if (attr->direction_type == SHD_TANGENT_UVMAP) {
- return GPU_stack_link(mat,
- node,
- "node_tangentmap",
- in,
- out,
- GPU_attribute(CD_TANGENT, ""),
- GPU_builtin(GPU_INVERSE_VIEW_MATRIX));
+ return GPU_stack_link(mat, node, "node_tangentmap", in, out, GPU_attribute(CD_TANGENT, ""));
}
else {
GPUNodeLink *orco = GPU_attribute(CD_ORCO, "");
@@ -68,10 +62,9 @@ static int node_shader_gpu_tangent(GPUMaterial *mat,
"node_tangent",
in,
out,
- GPU_builtin(GPU_VIEW_NORMAL),
+ GPU_builtin(GPU_WORLD_NORMAL),
orco,
- GPU_builtin(GPU_OBJECT_MATRIX),
- GPU_builtin(GPU_INVERSE_VIEW_MATRIX));
+ GPU_builtin(GPU_OBJECT_MATRIX));
}
}
diff --git a/source/blender/nodes/shader/nodes/node_shader_tex_coord.c b/source/blender/nodes/shader/nodes/node_shader_tex_coord.c
index fd62e8ce960..0e34f2ca9b1 100644
--- a/source/blender/nodes/shader/nodes/node_shader_tex_coord.c
+++ b/source/blender/nodes/shader/nodes/node_shader_tex_coord.c
@@ -42,10 +42,6 @@ static int node_shader_gpu_tex_coord(GPUMaterial *mat,
{
Object *ob = (Object *)node->id;
- if (ob != NULL) {
- invert_m4_m4(ob->imat, ob->obmat);
- }
-
GPUNodeLink *inv_obmat = (ob != NULL) ? GPU_uniform(&ob->imat[0][0]) :
GPU_builtin(GPU_INVERSE_OBJECT_MATRIX);
@@ -60,8 +56,7 @@ static int node_shader_gpu_tex_coord(GPUMaterial *mat,
in,
out,
GPU_builtin(GPU_VIEW_POSITION),
- GPU_builtin(GPU_VIEW_NORMAL),
- GPU_builtin(GPU_INVERSE_VIEW_MATRIX),
+ GPU_builtin(GPU_WORLD_NORMAL),
inv_obmat,
GPU_builtin(GPU_CAMERA_TEXCO_FACTORS),
orco,
diff --git a/source/blender/nodes/shader/nodes/node_shader_tex_environment.c b/source/blender/nodes/shader/nodes/node_shader_tex_environment.c
index c3b8bc8bfd0..615f55e4350 100644
--- a/source/blender/nodes/shader/nodes/node_shader_tex_environment.c
+++ b/source/blender/nodes/shader/nodes/node_shader_tex_environment.c
@@ -46,7 +46,6 @@ static void node_shader_init_tex_environment(bNodeTree *UNUSED(ntree), bNode *no
NodeTexEnvironment *tex = MEM_callocN(sizeof(NodeTexEnvironment), "NodeTexEnvironment");
BKE_texture_mapping_default(&tex->base.tex_mapping, TEXMAP_TYPE_POINT);
BKE_texture_colormapping_default(&tex->base.color_mapping);
- tex->color_space = SHD_COLORSPACE_COLOR;
tex->projection = SHD_PROJ_EQUIRECTANGULAR;
BKE_imageuser_default(&tex->iuser);
@@ -68,7 +67,6 @@ static int node_shader_gpu_tex_environment(GPUMaterial *mat,
NodeTexImage *tex_original = node_original->storage;
ImageUser *iuser = &tex_original->iuser;
- int isdata = tex->color_space == SHD_COLORSPACE_NONE;
GPUNodeLink *outalpha;
if (!ima) {
@@ -89,7 +87,7 @@ static int node_shader_gpu_tex_environment(GPUMaterial *mat,
"node_tex_environment_equirectangular",
in[0].link,
GPU_constant(&clamp_size),
- GPU_image(ima, iuser, isdata),
+ GPU_image(ima, iuser),
&in[0].link);
}
else {
@@ -104,7 +102,7 @@ static int node_shader_gpu_tex_environment(GPUMaterial *mat,
GPU_link(mat,
"node_tex_image_linear_no_mip",
in[0].link,
- GPU_image(ima, iuser, isdata),
+ GPU_image(ima, iuser),
&out[0].link,
&outalpha);
break;
@@ -112,26 +110,19 @@ static int node_shader_gpu_tex_environment(GPUMaterial *mat,
GPU_link(mat,
"node_tex_image_nearest",
in[0].link,
- GPU_image(ima, iuser, isdata),
+ GPU_image(ima, iuser),
&out[0].link,
&outalpha);
break;
default:
- GPU_link(mat,
- "node_tex_image_cubic",
- in[0].link,
- GPU_image(ima, iuser, isdata),
- &out[0].link,
- &outalpha);
+ GPU_link(
+ mat, "node_tex_image_cubic", in[0].link, GPU_image(ima, iuser), &out[0].link, &outalpha);
break;
}
- ImBuf *ibuf = BKE_image_acquire_ibuf(ima, iuser, NULL);
- if (ibuf && (ibuf->colormanage_flag & IMB_COLORMANAGE_IS_DATA) == 0 &&
- GPU_material_do_color_management(mat)) {
- GPU_link(mat, "srgb_to_linearrgb", out[0].link, &out[0].link);
+ if (out[0].hasoutput) {
+ GPU_link(mat, "tex_color_alpha_clear", out[0].link, &out[0].link);
}
- BKE_image_release_ibuf(ima, ibuf, NULL);
return true;
}
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 91d58bc41d0..786386bb63e 100644
--- a/source/blender/nodes/shader/nodes/node_shader_tex_image.c
+++ b/source/blender/nodes/shader/nodes/node_shader_tex_image.c
@@ -57,7 +57,6 @@ static void node_shader_init_tex_image(bNodeTree *UNUSED(ntree), bNode *node)
NodeTexImage *tex = MEM_callocN(sizeof(NodeTexImage), "NodeTexImage");
BKE_texture_mapping_default(&tex->base.tex_mapping, TEXMAP_TYPE_POINT);
BKE_texture_colormapping_default(&tex->base.color_mapping);
- tex->color_space = SHD_COLORSPACE_COLOR;
BKE_imageuser_default(&tex->iuser);
node->storage = tex;
@@ -99,7 +98,6 @@ static int node_shader_gpu_tex_image(GPUMaterial *mat,
const char *gpu_node_name = (tex->projection == SHD_PROJ_BOX) ? names_box[tex->interpolation] :
names[tex->interpolation];
- bool do_color_correction = false;
bool do_texco_extend = (tex->extension != SHD_IMAGE_EXTENSION_REPEAT);
const bool do_texco_clip = (tex->extension == SHD_IMAGE_EXTENSION_CLIP);
@@ -111,23 +109,13 @@ static int node_shader_gpu_tex_image(GPUMaterial *mat,
}
GPUNodeLink *norm, *col1, *col2, *col3, *input_coords, *gpu_image;
- GPUNodeLink *vnor, *nor_mat_inv, *blend;
+ GPUNodeLink *vnor, *ob_mat, *blend;
GPUNodeLink **texco = &in[0].link;
- int isdata = tex->color_space == SHD_COLORSPACE_NONE;
-
if (!ima) {
return GPU_stack_link(mat, node, "node_tex_image_empty", in, out);
}
- ImBuf *ibuf = BKE_image_acquire_ibuf(ima, iuser, NULL);
- if ((tex->color_space == SHD_COLORSPACE_COLOR) && ibuf &&
- (ibuf->colormanage_flag & IMB_COLORMANAGE_IS_DATA) == 0 &&
- GPU_material_do_color_management(mat)) {
- do_color_correction = true;
- }
- BKE_image_release_ibuf(ima, ibuf, NULL);
-
if (!*texco) {
*texco = GPU_attribute(CD_MTFACE, "");
}
@@ -140,25 +128,20 @@ static int node_shader_gpu_tex_image(GPUMaterial *mat,
GPU_link(mat, "set_rgb", *texco, &input_coords);
}
if (do_texco_extend) {
- GPU_link(mat, "point_texco_clamp", *texco, GPU_image(ima, iuser, isdata), texco);
+ GPU_link(mat, "point_texco_clamp", *texco, GPU_image(ima, iuser), texco);
}
- GPU_stack_link(mat, node, gpu_node_name, in, out, GPU_image(ima, iuser, isdata));
+ GPU_stack_link(mat, node, gpu_node_name, in, out, GPU_image(ima, iuser));
break;
case SHD_PROJ_BOX:
- vnor = GPU_builtin(GPU_VIEW_NORMAL);
- nor_mat_inv = GPU_builtin(GPU_INVERSE_NORMAL_MATRIX);
+ vnor = GPU_builtin(GPU_WORLD_NORMAL);
+ ob_mat = GPU_builtin(GPU_OBJECT_MATRIX);
blend = GPU_uniform(&tex->projection_blend);
- gpu_image = GPU_image(ima, iuser, isdata);
-
- GPU_link(mat, "mat3_mul", vnor, nor_mat_inv, &norm);
- GPU_link(
- mat, gpu_node_name, *texco, norm, GPU_image(ima, iuser, isdata), &col1, &col2, &col3);
- if (do_color_correction) {
- GPU_link(mat, "srgb_to_linearrgb", col1, &col1);
- GPU_link(mat, "srgb_to_linearrgb", col2, &col2);
- GPU_link(mat, "srgb_to_linearrgb", col3, &col3);
- }
+ gpu_image = GPU_image(ima, iuser);
+
+ /* equivalent to normal_world_to_object */
+ GPU_link(mat, "normal_transform_transposed_m4v3", vnor, ob_mat, &norm);
+ GPU_link(mat, gpu_node_name, *texco, norm, GPU_image(ima, iuser), &col1, &col2, &col3);
GPU_stack_link(
mat, node, "node_tex_image_box", in, out, norm, col1, col2, col3, gpu_image, blend);
break;
@@ -170,9 +153,9 @@ static int node_shader_gpu_tex_image(GPUMaterial *mat,
GPU_link(mat, "set_rgb", *texco, &input_coords);
}
if (do_texco_extend) {
- GPU_link(mat, "point_texco_clamp", *texco, GPU_image(ima, iuser, isdata), texco);
+ GPU_link(mat, "point_texco_clamp", *texco, GPU_image(ima, iuser), texco);
}
- GPU_stack_link(mat, node, gpu_node_name, in, out, GPU_image(ima, iuser, isdata));
+ GPU_stack_link(mat, node, gpu_node_name, in, out, GPU_image(ima, iuser));
break;
case SHD_PROJ_TUBE:
@@ -182,20 +165,31 @@ static int node_shader_gpu_tex_image(GPUMaterial *mat,
GPU_link(mat, "set_rgb", *texco, &input_coords);
}
if (do_texco_extend) {
- GPU_link(mat, "point_texco_clamp", *texco, GPU_image(ima, iuser, isdata), texco);
+ GPU_link(mat, "point_texco_clamp", *texco, GPU_image(ima, iuser), texco);
}
- GPU_stack_link(mat, node, gpu_node_name, in, out, GPU_image(ima, iuser, isdata));
+ GPU_stack_link(mat, node, gpu_node_name, in, out, GPU_image(ima, iuser));
break;
}
if (tex->projection != SHD_PROJ_BOX) {
if (do_texco_clip) {
gpu_node_name = names_clip[tex->interpolation];
- GPU_stack_link(
- mat, node, gpu_node_name, in, out, GPU_image(ima, iuser, isdata), out[0].link);
+ in[0].link = input_coords;
+ GPU_stack_link(mat, node, gpu_node_name, in, out, GPU_image(ima, iuser), out[0].link);
+ }
+ }
+
+ 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 &&
+ !(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);
}
- if (do_color_correction) {
- GPU_link(mat, "srgb_to_linearrgb", out[0].link, &out[0].link);
+ else {
+ GPU_link(mat, "tex_color_alpha_clear", out[0].link, &out[0].link);
}
}
diff --git a/source/blender/nodes/shader/nodes/node_shader_vector_displacement.c b/source/blender/nodes/shader/nodes/node_shader_vector_displacement.c
index cbc012040b0..ac8b49c4572 100644
--- a/source/blender/nodes/shader/nodes/node_shader_vector_displacement.c
+++ b/source/blender/nodes/shader/nodes/node_shader_vector_displacement.c
@@ -61,7 +61,7 @@ static int gpu_shader_vector_displacement(GPUMaterial *mat,
in,
out,
GPU_attribute(CD_TANGENT, ""),
- GPU_builtin(GPU_VIEW_NORMAL),
+ GPU_builtin(GPU_WORLD_NORMAL),
GPU_builtin(GPU_OBJECT_MATRIX),
GPU_builtin(GPU_VIEW_MATRIX));
}
diff --git a/source/blender/python/generic/idprop_py_api.c b/source/blender/python/generic/idprop_py_api.c
index dd5baaa661c..30cad991b55 100644
--- a/source/blender/python/generic/idprop_py_api.c
+++ b/source/blender/python/generic/idprop_py_api.c
@@ -601,7 +601,6 @@ static IDProperty *idp_from_PyMapping(const char *name, PyObject *ob)
pval = PySequence_GetItem(vals, i);
if (BPy_IDProperty_Map_ValidateAndCreate(key, prop, pval) == false) {
IDP_FreeProperty(prop);
- MEM_freeN(prop);
Py_XDECREF(keys);
Py_XDECREF(vals);
Py_XDECREF(key);
@@ -690,7 +689,7 @@ bool BPy_IDProperty_Map_ValidateAndCreate(PyObject *name_obj, IDProperty *group,
prop->prev = prop_exist->prev;
prop->next = prop_exist->next;
- IDP_FreeProperty(prop_exist);
+ IDP_FreePropertyContent(prop_exist);
*prop_exist = *prop;
MEM_freeN(prop);
}
diff --git a/source/blender/python/gpu/gpu_py_offscreen.c b/source/blender/python/gpu/gpu_py_offscreen.c
index 5ea747b5cdc..561aff41000 100644
--- a/source/blender/python/gpu/gpu_py_offscreen.c
+++ b/source/blender/python/gpu/gpu_py_offscreen.c
@@ -256,7 +256,6 @@ static PyObject *bpygpu_offscreen_draw_view3d(BPyGPUOffScreen *self,
false,
true,
"",
- NULL,
true,
self->ofs,
NULL);
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 a87deeabc65..092c9061bb7 100644
--- a/source/blender/python/intern/bpy_rna.c
+++ b/source/blender/python/intern/bpy_rna.c
@@ -1122,7 +1122,6 @@ static void pyrna_struct_dealloc(BPy_StructRNA *self)
#ifdef PYRNA_FREE_SUPPORT
if (self->freeptr && self->ptr.data) {
IDP_FreeProperty(self->ptr.data);
- MEM_freeN(self->ptr.data);
self->ptr.data = NULL;
}
#endif /* PYRNA_FREE_SUPPORT */
@@ -2030,7 +2029,15 @@ static int pyrna_py_to_prop(
else {
/* data == NULL, assign to RNA */
if (value == Py_None || RNA_struct_is_a(param->ptr.type, ptr_type)) {
- RNA_property_pointer_set(ptr, prop, value == Py_None ? PointerRNA_NULL : param->ptr);
+ ReportList reports;
+ BKE_reports_init(&reports, RPT_STORE);
+ RNA_property_pointer_set(
+ 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);
+ return -1;
+ }
}
else {
raise_error = true;
diff --git a/source/blender/python/intern/bpy_rna_anim.c b/source/blender/python/intern/bpy_rna_anim.c
index 79c31c8caad..710ae0433e0 100644
--- a/source/blender/python/intern/bpy_rna_anim.c
+++ b/source/blender/python/intern/bpy_rna_anim.c
@@ -263,8 +263,9 @@ static int pyrna_struct_keyframe_parse(PointerRNA *ptr,
/* flag may be null (no option currently for remove keyframes e.g.). */
if (r_options) {
- if (pyoptions && (pyrna_set_to_enum_bitfield(
- rna_enum_keying_flag_items, pyoptions, r_options, error_prefix) == -1)) {
+ if (pyoptions &&
+ (pyrna_set_to_enum_bitfield(
+ rna_enum_keying_flag_items_api, pyoptions, r_options, error_prefix) == -1)) {
return -1;
}
@@ -299,8 +300,11 @@ char pyrna_struct_keyframe_insert_doc[] =
"F-Curves.\n"
" - ``INSERTKEY_VISUAL`` Insert keyframes based on 'visual transforms'.\n"
" - ``INSERTKEY_XYZ_TO_RGB`` Color for newly added transformation F-Curves (Location, "
- "Rotation, Scale)\n"
- " and also Color is based on the transform axis.\n"
+ "Rotation, Scale) is based on the transform axis.\n"
+ " - ``INSERTKEY_REPLACE`` Only replace already exising keyframes.\n"
+ " - ``INSERTKEY_AVAILABLE`` Only insert into already existing F-Curves.\n"
+ " - ``INSERTKEY_CYCLE_AWARE`` Take cyclic extrapolation into account "
+ "(Cycle-Aware Keying option).\n"
" :type flag: set\n"
" :return: Success of keyframe insertion.\n"
" :rtype: boolean\n";
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/extern/include/RE_engine.h b/source/blender/render/extern/include/RE_engine.h
index 1092ab553e9..4f51f9874f8 100644
--- a/source/blender/render/extern/include/RE_engine.h
+++ b/source/blender/render/extern/include/RE_engine.h
@@ -93,8 +93,12 @@ typedef struct RenderEngineType {
const int depth,
void *result);
- void (*view_update)(struct RenderEngine *engine, const struct bContext *context);
- void (*view_draw)(struct RenderEngine *engine, const struct bContext *context);
+ void (*view_update)(struct RenderEngine *engine,
+ const struct bContext *context,
+ struct Depsgraph *depsgraph);
+ void (*view_draw)(struct RenderEngine *engine,
+ const struct bContext *context,
+ struct Depsgraph *depsgraph);
void (*update_script_node)(struct RenderEngine *engine,
struct bNodeTree *ntree,
diff --git a/source/blender/render/extern/include/RE_pipeline.h b/source/blender/render/extern/include/RE_pipeline.h
index 46d2df0acb5..db051d58d6c 100644
--- a/source/blender/render/extern/include/RE_pipeline.h
+++ b/source/blender/render/extern/include/RE_pipeline.h
@@ -284,21 +284,21 @@ bool RE_WriteRenderViewsMovie(struct ReportList *reports,
bool preview);
/* only RE_NewRender() needed, main Blender render calls */
-void RE_BlenderFrame(struct Render *re,
- struct Main *bmain,
- struct Scene *scene,
- struct ViewLayer *single_layer,
- struct Object *camera_override,
- int frame,
- const bool write_still);
-void RE_BlenderAnim(struct Render *re,
+void RE_RenderFrame(struct Render *re,
struct Main *bmain,
struct Scene *scene,
struct ViewLayer *single_layer,
struct Object *camera_override,
- int sfra,
- int efra,
- int tfra);
+ int frame,
+ const bool write_still);
+void RE_RenderAnim(struct Render *re,
+ struct Main *bmain,
+ struct Scene *scene,
+ struct ViewLayer *single_layer,
+ struct Object *camera_override,
+ int sfra,
+ int efra,
+ int tfra);
#ifdef WITH_FREESTYLE
void RE_RenderFreestyleStrokes(struct Render *re,
struct Main *bmain,
@@ -307,6 +307,9 @@ void RE_RenderFreestyleStrokes(struct Render *re,
void RE_RenderFreestyleExternal(struct Render *re);
#endif
+/* Free memory and clear runtime data which is only needed during rendering. */
+void RE_CleanAfterRender(struct Render *re);
+
void RE_SetActiveRenderView(struct Render *re, const char *viewname);
const char *RE_GetActiveRenderView(struct Render *re);
diff --git a/source/blender/render/intern/include/render_types.h b/source/blender/render/intern/include/render_types.h
index 63fd3f1d0bd..e4a2afa4349 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,7 +113,7 @@ struct Render {
struct Object *camera_override;
ThreadRWMutex partsmutex;
- ListBase parts;
+ struct GHash *parts;
/* render engine */
struct RenderEngine *engine;
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/multires_bake.c b/source/blender/render/intern/source/multires_bake.c
index 237debceb83..878a774ab37 100644
--- a/source/blender/render/intern/source/multires_bake.c
+++ b/source/blender/render/intern/source/multires_bake.c
@@ -1458,7 +1458,8 @@ static void finish_images(MultiresBakeRender *bkr, MultiresBakeResult *result)
bake_ibuf_filter(ibuf, userdata->mask_buffer, bkr->bake_filter);
- ibuf->userflags |= IB_BITMAPDIRTY | IB_DISPLAY_BUFFER_INVALID;
+ ibuf->userflags |= IB_DISPLAY_BUFFER_INVALID;
+ BKE_image_mark_dirty(ima, ibuf);
if (ibuf->rect_float) {
ibuf->userflags |= IB_RECT_INVALID;
diff --git a/source/blender/render/intern/source/pipeline.c b/source/blender/render/intern/source/pipeline.c
index 7d3002ea71d..9c1c713ab94 100644
--- a/source/blender/render/intern/source/pipeline.c
+++ b/source/blender/render/intern/source/pipeline.c
@@ -1988,7 +1988,7 @@ const char *RE_GetActiveRenderView(Render *re)
/* evaluating scene options for general Blender render */
static int render_initialize_from_main(Render *re,
- RenderData *rd,
+ const RenderData *rd,
Main *bmain,
Scene *scene,
ViewLayer *single_layer,
@@ -2072,13 +2072,13 @@ void RE_SetReports(Render *re, ReportList *reports)
}
/* general Blender frame render call */
-void RE_BlenderFrame(Render *re,
- Main *bmain,
- Scene *scene,
- ViewLayer *single_layer,
- Object *camera_override,
- int frame,
- const bool write_still)
+void RE_RenderFrame(Render *re,
+ Main *bmain,
+ Scene *scene,
+ ViewLayer *single_layer,
+ Object *camera_override,
+ int frame,
+ const bool write_still)
{
BLI_callback_exec(re->main, (ID *)scene, BLI_CB_EVT_RENDER_INIT);
@@ -2090,6 +2090,7 @@ void RE_BlenderFrame(Render *re,
if (render_initialize_from_main(
re, &scene->r, bmain, scene, single_layer, camera_override, 0, 0)) {
+ const RenderData rd = scene->r;
MEM_reset_peak_memory();
BLI_callback_exec(re->main, (ID *)scene, BLI_CB_EVT_RENDER_PRE);
@@ -2097,18 +2098,18 @@ void RE_BlenderFrame(Render *re,
do_render_all_options(re);
if (write_still && !G.is_break) {
- if (BKE_imtype_is_movie(scene->r.im_format.imtype)) {
+ if (BKE_imtype_is_movie(rd.im_format.imtype)) {
/* operator checks this but in case its called from elsewhere */
printf("Error: cant write single images with a movie format!\n");
}
else {
char name[FILE_MAX];
BKE_image_path_from_imformat(name,
- scene->r.pic,
+ rd.pic,
BKE_main_blendfile_path(bmain),
scene->r.cfra,
- &scene->r.im_format,
- (scene->r.scemode & R_EXTENSION) != 0,
+ &rd.im_format,
+ (rd.scemode & R_EXTENSION) != 0,
false,
NULL);
@@ -2117,7 +2118,8 @@ void RE_BlenderFrame(Render *re,
}
}
- BLI_callback_exec(re->main, (ID *)scene, BLI_CB_EVT_RENDER_POST); /* keep after file save */
+ /* keep after file save */
+ BLI_callback_exec(re->main, (ID *)scene, BLI_CB_EVT_RENDER_POST);
if (write_still) {
BLI_callback_exec(re->main, (ID *)scene, BLI_CB_EVT_RENDER_WRITE);
}
@@ -2126,8 +2128,7 @@ void RE_BlenderFrame(Render *re,
BLI_callback_exec(
re->main, (ID *)scene, G.is_break ? BLI_CB_EVT_RENDER_CANCEL : BLI_CB_EVT_RENDER_COMPLETE);
- /* Destroy the opengl context in the correct thread. */
- RE_gl_context_destroy(re);
+ RE_CleanAfterRender(re);
/* UGLY WARNING */
G.is_rendering = false;
@@ -2427,7 +2428,10 @@ static int do_write_image_or_movie(Render *re,
return ok;
}
-static void get_videos_dimensions(Render *re, RenderData *rd, size_t *r_width, size_t *r_height)
+static void get_videos_dimensions(const Render *re,
+ const RenderData *rd,
+ size_t *r_width,
+ size_t *r_height)
{
size_t width, height;
if (re->r.mode & R_BORDER) {
@@ -2461,23 +2465,23 @@ static void re_movie_free_all(Render *re, bMovieHandle *mh, int totvideos)
}
/* saves images to disk */
-void RE_BlenderAnim(Render *re,
- Main *bmain,
- Scene *scene,
- ViewLayer *single_layer,
- Object *camera_override,
- int sfra,
- int efra,
- int tfra)
-{
- RenderData rd = scene->r;
+void RE_RenderAnim(Render *re,
+ Main *bmain,
+ Scene *scene,
+ ViewLayer *single_layer,
+ Object *camera_override,
+ int sfra,
+ int efra,
+ int tfra)
+{
+ const RenderData rd = scene->r;
bMovieHandle *mh = NULL;
- int cfrao = scene->r.cfra;
+ const int cfrao = rd.cfra;
int nfra, totrendered = 0, totskipped = 0;
const int totvideos = BKE_scene_multiview_num_videos_get(&rd);
- const bool is_movie = BKE_imtype_is_movie(scene->r.im_format.imtype);
- const bool is_multiview_name = ((scene->r.scemode & R_MULTIVIEW) != 0 &&
- (scene->r.im_format.views_format == R_IMF_VIEWS_INDIVIDUAL));
+ const bool is_movie = BKE_imtype_is_movie(rd.im_format.imtype);
+ const bool is_multiview_name = ((rd.scemode & R_MULTIVIEW) != 0 &&
+ (rd.im_format.views_format == R_IMF_VIEWS_INDIVIDUAL));
BLI_callback_exec(re->main, (ID *)scene, BLI_CB_EVT_RENDER_INIT);
@@ -2493,7 +2497,7 @@ void RE_BlenderAnim(Render *re,
get_videos_dimensions(re, &rd, &width, &height);
- mh = BKE_movie_handle_get(scene->r.im_format.imtype);
+ mh = BKE_movie_handle_get(rd.im_format.imtype);
if (mh == NULL) {
BKE_report(re->reports, RPT_ERROR, "Movie format unsupported");
return;
@@ -2530,23 +2534,6 @@ void RE_BlenderAnim(Render *re,
for (nfra = sfra, scene->r.cfra = sfra; scene->r.cfra <= efra; scene->r.cfra++) {
char name[FILE_MAX];
- /* Special case for 'mh->get_next_frame'
- * this overrides regular frame stepping logic */
- if (mh && mh->get_next_frame) {
- while (G.is_break == false) {
- int nfra_test = mh->get_next_frame(re->movie_ctx_arr[0], &re->r, re->reports);
- if (nfra_test >= 0 && nfra_test >= sfra && nfra_test <= efra) {
- nfra = nfra_test;
- break;
- }
- else {
- if (re->test_break(re->tbh)) {
- G.is_break = true;
- }
- }
- }
- }
-
/* Here is a feedback loop exists -- render initialization requires updated
* render layers settings which could be animated, but scene evaluation for
* the frame happens later because it depends on what layers are visible to
@@ -2582,18 +2569,18 @@ void RE_BlenderAnim(Render *re,
/* Touch/NoOverwrite options are only valid for image's */
if (is_movie == false) {
- if (scene->r.mode & (R_NO_OVERWRITE | R_TOUCH)) {
+ if (rd.mode & (R_NO_OVERWRITE | R_TOUCH)) {
BKE_image_path_from_imformat(name,
- scene->r.pic,
+ rd.pic,
BKE_main_blendfile_path(bmain),
scene->r.cfra,
- &scene->r.im_format,
- (scene->r.scemode & R_EXTENSION) != 0,
+ &rd.im_format,
+ (rd.scemode & R_EXTENSION) != 0,
true,
NULL);
}
- if (scene->r.mode & R_NO_OVERWRITE) {
+ if (rd.mode & R_NO_OVERWRITE) {
if (!is_multiview_name) {
if (BLI_exists(name)) {
printf("skipping existing frame \"%s\"\n", name);
@@ -2626,7 +2613,7 @@ void RE_BlenderAnim(Render *re,
}
}
- if (scene->r.mode & R_TOUCH) {
+ if (rd.mode & R_TOUCH) {
if (!is_multiview_name) {
if (!BLI_exists(name)) {
BLI_make_existing_file(name); /* makes the dir if its not there */
@@ -2675,7 +2662,7 @@ void RE_BlenderAnim(Render *re,
if (G.is_break == true) {
/* remove touched file */
if (is_movie == false) {
- if ((scene->r.mode & R_TOUCH)) {
+ if ((rd.mode & R_TOUCH)) {
if (!is_multiview_name) {
if ((BLI_file_size(name) == 0)) {
/* BLI_exists(name) is implicit */
@@ -2706,8 +2693,8 @@ void RE_BlenderAnim(Render *re,
}
if (G.is_break == false) {
- BLI_callback_exec(
- re->main, (ID *)scene, BLI_CB_EVT_RENDER_POST); /* keep after file save */
+ /* keep after file save */
+ BLI_callback_exec(re->main, (ID *)scene, BLI_CB_EVT_RENDER_POST);
BLI_callback_exec(re->main, (ID *)scene, BLI_CB_EVT_RENDER_WRITE);
}
}
@@ -2730,8 +2717,7 @@ void RE_BlenderAnim(Render *re,
re->main, (ID *)scene, G.is_break ? BLI_CB_EVT_RENDER_CANCEL : BLI_CB_EVT_RENDER_COMPLETE);
BKE_sound_reset_scene_specs(scene);
- /* Destroy the opengl context in the correct thread. */
- RE_gl_context_destroy(re);
+ RE_CleanAfterRender(re);
/* UGLY WARNING */
G.is_rendering = false;
@@ -2756,6 +2742,12 @@ void RE_PreviewRender(Render *re, Main *bmain, Scene *sce)
do_render_3d(re);
}
+void RE_CleanAfterRender(Render *re)
+{
+ /* Destroy the opengl context in the correct thread. */
+ RE_gl_context_destroy(re);
+}
+
/* note; repeated win/disprect calc... solve that nicer, also in compo */
/* only the temp file! */
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 f1037dadf85..4a7953d7a24 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;
@@ -373,7 +374,8 @@ int WM_operator_confirm_message_ex(struct bContext *C,
struct wmOperator *op,
const char *title,
const int icon,
- const char *message);
+ const char *message,
+ const short opcontext);
int WM_operator_confirm_message(struct bContext *C, struct wmOperator *op, const char *message);
/* operator api */
@@ -400,6 +402,10 @@ int WM_operator_name_call(struct bContext *C,
const char *opstring,
short context,
struct PointerRNA *properties);
+int WM_operator_name_call_with_properties(struct bContext *C,
+ const char *opstring,
+ short context,
+ struct IDProperty *properties);
int WM_operator_call_py(struct bContext *C,
struct wmOperatorType *ot,
short context,
@@ -660,6 +666,7 @@ enum {
WM_JOB_TYPE_SHADER_COMPILATION,
WM_JOB_TYPE_STUDIOLIGHT,
WM_JOB_TYPE_LIGHT_BAKE,
+ WM_JOB_TYPE_FSMENU_BOOKMARK_VALIDATE,
/* add as needed, screencast, seq proxy build
* if having hard coded values is a problem */
};
@@ -789,6 +796,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_types.h b/source/blender/windowmanager/WM_types.h
index 154c4837a68..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 ************************ */
@@ -605,7 +617,7 @@ typedef struct wmOperatorType {
* that the operator might still fail to execute even if this return true */
bool (*poll)(struct bContext *) ATTR_WARN_UNUSED_RESULT;
- /* Use to check of properties should be displayed in auto-generated UI.
+ /* Use to check if properties should be displayed in auto-generated UI.
* Use 'check' callback to enforce refreshing. */
bool (*poll_property)(const struct bContext *C,
struct wmOperator *op,
diff --git a/source/blender/windowmanager/gizmo/WM_gizmo_types.h b/source/blender/windowmanager/gizmo/WM_gizmo_types.h
index 1c298f378a4..7d38194db1b 100644
--- a/source/blender/windowmanager/gizmo/WM_gizmo_types.h
+++ b/source/blender/windowmanager/gizmo/WM_gizmo_types.h
@@ -198,6 +198,10 @@ struct wmGizmo {
/** For single click button gizmos, use a different part as a fallback, -1 when unused. */
int drag_part;
+ /** Distance to bias this gizmo above others when picking
+ * (in worldspace, scaled by the gizmo scale - when used). */
+ float select_bias;
+
/**
* Transformation of the gizmo in 2d or 3d space.
* - Matrix axis are expected to be unit length (scale is applied after).
diff --git a/source/blender/windowmanager/gizmo/intern/wm_gizmo.c b/source/blender/windowmanager/gizmo/intern/wm_gizmo.c
index e2e5096ef99..b05865aa7bb 100644
--- a/source/blender/windowmanager/gizmo/intern/wm_gizmo.c
+++ b/source/blender/windowmanager/gizmo/intern/wm_gizmo.c
@@ -754,7 +754,6 @@ void WM_gizmo_properties_free(PointerRNA *ptr)
if (properties) {
IDP_FreeProperty(properties);
- MEM_freeN(properties);
ptr->data = NULL; /* just in case */
}
}
diff --git a/source/blender/windowmanager/gizmo/intern/wm_gizmo_map.c b/source/blender/windowmanager/gizmo/intern/wm_gizmo_map.c
index 31c5e1fb94c..9f36af8b616 100644
--- a/source/blender/windowmanager/gizmo/intern/wm_gizmo_map.c
+++ b/source/blender/windowmanager/gizmo/intern/wm_gizmo_map.c
@@ -25,8 +25,10 @@
#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,7 +472,8 @@ void WM_gizmomap_draw(wmGizmoMap *gzmap,
static void gizmo_draw_select_3D_loop(const bContext *C,
ListBase *visible_gizmos,
- const wmGizmo *gz_stop)
+ const wmGizmo *gz_stop,
+ bool *r_use_select_bias)
{
int select_id = 0;
wmGizmo *gz;
@@ -511,6 +514,10 @@ static void gizmo_draw_select_3D_loop(const bContext *C,
is_depth_skip_prev = is_depth_skip;
}
+ if (gz->select_bias != 0.0) {
+ *r_use_select_bias = true;
+ }
+
/* pass the selection id shifted by 8 bits. Last 8 bits are used for selected gizmo part id */
gz->type->draw_select(C, gz, select_id << 8);
@@ -543,24 +550,68 @@ static int gizmo_find_intersected_3d_intern(ListBase *visible_gizmos,
ED_view3d_draw_setup_view(
CTX_wm_window(C), CTX_data_depsgraph(C), CTX_data_scene(C), ar, v3d, NULL, NULL, &rect);
+ bool use_select_bias = false;
+
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);
+ gizmo_draw_select_3D_loop(C, visible_gizmos, gz_stop, &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);
+ gizmo_draw_select_3D_loop(C, visible_gizmos, gz_stop, &use_select_bias);
GPU_select_end();
}
ED_view3d_draw_setup_view(
CTX_wm_window(C), CTX_data_depsgraph(C), CTX_data_scene(C), ar, v3d, NULL, NULL, NULL);
- const GLuint *hit_near = GPU_select_buffer_near(buffer, hits);
-
- return hit_near ? hit_near[3] : -1;
+ 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);
+
+ RegionView3D *rv3d = ar->regiondata;
+ const int viewport[4] = {0, 0, ar->winx, ar->winy};
+ float co_3d_origin[3];
+
+ GPU_matrix_unproject_model_inverted(
+ co_screen, rv3d->viewinv, rv3d->winmat, viewport, co_3d_origin);
+
+ GLuint *buf_iter = buffer;
+ int hit_found = -1;
+ float dot_best = FLT_MAX;
+
+ for (int i = 0; i < hits; i++, buf_iter += 4) {
+ BLI_assert(buf_iter[3] != -1);
+ wmGizmo *gz = gizmo_table[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);
+ float select_bias = gz->select_bias;
+ if ((gz->flag & WM_GIZMO_DRAW_NO_SCALE) == 0) {
+ select_bias *= gz->scale_final;
+ }
+ sub_v3_v3(co_3d, co_3d_origin);
+ const float dot_test = dot_v3v3(co_3d, co_direction) - select_bias;
+ if (dot_best > dot_test) {
+ dot_best = dot_test;
+ hit_found = buf_iter[3];
+ }
+ }
+ BLI_array_free(gizmo_table);
+ return hit_found;
+ }
+ else {
+ const GLuint *hit_near = GPU_select_buffer_near(buffer, hits);
+ return hit_near ? hit_near[3] : -1;
+ }
}
/**
diff --git a/source/blender/windowmanager/intern/wm.c b/source/blender/windowmanager/intern/wm.c
index 7647e9f558f..77e17ad4687 100644
--- a/source/blender/windowmanager/intern/wm.c
+++ b/source/blender/windowmanager/intern/wm.c
@@ -82,7 +82,6 @@ void WM_operator_free(wmOperator *op)
if (op->properties) {
IDP_FreeProperty(op->properties);
- MEM_freeN(op->properties);
}
if (op->reports && (op->reports->flag & RPT_FREE)) {
diff --git a/source/blender/windowmanager/intern/wm_dragdrop.c b/source/blender/windowmanager/intern/wm_dragdrop.c
index 30311d83509..e4ecf7e6e94 100644
--- a/source/blender/windowmanager/intern/wm_dragdrop.c
+++ b/source/blender/windowmanager/intern/wm_dragdrop.c
@@ -442,7 +442,7 @@ void wm_drags_draw(bContext *C, wmWindow *win, rcti *rect)
drag_rect_minmax(rect, x, y, x + iconsize, y + iconsize);
}
else {
- UI_icon_draw_aspect(x, y, drag->icon, 1.0f / UI_DPI_FAC, 0.8, text_col);
+ UI_icon_draw_ex(x, y, drag->icon, U.inv_dpi_fac, 0.8, 0.0f, text_col, false);
}
}
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 13b6260e2b9..6683085e6d3 100644
--- a/source/blender/windowmanager/intern/wm_event_system.c
+++ b/source/blender/windowmanager/intern/wm_event_system.c
@@ -1293,7 +1293,6 @@ static bool operator_last_properties_init_impl(wmOperator *op, IDProperty *last_
IDP_MergeGroup(op->properties, replaceprops, true);
IDP_FreeProperty(replaceprops);
- MEM_freeN(replaceprops);
return changed;
}
@@ -1316,7 +1315,6 @@ bool WM_operator_last_properties_store(wmOperator *op)
{
if (op->type->last_properties) {
IDP_FreeProperty(op->type->last_properties);
- MEM_freeN(op->type->last_properties);
op->type->last_properties = NULL;
}
@@ -1680,6 +1678,17 @@ int WM_operator_name_call(bContext *C, const char *opstring, short context, Poin
return 0;
}
+int WM_operator_name_call_with_properties(struct bContext *C,
+ const char *opstring,
+ short context,
+ struct IDProperty *properties)
+{
+ PointerRNA props_ptr;
+ wmOperatorType *ot = WM_operatortype_find(opstring, false);
+ RNA_pointer_create(NULL, ot->srna, properties, &props_ptr);
+ return WM_operator_name_call_ptr(C, ot, context, &props_ptr);
+}
+
/**
* Call an existent menu. The menu can be created in C or Python.
*/
diff --git a/source/blender/windowmanager/intern/wm_files.c b/source/blender/windowmanager/intern/wm_files.c
index 6d90d4745a6..097db49aea6 100644
--- a/source/blender/windowmanager/intern/wm_files.c
+++ b/source/blender/windowmanager/intern/wm_files.c
@@ -76,6 +76,7 @@
#include "BKE_blender_undo.h"
#include "BKE_context.h"
#include "BKE_global.h"
+#include "BKE_idprop.h"
#include "BKE_main.h"
#include "BKE_packedFile.h"
#include "BKE_report.h"
@@ -98,6 +99,7 @@
#include "ED_datafiles.h"
#include "ED_fileselect.h"
+#include "ED_image.h"
#include "ED_screen.h"
#include "ED_view3d.h"
#include "ED_util.h"
@@ -488,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 */
@@ -513,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);
+ }
+ }
+
+ 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);
+ }
}
- /* 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) {
+ 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 */
@@ -555,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);
+ }
}
}
@@ -600,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;
@@ -638,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) {
@@ -646,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;
}
@@ -716,26 +743,6 @@ const char *WM_init_state_app_template_get(void)
return wm_init_state_app_template.override ? wm_init_state_app_template.app_template : NULL;
}
-static bool wm_app_template_has_userpref(const char *app_template)
-{
- /* Test if app template provides a userpref.blend. If not, we will
- * share user preferences with the rest of Blender. */
- if (!app_template && app_template[0]) {
- return false;
- }
-
- char app_template_path[FILE_MAX];
- if (!BKE_appdir_app_template_id_search(
- app_template, app_template_path, sizeof(app_template_path))) {
- return false;
- }
-
- char userpref_path[FILE_MAX];
- BLI_path_join(
- userpref_path, sizeof(userpref_path), app_template_path, BLENDER_USERPREF_FILE, NULL);
- return BLI_exists(userpref_path);
-}
-
/**
* Called on startup, (context entirely filled with NULLs)
* or called for 'New File' both startup.blend and userpref.blend are checked.
@@ -758,6 +765,7 @@ void wm_homefile_read(bContext *C,
ReportList *reports,
bool use_factory_settings,
bool use_empty_data,
+ bool use_data,
bool use_userdef,
const char *filepath_startup_override,
const char *app_template_override,
@@ -788,7 +796,14 @@ void wm_homefile_read(bContext *C,
* And in this case versioning code is to be run.
*/
bool read_userdef_from_memory = false;
- eBLOReadSkip skip_flags = use_userdef ? 0 : BLO_READ_SKIP_USERDEF;
+ eBLOReadSkip skip_flags = 0;
+
+ if (use_data == false) {
+ skip_flags |= BLO_READ_SKIP_DATA;
+ }
+ if (use_userdef == false) {
+ skip_flags |= BLO_READ_SKIP_USERDEF;
+ }
/* True if we load startup.blend from memory
* or use app-template startup.blend which the user hasn't saved. */
@@ -801,14 +816,16 @@ void wm_homefile_read(bContext *C,
SET_FLAG_FROM_TEST(G.f, (U.flag & USER_SCRIPT_AUTOEXEC_DISABLE) == 0, G_FLAG_SCRIPT_AUTOEXEC);
}
- BLI_callback_exec(CTX_data_main(C), NULL, BLI_CB_EVT_LOAD_PRE);
+ if (use_data) {
+ BLI_callback_exec(CTX_data_main(C), NULL, BLI_CB_EVT_LOAD_PRE);
- UI_view2d_zoom_cache_reset();
+ G.relbase_valid = 0;
- G.relbase_valid = 0;
+ /* put aside screens to match with persistent windows later */
+ wm_window_match_init(C, &wmbase);
+ }
- /* put aside screens to match with persistent windows later */
- wm_window_match_init(C, &wmbase);
+ UI_view2d_zoom_cache_reset();
filepath_startup[0] = '\0';
filepath_userdef[0] = '\0';
@@ -931,7 +948,9 @@ void wm_homefile_read(bContext *C,
}
if (success) {
if (update_defaults) {
- BLO_update_defaults_startup_blend(CTX_data_main(C), app_template);
+ if (use_data) {
+ BLO_update_defaults_startup_blend(CTX_data_main(C), app_template);
+ }
}
is_factory_startup = filepath_startup_is_factory;
}
@@ -1010,10 +1029,12 @@ void wm_homefile_read(bContext *C,
BLI_strncpy(U.app_template, app_template_override, sizeof(U.app_template));
}
- /* Prevent buggy files that had G_FILE_RELATIVE_REMAP written out by mistake.
- * Screws up autosaves otherwise can remove this eventually,
- * only in a 2.53 and older, now its not written. */
- G.fileflags &= ~G_FILE_RELATIVE_REMAP;
+ if (use_data) {
+ /* Prevent buggy files that had G_FILE_RELATIVE_REMAP written out by mistake.
+ * Screws up autosaves otherwise can remove this eventually,
+ * only in a 2.53 and older, now its not written. */
+ G.fileflags &= ~G_FILE_RELATIVE_REMAP;
+ }
bmain = CTX_data_main(C);
@@ -1023,8 +1044,10 @@ void wm_homefile_read(bContext *C,
reset_app_template = true;
}
- /* match the read WM with current WM */
- wm_window_match_do(C, &wmbase, &bmain->wm, &bmain->wm);
+ if (use_data) {
+ /* match the read WM with current WM */
+ wm_window_match_do(C, &wmbase, &bmain->wm, &bmain->wm);
+ }
if (use_factory_settings) {
/* Clear keymaps because the current default keymap may have been initialized
@@ -1036,14 +1059,16 @@ void wm_homefile_read(bContext *C,
}
}
- WM_check(C); /* opens window(s), checks keymaps */
+ if (use_data) {
+ WM_check(C); /* opens window(s), checks keymaps */
- bmain->name[0] = '\0';
+ bmain->name[0] = '\0';
- /* start with save preference untitled.blend */
- G.save_over = 0;
+ /* 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;
}
@@ -1694,69 +1720,141 @@ void WM_OT_userpref_autoexec_path_remove(wmOperatorType *ot)
static int wm_userpref_write_exec(bContext *C, wmOperator *op)
{
wmWindowManager *wm = CTX_wm_manager(C);
- char filepath[FILE_MAX];
- const char *cfgdir;
- bool ok = true;
- bool use_template_userpref = wm_app_template_has_userpref(U.app_template);
- /* update keymaps in user preferences */
+ /* Update keymaps in user preferences. */
WM_keyconfig_update(wm);
- if ((cfgdir = BKE_appdir_folder_id_create(BLENDER_USER_CONFIG, NULL))) {
- bool ok_write;
- BLI_path_join(filepath, sizeof(filepath), cfgdir, BLENDER_USERPREF_FILE, NULL);
+ const bool ok = BKE_blendfile_userdef_write_all(op->reports);
- printf("Writing userprefs: '%s' ", filepath);
- if (use_template_userpref) {
- ok_write = BKE_blendfile_userdef_write_app_template(filepath, op->reports);
- }
- else {
- ok_write = BKE_blendfile_userdef_write(filepath, op->reports);
- }
+ return ok ? OPERATOR_FINISHED : OPERATOR_CANCELLED;
+}
- if (ok_write) {
- printf("ok\n");
- }
- else {
- printf("fail\n");
- ok = false;
- }
- }
- else {
- BKE_report(op->reports, RPT_ERROR, "Unable to create userpref path");
- }
+void WM_OT_save_userpref(wmOperatorType *ot)
+{
+ ot->name = "Save Preferences";
+ ot->idname = "WM_OT_save_userpref";
+ ot->description = "Save preferences separately, overrides startup file preferences";
- if (use_template_userpref) {
- if ((cfgdir = BKE_appdir_folder_id_create(BLENDER_USER_CONFIG, U.app_template))) {
- /* Also save app-template prefs */
- BLI_path_join(filepath, sizeof(filepath), cfgdir, BLENDER_USERPREF_FILE, NULL);
+ ot->invoke = WM_operator_confirm;
+ ot->exec = wm_userpref_write_exec;
+}
- printf("Writing userprefs app-template: '%s' ", filepath);
- if (BKE_blendfile_userdef_write(filepath, op->reports) != 0) {
- printf("ok\n");
+static void rna_struct_update_when_changed(bContext *C,
+ Main *bmain,
+ PointerRNA *ptr_a,
+ PointerRNA *ptr_b)
+{
+ CollectionPropertyIterator iter;
+ PropertyRNA *iterprop = RNA_struct_iterator_property(ptr_a->type);
+ BLI_assert(ptr_a->type == ptr_b->type);
+ RNA_property_collection_begin(ptr_a, iterprop, &iter);
+ for (; iter.valid; RNA_property_collection_next(&iter)) {
+ PropertyRNA *prop = iter.ptr.data;
+ if (STREQ(RNA_property_identifier(prop), "rna_type")) {
+ continue;
+ }
+ switch (RNA_property_type(prop)) {
+ case PROP_POINTER: {
+ PointerRNA ptr_sub_a = RNA_property_pointer_get(ptr_a, prop);
+ PointerRNA ptr_sub_b = RNA_property_pointer_get(ptr_b, prop);
+ rna_struct_update_when_changed(C, bmain, &ptr_sub_a, &ptr_sub_b);
+ break;
}
- else {
- printf("fail\n");
- ok = false;
+ case PROP_COLLECTION:
+ /* Don't handle collections. */
+ break;
+ default: {
+ if (!RNA_property_equals(bmain, ptr_a, ptr_b, prop, RNA_EQ_STRICT)) {
+ RNA_property_update(C, ptr_b, prop);
+ }
}
}
- else {
- BKE_report(op->reports, RPT_ERROR, "Unable to create app-template userpref path");
- ok = false;
- }
}
+ RNA_property_collection_end(&iter);
+}
- return ok ? OPERATOR_FINISHED : OPERATOR_CANCELLED;
+static void wm_userpref_update_when_changed(bContext *C,
+ Main *bmain,
+ UserDef *userdef_prev,
+ UserDef *userdef_curr)
+{
+ PointerRNA ptr_a, ptr_b;
+ RNA_pointer_create(NULL, &RNA_Preferences, userdef_prev, &ptr_a);
+ RNA_pointer_create(NULL, &RNA_Preferences, userdef_curr, &ptr_b);
+ const bool is_dirty = userdef_curr->runtime.is_dirty;
+
+ rna_struct_update_when_changed(C, bmain, &ptr_a, &ptr_b);
+
+#ifdef WITH_PYTHON
+ BPY_execute_string(C, (const char *[]){"addon_utils", NULL}, "addon_utils.reset_all()");
+#endif
+
+ WM_keyconfig_reload(C);
+ userdef_curr->runtime.is_dirty = is_dirty;
}
-void WM_OT_save_userpref(wmOperatorType *ot)
+static int wm_userpref_read_exec(bContext *C, wmOperator *op)
{
- ot->name = "Save Preferences";
- ot->idname = "WM_OT_save_userpref";
- ot->description = "Save preferences separately, overrides startup file preferences";
+ const bool use_data = false;
+ const bool use_userdef = true;
+ const bool use_factory_settings = STREQ(op->type->idname, "WM_OT_read_factory_userpref");
+
+ UserDef U_backup = U;
+
+ wm_homefile_read(C,
+ op->reports,
+ use_factory_settings,
+ false,
+ use_data,
+ use_userdef,
+ NULL,
+ WM_init_state_app_template_get(),
+ NULL);
+
+#define USERDEF_RESTORE(member) \
+ { \
+ U.member = U_backup.member; \
+ } \
+ ((void)0)
+
+ USERDEF_RESTORE(userpref);
+
+#undef USERDEF_RESTORE
+
+ Main *bmain = CTX_data_main(C);
+
+ wm_userpref_update_when_changed(C, bmain, &U_backup, &U);
+
+ if (use_factory_settings) {
+ U.runtime.is_dirty = true;
+ }
+
+ /* Needed to recalculate UI scaling values (eg, #UserDef.inv_dpi_fac). */
+ wm_window_clear_drawable(bmain->wm.first);
+
+ WM_event_add_notifier(C, NC_WINDOW, NULL);
+
+ return OPERATOR_FINISHED;
+}
+
+void WM_OT_read_userpref(wmOperatorType *ot)
+{
+ ot->name = "Load Preferences";
+ ot->idname = "WM_OT_read_userpref";
+ ot->description = "Load last saved preferences";
ot->invoke = WM_operator_confirm;
- ot->exec = wm_userpref_write_exec;
+ ot->exec = wm_userpref_read_exec;
+}
+
+void WM_OT_read_factory_userpref(wmOperatorType *ot)
+{
+ ot->name = "Load Factory Preferences";
+ ot->idname = "WM_OT_read_factory_userpref";
+ ot->description = "Load default preferences";
+
+ ot->invoke = WM_operator_confirm;
+ ot->exec = wm_userpref_read_exec;
}
static int wm_history_file_read_exec(bContext *UNUSED(C), wmOperator *UNUSED(op))
@@ -1816,14 +1914,15 @@ static int wm_homefile_read_exec(bContext *C, wmOperator *op)
PropertyRNA *prop_app_template = RNA_struct_find_property(op->ptr, "app_template");
const bool use_splash = !use_factory_settings && RNA_boolean_get(op->ptr, "use_splash");
const bool use_empty_data = RNA_boolean_get(op->ptr, "use_empty");
+ const bool use_temporary_preferences = RNA_boolean_get(op->ptr, "use_temporary_preferences");
if (prop_app_template && RNA_property_is_set(op->ptr, prop_app_template)) {
RNA_property_string_get(op->ptr, prop_app_template, app_template_buf);
app_template = app_template_buf;
/* Always load preferences when switching templates with own preferences. */
- use_userdef = wm_app_template_has_userpref(app_template) ||
- wm_app_template_has_userpref(U.app_template);
+ use_userdef = BKE_appdir_app_template_has_userpref(app_template) ||
+ BKE_appdir_app_template_has_userpref(U.app_template);
/* Turn override off, since we're explicitly loading a different app-template. */
WM_init_state_app_template_set(NULL);
@@ -1833,10 +1932,12 @@ static int wm_homefile_read_exec(bContext *C, wmOperator *op)
app_template = WM_init_state_app_template_get();
}
+ bool use_data = true;
wm_homefile_read(C,
op->reports,
use_factory_settings,
use_empty_data,
+ use_data,
use_userdef,
filepath,
app_template,
@@ -1844,20 +1945,56 @@ static int wm_homefile_read_exec(bContext *C, wmOperator *op)
if (use_splash) {
WM_init_splash(C);
}
+ SET_FLAG_FROM_TEST(G.f, use_temporary_preferences, G_FLAG_USERPREF_NO_SAVE_ON_EXIT);
+
return OPERATOR_FINISHED;
}
+static void wm_homefile_read_after_dialog_callback(bContext *C, void *user_data)
+{
+ WM_operator_name_call_with_properties(
+ C, "WM_OT_read_homefile", WM_OP_EXEC_DEFAULT, (IDProperty *)user_data);
+}
+
+static void wm_free_operator_properties_callback(void *user_data)
+{
+ IDProperty *properties = (IDProperty *)user_data;
+ IDP_FreeProperty(properties);
+}
+
static int wm_homefile_read_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event))
{
- wmWindowManager *wm = CTX_wm_manager(C);
- if (U.uiflag & USER_SAVE_PROMPT && !wm->file_saved) {
- return WM_operator_confirm_message(C, op, "Changes in current file will be lost. Continue?");
+ if (U.uiflag & USER_SAVE_PROMPT && wm_file_or_image_is_modified(C)) {
+ 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;
+ wm_close_file_dialog(C, callback);
+ return OPERATOR_INTERFACE;
}
else {
return wm_homefile_read_exec(C, op);
}
}
+static void read_homefile_props(wmOperatorType *ot)
+{
+ PropertyRNA *prop;
+
+ prop = RNA_def_string(ot->srna, "app_template", "Template", sizeof(U.app_template), "", "");
+ RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE);
+
+ prop = RNA_def_boolean(ot->srna, "use_empty", false, "Empty", "");
+ RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE);
+
+ prop = RNA_def_boolean(ot->srna,
+ "use_temporary_preferences",
+ false,
+ "Temporary Preferences",
+ "Don't save preferences on exit");
+ RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE);
+}
+
void WM_OT_read_homefile(wmOperatorType *ot)
{
PropertyRNA *prop;
@@ -1877,23 +2014,17 @@ void WM_OT_read_homefile(wmOperatorType *ot)
ot->srna, "load_ui", true, "Load UI", "Load user interface setup from the .blend file");
RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE);
- prop = RNA_def_boolean(ot->srna, "use_empty", false, "Empty", "");
- RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE);
-
/* So the splash can be kept open after loading a file (for templates). */
prop = RNA_def_boolean(ot->srna, "use_splash", false, "Splash", "");
RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE);
- prop = RNA_def_string(ot->srna, "app_template", "Template", sizeof(U.app_template), "", "");
- RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE);
+ read_homefile_props(ot);
/* omit poll to run in background mode */
}
void WM_OT_read_factory_settings(wmOperatorType *ot)
{
- PropertyRNA *prop;
-
ot->name = "Load Factory Settings";
ot->idname = "WM_OT_read_factory_settings";
ot->description = "Load default file and preferences";
@@ -1901,12 +2032,7 @@ void WM_OT_read_factory_settings(wmOperatorType *ot)
ot->invoke = WM_operator_confirm;
ot->exec = wm_homefile_read_exec;
- prop = RNA_def_string(ot->srna, "app_template", "Template", sizeof(U.app_template), "", "");
- RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE);
-
- prop = RNA_def_boolean(ot->srna, "use_empty", false, "Empty", "");
- RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE);
-
+ read_homefile_props(ot);
/* omit poll to run in background mode */
}
@@ -1939,13 +2065,88 @@ static bool wm_file_read_opwrap(bContext *C,
return success;
}
-/* currently fits in a pointer */
-struct FileRuntime {
- bool is_untrusted;
+/* Generic operator state utilities
+ *********************************************/
+
+static void create_operator_state(wmOperatorType *ot, int first_state)
+{
+ PropertyRNA *prop = RNA_def_int(
+ ot->srna, "state", first_state, INT32_MIN, INT32_MAX, "State", "", INT32_MIN, INT32_MAX);
+ RNA_def_property_flag(prop, PROP_SKIP_SAVE);
+ RNA_def_property_flag(prop, PROP_HIDDEN);
+}
+
+static int get_operator_state(wmOperator *op)
+{
+ return RNA_int_get(op->ptr, "state");
+}
+
+static void set_next_operator_state(wmOperator *op, int state)
+{
+ RNA_int_set(op->ptr, "state", state);
+}
+
+typedef struct OperatorDispatchTarget {
+ int state;
+ int (*run)(bContext *C, wmOperator *op);
+} OperatorDispatchTarget;
+
+static int operator_state_dispatch(bContext *C, wmOperator *op, OperatorDispatchTarget *targets)
+{
+ int state = get_operator_state(op);
+ for (int i = 0; targets[i].run; i++) {
+ OperatorDispatchTarget target = targets[i];
+ if (target.state == state) {
+ return target.run(C, op);
+ }
+ }
+ BLI_assert(false);
+ return OPERATOR_CANCELLED;
+}
+
+/* Open Mainfile operator
+ ********************************************/
+
+enum {
+ OPEN_MAINFILE_STATE_DISCARD_CHANGES,
+ OPEN_MAINFILE_STATE_SELECT_FILE_PATH,
+ OPEN_MAINFILE_STATE_OPEN,
};
-static int wm_open_mainfile_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event))
+static int wm_open_mainfile_dispatch(bContext *C, wmOperator *op);
+
+static void wm_open_mainfile_after_dialog_callback(bContext *C, void *user_data)
{
+ WM_operator_name_call_with_properties(
+ C, "WM_OT_open_mainfile", WM_OP_INVOKE_DEFAULT, (IDProperty *)user_data);
+}
+
+static int wm_open_mainfile__discard_changes(bContext *C, wmOperator *op)
+{
+ if (RNA_boolean_get(op->ptr, "display_file_selector")) {
+ set_next_operator_state(op, OPEN_MAINFILE_STATE_SELECT_FILE_PATH);
+ }
+ else {
+ set_next_operator_state(op, OPEN_MAINFILE_STATE_OPEN);
+ }
+
+ if (U.uiflag & USER_SAVE_PROMPT && wm_file_or_image_is_modified(C)) {
+ 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;
+ wm_close_file_dialog(C, callback);
+ return OPERATOR_INTERFACE;
+ }
+ else {
+ return wm_open_mainfile_dispatch(C, op);
+ }
+}
+
+static int wm_open_mainfile__select_file_path(bContext *C, wmOperator *op)
+{
+ set_next_operator_state(op, OPEN_MAINFILE_STATE_OPEN);
+
Main *bmain = CTX_data_main(C);
const char *openname = BKE_main_blendfile_path(bmain);
@@ -1973,7 +2174,7 @@ static int wm_open_mainfile_invoke(bContext *C, wmOperator *op, const wmEvent *U
return OPERATOR_RUNNING_MODAL;
}
-static int wm_open_mainfile_exec(bContext *C, wmOperator *op)
+static int wm_open_mainfile__open(bContext *C, wmOperator *op)
{
char filepath[FILE_MAX];
bool success;
@@ -2011,6 +2212,33 @@ static int wm_open_mainfile_exec(bContext *C, wmOperator *op)
}
}
+static OperatorDispatchTarget wm_open_mainfile_dispatch_targets[] = {
+ {OPEN_MAINFILE_STATE_DISCARD_CHANGES, wm_open_mainfile__discard_changes},
+ {OPEN_MAINFILE_STATE_SELECT_FILE_PATH, wm_open_mainfile__select_file_path},
+ {OPEN_MAINFILE_STATE_OPEN, wm_open_mainfile__open},
+ {0, NULL},
+};
+
+static int wm_open_mainfile_dispatch(bContext *C, wmOperator *op)
+{
+ return operator_state_dispatch(C, op, wm_open_mainfile_dispatch_targets);
+}
+
+static int wm_open_mainfile_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event))
+{
+ return wm_open_mainfile_dispatch(C, op);
+}
+
+static int wm_open_mainfile_exec(bContext *C, wmOperator *op)
+{
+ return wm_open_mainfile__open(C, op);
+}
+
+/* currently fits in a pointer */
+struct FileRuntime {
+ bool is_untrusted;
+};
+
static bool wm_open_mainfile_check(bContext *UNUSED(C), wmOperator *op)
{
struct FileRuntime *file_info = (struct FileRuntime *)&op->customdata;
@@ -2091,6 +2319,12 @@ void WM_OT_open_mainfile(wmOperatorType *ot)
"Trusted Source",
"Allow .blend file to execute scripts automatically, default available from "
"system preferences");
+
+ PropertyRNA *prop = RNA_def_boolean(
+ ot->srna, "display_file_selector", true, "Display File Selector", "");
+ RNA_def_property_flag(prop, PROP_SKIP_SAVE);
+
+ create_operator_state(ot, OPEN_MAINFILE_STATE_DISCARD_CHANGES);
}
/** \} */
@@ -2629,9 +2863,228 @@ void wm_test_autorun_warning(bContext *C)
if (win) {
wmWindow *prevwin = CTX_wm_window(C);
CTX_wm_window_set(C, win);
- UI_popup_block_invoke(C, block_create_autorun_warning, NULL);
+ UI_popup_block_invoke(C, block_create_autorun_warning, NULL, NULL);
CTX_wm_window_set(C, prevwin);
}
}
+/* Close File Dialog
+ *************************************/
+
+static char save_images_when_file_is_closed = true;
+
+static void wm_block_file_close_cancel(bContext *C, void *arg_block, void *UNUSED(arg_data))
+{
+ wmWindow *win = CTX_wm_window(C);
+ UI_popup_block_close(C, win, arg_block);
+}
+
+static void wm_block_file_close_discard(bContext *C, void *arg_block, void *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
+ * to a crash. */
+ wmWindow *win = CTX_wm_window(C);
+ UI_popup_block_close(C, win, arg_block);
+
+ callback->exec(C, callback->user_data);
+ WM_generic_callback_free(callback);
+}
+
+static void wm_block_file_close_save(bContext *C, void *arg_block, void *arg_data)
+{
+ wmGenericCallback *callback = WM_generic_callback_steal((wmGenericCallback *)arg_data);
+ bool execute_callback = true;
+
+ wmWindow *win = CTX_wm_window(C);
+ UI_popup_block_close(C, win, arg_block);
+
+ if (save_images_when_file_is_closed) {
+ ReportList *reports = CTX_wm_reports(C);
+ if (!ED_image_save_all_modified(C, reports)) {
+ execute_callback = false;
+ }
+ WM_report_banner_show();
+ }
+
+ Main *bmain = CTX_data_main(C);
+ bool file_has_been_saved_before = BKE_main_blendfile_path(bmain)[0] != '\0';
+
+ if (file_has_been_saved_before) {
+ WM_operator_name_call(C, "WM_OT_save_mainfile", WM_OP_EXEC_DEFAULT, NULL);
+ }
+ else {
+ WM_operator_name_call(C, "WM_OT_save_mainfile", WM_OP_INVOKE_DEFAULT, NULL);
+ execute_callback = false;
+ }
+
+ if (execute_callback) {
+ callback->exec(C, callback->user_data);
+ }
+ WM_generic_callback_free(callback);
+}
+
+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, "");
+ UI_but_func_set(but, wm_block_file_close_cancel, block, post_action);
+ UI_but_drawflag_disable(but, UI_BUT_TEXT_LEFT);
+}
+
+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, "");
+ UI_but_func_set(but, wm_block_file_close_discard, block, post_action);
+ UI_but_drawflag_disable(but, UI_BUT_TEXT_LEFT);
+}
+
+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, "");
+ UI_but_func_set(but, wm_block_file_close_save, block, post_action);
+ UI_but_drawflag_disable(but, UI_BUT_TEXT_LEFT);
+ 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)
+{
+ wmGenericCallback *post_action = (wmGenericCallback *)arg1;
+ Main *bmain = CTX_data_main(C);
+
+ uiStyle *style = UI_style_get();
+ 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);
+ UI_block_theme_style_set(block, UI_BLOCK_THEME_STYLE_POPUP);
+ UI_block_emboss_set(block, UI_EMBOSS);
+
+ uiLayout *layout = UI_block_layout(block,
+ UI_LAYOUT_VERTICAL,
+ UI_LAYOUT_PANEL,
+ 10,
+ 2,
+ U.widget_unit * 24,
+ U.widget_unit * 6,
+ 0,
+ style);
+
+ /* Title */
+ bool blend_file_is_saved = BKE_main_blendfile_path(bmain)[0] != '\0';
+ if (blend_file_is_saved) {
+ uiItemL(layout, "This file has unsaved changes.", ICON_INFO);
+ }
+ else {
+ uiItemL(layout, "This file has not been saved yet.", ICON_INFO);
+ }
+
+ /* Image Saving */
+ ReportList reports;
+ BKE_reports_init(&reports, RPT_STORE);
+ uint modified_images_count = ED_image_save_all_modified_info(C, &reports);
+
+ if (modified_images_count > 0) {
+ char message[64];
+ BLI_snprintf(message,
+ sizeof(message),
+ (modified_images_count == 1) ? "Save %u modified image" :
+ "Save %u modified images",
+ modified_images_count);
+ uiDefButBitC(block,
+ UI_BTYPE_CHECKBOX,
+ 1,
+ 0,
+ message,
+ 0,
+ 0,
+ 0,
+ UI_UNIT_Y,
+ &save_images_when_file_is_closed,
+ 0,
+ 0,
+ 0,
+ 0,
+ "");
+
+ LISTBASE_FOREACH (Report *, report, &reports.list) {
+ uiItemL(layout, report->message, ICON_ERROR);
+ }
+ }
+
+ BKE_reports_clear(&reports);
+
+ uiItemL(layout, "", ICON_NONE);
+
+ /* Buttons */
+#ifdef _WIN32
+ const bool windows_layout = true;
+#else
+ const bool windows_layout = false;
+#endif
+
+ uiLayout *split = uiLayoutSplit(layout, 0.0f, true);
+
+ if (windows_layout) {
+ /* Windows standard layout. */
+ uiLayout *col = uiLayoutColumn(split, false);
+ uiItemS(col);
+
+ col = uiLayoutColumn(split, false);
+ wm_block_file_close_save_button(block, post_action);
+
+ col = uiLayoutColumn(split, false);
+ wm_block_file_close_discard_button(block, post_action);
+
+ col = uiLayoutColumn(split, false);
+ wm_block_file_close_cancel_button(block, post_action);
+ }
+ else {
+ /* macOS and Linux standard layout. */
+ uiLayout *col = uiLayoutColumn(split, false);
+ wm_block_file_close_discard_button(block, post_action);
+
+ col = uiLayoutColumn(split, false);
+ uiItemS(col);
+
+ col = uiLayoutColumn(split, false);
+ wm_block_file_close_cancel_button(block, post_action);
+
+ col = uiLayoutColumn(split, false);
+ wm_block_file_close_save_button(block, post_action);
+ }
+
+ UI_block_bounds_set_centered(block, 10);
+ return block;
+}
+
+static void free_post_file_close_action(void *arg)
+{
+ wmGenericCallback *action = (wmGenericCallback *)arg;
+ WM_generic_callback_free(action);
+}
+
+void wm_close_file_dialog(bContext *C, wmGenericCallback *post_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)
+{
+ wmWindowManager *wm = CTX_wm_manager(C);
+ return !wm->file_saved || ED_image_should_save_modified(C);
+}
+
/** \} */
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_init_exit.c b/source/blender/windowmanager/intern/wm_init_exit.c
index 97ba9190351..04a3115992f 100644
--- a/source/blender/windowmanager/intern/wm_init_exit.c
+++ b/source/blender/windowmanager/intern/wm_init_exit.c
@@ -52,6 +52,7 @@
#include "BLO_writefile.h"
#include "BLO_undofile.h"
+#include "BKE_blendfile.h"
#include "BKE_blender.h"
#include "BKE_blender_undo.h"
#include "BKE_context.h"
@@ -254,11 +255,15 @@ void WM_init(bContext *C, int argc, const char **argv)
/* get the default database, plus a wm */
bool is_factory_startup = true;
+ const bool use_data = true;
+ const bool use_userdef = true;
+
wm_homefile_read(C,
NULL,
G.factory_startup,
false,
- true,
+ use_data,
+ use_userdef,
NULL,
WM_init_state_app_template_get(),
&is_factory_startup);
@@ -469,6 +474,14 @@ void WM_exit_ext(bContext *C, const bool do_python)
WM_event_remove_handlers(C, &win->modalhandlers);
ED_screen_exit(C, win, WM_window_get_active_screen(win));
}
+
+ if (!G.background) {
+ if ((U.pref_flag & USER_PREF_FLAG_SAVE) && ((G.f & G_FLAG_USERPREF_NO_SAVE_ON_EXIT) == 0)) {
+ if (U.runtime.is_dirty) {
+ BKE_blendfile_userdef_write_all(NULL);
+ }
+ }
+ }
}
BLI_timer_free();
diff --git a/source/blender/windowmanager/intern/wm_keymap.c b/source/blender/windowmanager/intern/wm_keymap.c
index bae9a5de1e6..a4ee735d911 100644
--- a/source/blender/windowmanager/intern/wm_keymap.c
+++ b/source/blender/windowmanager/intern/wm_keymap.c
@@ -310,6 +310,7 @@ bool WM_keyconfig_remove(wmWindowManager *wm, wmKeyConfig *keyconf)
if (BLI_findindex(&wm->keyconfigs, keyconf) != -1) {
if (STREQLEN(U.keyconfigstr, keyconf->idname, sizeof(U.keyconfigstr))) {
BLI_strncpy(U.keyconfigstr, wm->defaultconf->idname, sizeof(U.keyconfigstr));
+ U.runtime.is_dirty = true;
WM_keyconfig_update_tag(NULL, NULL);
}
@@ -360,6 +361,9 @@ void WM_keyconfig_set_active(wmWindowManager *wm, const char *idname)
WM_keyconfig_update(wm);
BLI_strncpy(U.keyconfigstr, idname, sizeof(U.keyconfigstr));
+ if (wm->initialized & WM_KEYCONFIG_IS_INITIALIZED) {
+ U.runtime.is_dirty = true;
+ }
WM_keyconfig_update_tag(NULL, NULL);
WM_keyconfig_update(wm);
@@ -1120,7 +1124,8 @@ const char *WM_key_event_string(const short type, const bool compact)
if (platform == MACOS) {
icon_glyph = "\xe2\x87\xa7";
}
- return key_event_icon_or_text(font_id, IFACE_("Shift"), icon_glyph);
+ return key_event_icon_or_text(
+ font_id, CTX_IFACE_(BLT_I18NCONTEXT_ID_WINDOWMANAGER, "Shift"), icon_glyph);
}
case LEFTCTRLKEY:
case RIGHTCTRLKEY:
@@ -1407,7 +1412,6 @@ static wmKeyMapItem *wm_keymap_item_find_in_keymap(wmKeyMap *keymap,
}
IDP_FreeProperty(properties_default);
- MEM_freeN(properties_default);
}
}
}
@@ -1581,7 +1585,6 @@ static wmKeyMapItem *wm_keymap_item_find(const bContext *C,
}
IDP_FreeProperty(properties_temp);
- MEM_freeN(properties_temp);
}
}
@@ -1620,7 +1623,6 @@ static wmKeyMapItem *wm_keymap_item_find(const bContext *C,
}
IDP_FreeProperty(properties_default);
- MEM_freeN(properties_default);
}
}
}
@@ -2017,7 +2019,6 @@ void WM_keymap_item_restore_to_default(bContext *C, wmKeyMap *keymap, wmKeyMapIt
if (orig->properties) {
if (kmi->properties) {
IDP_FreeProperty(kmi->properties);
- MEM_freeN(kmi->properties);
kmi->properties = NULL;
}
diff --git a/source/blender/windowmanager/intern/wm_operator_props.c b/source/blender/windowmanager/intern/wm_operator_props.c
index ece57f5a63b..3ad7247d993 100644
--- a/source/blender/windowmanager/intern/wm_operator_props.c
+++ b/source/blender/windowmanager/intern/wm_operator_props.c
@@ -94,7 +94,9 @@ void WM_operator_properties_filesel(wmOperatorType *ot,
}
if (flag & WM_FILESEL_FILES) {
- RNA_def_collection_runtime(ot->srna, "files", &RNA_OperatorFileListElement, "Files", "");
+ prop = RNA_def_collection_runtime(
+ ot->srna, "files", &RNA_OperatorFileListElement, "Files", "");
+ RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE);
}
if (action == FILE_SAVE) {
@@ -344,11 +346,11 @@ void WM_operator_properties_gesture_box(wmOperatorType *ot)
void WM_operator_properties_select_operation(wmOperatorType *ot)
{
static const EnumPropertyItem select_mode_items[] = {
- {SEL_OP_SET, "SET", 0, "New", ""},
- {SEL_OP_ADD, "ADD", 0, "Add", ""},
- {SEL_OP_SUB, "SUB", 0, "Subtract", ""},
- {SEL_OP_XOR, "XOR", 0, "Difference", ""},
- {SEL_OP_AND, "AND", 0, "Intersect", ""},
+ {SEL_OP_SET, "SET", ICON_SELECT_SET, "Set", "Set a new selection"},
+ {SEL_OP_ADD, "ADD", ICON_SELECT_EXTEND, "Extend", "Extend existing selection"},
+ {SEL_OP_SUB, "SUB", ICON_SELECT_SUBTRACT, "Subtract", "Subtract existing selection"},
+ {SEL_OP_XOR, "XOR", ICON_SELECT_DIFFERENCE, "Difference", "Inverts existing selection"},
+ {SEL_OP_AND, "AND", ICON_SELECT_INTERSECT, "Intersect", "Intersect existing selection"},
{0, NULL, 0, NULL, NULL},
};
PropertyRNA *prop = RNA_def_enum(ot->srna, "mode", select_mode_items, SEL_OP_SET, "Mode", "");
@@ -359,9 +361,9 @@ void WM_operator_properties_select_operation(wmOperatorType *ot)
void WM_operator_properties_select_operation_simple(wmOperatorType *ot)
{
static const EnumPropertyItem select_mode_items[] = {
- {SEL_OP_SET, "SET", 0, "New", ""},
- {SEL_OP_ADD, "ADD", 0, "Add", ""},
- {SEL_OP_SUB, "SUB", 0, "Subtract", ""},
+ {SEL_OP_SET, "SET", ICON_SELECT_SET, "Set", "Set a new selection"},
+ {SEL_OP_ADD, "ADD", ICON_SELECT_EXTEND, "Extend", "Extend existing selection"},
+ {SEL_OP_SUB, "SUB", ICON_SELECT_SUBTRACT, "Subtract", "Subtract existing selection"},
{0, NULL, 0, NULL, NULL},
};
PropertyRNA *prop = RNA_def_enum(ot->srna, "mode", select_mode_items, SEL_OP_SET, "Mode", "");
diff --git a/source/blender/windowmanager/intern/wm_operator_type.c b/source/blender/windowmanager/intern/wm_operator_type.c
index 3585cffc615..179b4402200 100644
--- a/source/blender/windowmanager/intern/wm_operator_type.c
+++ b/source/blender/windowmanager/intern/wm_operator_type.c
@@ -156,7 +156,6 @@ void WM_operatortype_remove_ptr(wmOperatorType *ot)
if (ot->last_properties) {
IDP_FreeProperty(ot->last_properties);
- MEM_freeN(ot->last_properties);
}
if (ot->macro.first) {
@@ -194,7 +193,6 @@ static void operatortype_ghash_free_cb(wmOperatorType *ot)
{
if (ot->last_properties) {
IDP_FreeProperty(ot->last_properties);
- MEM_freeN(ot->last_properties);
}
if (ot->macro.first) {
@@ -279,7 +277,6 @@ void WM_operatortype_last_properties_clear_all(void)
if (ot->last_properties) {
IDP_FreeProperty(ot->last_properties);
- MEM_freeN(ot->last_properties);
ot->last_properties = NULL;
}
}
diff --git a/source/blender/windowmanager/intern/wm_operators.c b/source/blender/windowmanager/intern/wm_operators.c
index ec803c9bba7..4a99c2de6e7 100644
--- a/source/blender/windowmanager/intern/wm_operators.c
+++ b/source/blender/windowmanager/intern/wm_operators.c
@@ -691,7 +691,6 @@ void WM_operator_properties_free(PointerRNA *ptr)
if (properties) {
IDP_FreeProperty(properties);
- MEM_freeN(properties);
ptr->data = NULL; /* just in case */
}
}
@@ -870,7 +869,7 @@ int WM_enum_search_invoke_previews(bContext *C, wmOperator *op, short prv_cols,
search_menu.prv_cols = prv_cols;
search_menu.prv_rows = prv_rows;
- UI_popup_block_invoke(C, wm_enum_search_menu, &search_menu);
+ UI_popup_block_invoke(C, wm_enum_search_menu, &search_menu, NULL);
return OPERATOR_INTERFACE;
}
@@ -879,13 +878,17 @@ int WM_enum_search_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(eve
{
static struct EnumSearchMenu search_menu;
search_menu.op = op;
- UI_popup_block_invoke(C, wm_enum_search_menu, &search_menu);
+ UI_popup_block_invoke(C, wm_enum_search_menu, &search_menu, NULL);
return OPERATOR_INTERFACE;
}
/* Can't be used as an invoke directly, needs message arg (can be NULL) */
-int WM_operator_confirm_message_ex(
- bContext *C, wmOperator *op, const char *title, const int icon, const char *message)
+int WM_operator_confirm_message_ex(bContext *C,
+ wmOperator *op,
+ const char *title,
+ const int icon,
+ const char *message,
+ const short opcontext)
{
uiPopupMenu *pup;
uiLayout *layout;
@@ -900,8 +903,7 @@ int WM_operator_confirm_message_ex(
pup = UI_popup_menu_begin(C, title, icon);
layout = UI_popup_menu_layout(pup);
- uiItemFullO_ptr(
- layout, op->type, message, ICON_NONE, properties, WM_OP_EXEC_REGION_WIN, 0, NULL);
+ uiItemFullO_ptr(layout, op->type, message, ICON_NONE, properties, opcontext, 0, NULL);
UI_popup_menu_end(C, pup);
return OPERATOR_INTERFACE;
@@ -909,7 +911,8 @@ int WM_operator_confirm_message_ex(
int WM_operator_confirm_message(bContext *C, wmOperator *op, const char *message)
{
- return WM_operator_confirm_message_ex(C, op, IFACE_("OK?"), ICON_QUESTION, message);
+ return WM_operator_confirm_message_ex(
+ C, op, IFACE_("OK?"), ICON_QUESTION, message, WM_OP_EXEC_REGION_WIN);
}
int WM_operator_confirm(bContext *C, wmOperator *op, const wmEvent *UNUSED(event))
@@ -1398,7 +1401,7 @@ int WM_operator_redo_popup(bContext *C, wmOperator *op)
return OPERATOR_CANCELLED;
}
- UI_popup_block_invoke(C, wm_block_create_redo, op);
+ UI_popup_block_invoke(C, wm_block_create_redo, op, NULL);
return OPERATOR_CANCELLED;
}
@@ -1710,7 +1713,7 @@ static uiBlock *wm_block_create_splash(bContext *C, ARegion *ar, void *UNUSED(ar
static int wm_splash_invoke(bContext *C, wmOperator *UNUSED(op), const wmEvent *UNUSED(event))
{
- UI_popup_block_invoke(C, wm_block_create_splash, NULL);
+ UI_popup_block_invoke(C, wm_block_create_splash, NULL, NULL);
return OPERATOR_FINISHED;
}
@@ -1816,7 +1819,7 @@ static int wm_search_menu_invoke(bContext *C, wmOperator *UNUSED(op), const wmEv
data.size[0] = UI_searchbox_size_x() * 2;
data.size[1] = UI_searchbox_size_y();
- UI_popup_block_invoke(C, wm_block_search_menu, &data);
+ UI_popup_block_invoke(C, wm_block_search_menu, &data, NULL);
return OPERATOR_INTERFACE;
}
@@ -3082,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) {
@@ -3107,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);
}
}
}
@@ -3153,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");
@@ -3166,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;
@@ -3504,6 +3508,8 @@ void wm_operatortypes_register(void)
WM_operatortype_append(WM_OT_read_factory_settings);
WM_operatortype_append(WM_OT_save_homefile);
WM_operatortype_append(WM_OT_save_userpref);
+ WM_operatortype_append(WM_OT_read_userpref);
+ WM_operatortype_append(WM_OT_read_factory_userpref);
WM_operatortype_append(WM_OT_userpref_autoexec_path_add);
WM_operatortype_append(WM_OT_userpref_autoexec_path_remove);
WM_operatortype_append(WM_OT_window_fullscreen_toggle);
diff --git a/source/blender/windowmanager/intern/wm_playanim.c b/source/blender/windowmanager/intern/wm_playanim.c
index 844316bc925..7cc44bcad99 100644
--- a/source/blender/windowmanager/intern/wm_playanim.c
+++ b/source/blender/windowmanager/intern/wm_playanim.c
@@ -1063,7 +1063,7 @@ static int ghost_event_proc(GHOST_EventHandle evt, GHOST_TUserDataPtr ps_void)
break;
}
- case GHOST_kEventQuit:
+ case GHOST_kEventQuitRequest:
case GHOST_kEventWindowClose: {
ps->go = false;
break;
diff --git a/source/blender/windowmanager/intern/wm_toolsystem.c b/source/blender/windowmanager/intern/wm_toolsystem.c
index f429415bee9..3ea58d8c4e5 100644
--- a/source/blender/windowmanager/intern/wm_toolsystem.c
+++ b/source/blender/windowmanager/intern/wm_toolsystem.c
@@ -574,6 +574,20 @@ void WM_toolsystem_refresh_active(bContext *C)
}
}
}
+
+ BKE_workspace_id_tag_all_visible(bmain, LIB_TAG_DOIT);
+
+ LISTBASE_FOREACH (WorkSpace *, workspace, &bmain->workspaces) {
+ if (workspace->id.tag & LIB_TAG_DOIT) {
+ workspace->id.tag &= ~LIB_TAG_DOIT;
+ /* Refresh to ensure data is initialized.
+ * This is needed because undo can load a state which no longer has the underlying DNA data
+ * needed for the tool (un-initialized paint-slots for eg), see: T64339. */
+ for (bToolRef *tref = workspace->tools.first; tref; tref = tref->next) {
+ toolsystem_refresh_ref(C, workspace, tref);
+ }
+ }
+ }
}
void WM_toolsystem_refresh_screen_area(WorkSpace *workspace, ViewLayer *view_layer, ScrArea *sa)
@@ -712,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 e98067d78cc..7ae572e5685 100644
--- a/source/blender/windowmanager/intern/wm_window.c
+++ b/source/blender/windowmanager/intern/wm_window.c
@@ -61,6 +61,7 @@
#include "WM_types.h"
#include "wm.h"
#include "wm_draw.h"
+#include "wm_files.h"
#include "wm_window.h"
#include "wm_event_system.h"
@@ -356,150 +357,9 @@ wmWindow *wm_window_copy_test(bContext *C,
/** \name Quit Confirmation Dialog
* \{ */
-/** Cancel quitting and close the dialog */
-static void wm_block_confirm_quit_cancel(bContext *C, void *arg_block, void *UNUSED(arg))
+static void wm_save_file_on_quit_dialog_callback(bContext *C, void *UNUSED(user_data))
{
- wmWindow *win = CTX_wm_window(C);
- UI_popup_block_close(C, win, arg_block);
-}
-
-/** Discard the file changes and quit */
-ATTR_NORETURN
-static void wm_block_confirm_quit_discard(bContext *C, void *arg_block, void *UNUSED(arg))
-{
- wmWindow *win = CTX_wm_window(C);
- UI_popup_block_close(C, win, arg_block);
- WM_exit(C);
-}
-
-/* Save changes and quit */
-static void wm_block_confirm_quit_save(bContext *C, void *arg_block, void *UNUSED(arg))
-{
- PointerRNA props_ptr;
- wmWindow *win = CTX_wm_window(C);
-
- UI_popup_block_close(C, win, arg_block);
-
- wmOperatorType *ot = WM_operatortype_find("WM_OT_save_mainfile", false);
-
- WM_operator_properties_create_ptr(&props_ptr, ot);
- RNA_boolean_set(&props_ptr, "exit", true);
- /* No need for second confirmation popup. */
- RNA_boolean_set(&props_ptr, "check_existing", false);
- WM_operator_name_call_ptr(C, ot, WM_OP_INVOKE_DEFAULT, &props_ptr);
- WM_operator_properties_free(&props_ptr);
-}
-
-/* Build the confirm dialog UI */
-static uiBlock *block_create_confirm_quit(struct bContext *C,
- struct ARegion *ar,
- void *UNUSED(arg1))
-{
- Main *bmain = CTX_data_main(C);
-
- uiStyle *style = UI_style_get();
- uiBlock *block = UI_block_begin(C, ar, "confirm_quit_popup", UI_EMBOSS);
-
- UI_block_flag_enable(
- block, UI_BLOCK_KEEP_OPEN | UI_BLOCK_LOOP | UI_BLOCK_NO_WIN_CLIP | UI_BLOCK_NUMSELECT);
- UI_block_theme_style_set(block, UI_BLOCK_THEME_STYLE_POPUP);
- UI_block_emboss_set(block, UI_EMBOSS);
-
- uiLayout *layout = UI_block_layout(block,
- UI_LAYOUT_VERTICAL,
- UI_LAYOUT_PANEL,
- 10,
- 2,
- U.widget_unit * 24,
- U.widget_unit * 6,
- 0,
- style);
-
- /* Text and some vertical space */
- {
- char *message;
- if (BKE_main_blendfile_path(bmain)[0] == '\0') {
- message = BLI_strdup(IFACE_("This file has not been saved yet. Save before closing?"));
- }
- else {
- const char *basename = BLI_path_basename(BKE_main_blendfile_path(bmain));
- message = BLI_sprintfN(IFACE_("Save changes to \"%s\" before closing?"), basename);
- }
- uiItemL(layout, message, ICON_ERROR);
- MEM_freeN(message);
- }
-
- uiItemS(layout);
- uiItemS(layout);
-
- /* Buttons */
- uiBut *but;
-
- uiLayout *split = uiLayoutSplit(layout, 0.0f, true);
-
- uiLayout *col = uiLayoutColumn(split, false);
-
- but = uiDefIconTextBut(block,
- UI_BTYPE_BUT,
- 0,
- ICON_SCREEN_BACK,
- IFACE_("Cancel"),
- 0,
- 0,
- 0,
- UI_UNIT_Y,
- NULL,
- 0,
- 0,
- 0,
- 0,
- TIP_("Do not quit"));
- UI_but_func_set(but, wm_block_confirm_quit_cancel, block, NULL);
-
- /* empty space between buttons */
- col = uiLayoutColumn(split, false);
- uiItemS(col);
-
- col = uiLayoutColumn(split, 1);
- but = uiDefIconTextBut(block,
- UI_BTYPE_BUT,
- 0,
- ICON_CANCEL,
- IFACE_("Discard Changes"),
- 0,
- 0,
- 50,
- UI_UNIT_Y,
- NULL,
- 0,
- 0,
- 0,
- 0,
- TIP_("Discard changes and quit"));
- UI_but_func_set(but, wm_block_confirm_quit_discard, block, NULL);
-
- col = uiLayoutColumn(split, 1);
- but = uiDefIconTextBut(block,
- UI_BTYPE_BUT,
- 0,
- ICON_FILE_TICK,
- IFACE_("Save & Quit"),
- 0,
- 0,
- 50,
- UI_UNIT_Y,
- NULL,
- 0,
- 0,
- 0,
- 0,
- TIP_("Save and quit"));
- UI_but_func_set(but, wm_block_confirm_quit_save, block, NULL);
- UI_but_flag_enable(but, UI_BUT_ACTIVE_DEFAULT);
-
- UI_block_bounds_set_centered(block, 10);
-
- return block;
+ wm_exit_schedule_delayed(C);
}
/**
@@ -508,16 +368,9 @@ static uiBlock *block_create_confirm_quit(struct bContext *C,
*/
static void wm_confirm_quit(bContext *C)
{
- wmWindow *win = CTX_wm_window(C);
-
- if (GHOST_SupportsNativeDialogs() == 0) {
- if (!UI_popup_block_name_exists(C, "confirm_quit_popup")) {
- UI_popup_block_invoke(C, block_create_confirm_quit, NULL);
- }
- }
- else if (GHOST_confirmQuit(win->ghostwin)) {
- wm_exit_schedule_delayed(C);
- }
+ wmGenericCallback *action = MEM_callocN(sizeof(*action), __func__);
+ action->exec = wm_save_file_on_quit_dialog_callback;
+ wm_close_file_dialog(C, action);
}
/**
@@ -529,7 +382,6 @@ static void wm_confirm_quit(bContext *C)
*/
void wm_quit_with_optional_confirmation_prompt(bContext *C, wmWindow *win)
{
- wmWindowManager *wm = CTX_wm_manager(C);
wmWindow *win_ctx = CTX_wm_window(C);
/* The popup will be displayed in the context window which may not be set
@@ -537,7 +389,7 @@ void wm_quit_with_optional_confirmation_prompt(bContext *C, wmWindow *win)
CTX_wm_window_set(C, win);
if (U.uiflag & USER_SAVE_PROMPT) {
- if (!wm->file_saved && !G.background) {
+ if (wm_file_or_image_is_modified(C) && !G.background) {
wm_confirm_quit(C);
}
else {
@@ -672,6 +524,7 @@ void WM_window_set_dpi(wmWindow *win)
U.dpi = dpi / pixelsize;
U.virtual_pixel = (pixelsize == 1) ? VIRTUAL_PIXEL_NATIVE : VIRTUAL_PIXEL_DOUBLE;
U.dpi_fac = ((U.pixelsize * (float)U.dpi) / 72.0f);
+ U.inv_dpi_fac = 1.0f / U.dpi_fac;
/* Set user preferences globals for drawing, and for forward compatibility. */
U.widget_unit = (U.pixelsize * U.dpi * 20 + 36) / 72;
@@ -1264,8 +1117,25 @@ static int ghost_event_proc(GHOST_EventHandle evt, GHOST_TUserDataPtr C_void_ptr
GHOST_TEventType type = GHOST_GetEventType(evt);
int time = GHOST_GetEventTime(evt);
- if (type == GHOST_kEventQuit) {
- WM_exit(C);
+ if (type == GHOST_kEventQuitRequest) {
+ /* Find an active window to display quit dialog in. */
+ GHOST_WindowHandle ghostwin = GHOST_GetEventWindow(evt);
+ wmWindow *win;
+
+ if (ghostwin && GHOST_ValidWindow(g_system, ghostwin)) {
+ win = GHOST_GetWindowUserData(ghostwin);
+ }
+ else {
+ win = wm->winactive;
+ }
+
+ /* Display quit dialog or quit immediately. */
+ if (win) {
+ wm_quit_with_optional_confirmation_prompt(C, win);
+ }
+ else {
+ wm_exit_schedule_delayed(C);
+ }
}
else {
GHOST_WindowHandle ghostwin = GHOST_GetEventWindow(evt);
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 c60df27e24b..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 */
@@ -33,16 +34,22 @@ void wm_homefile_read(struct bContext *C,
struct ReportList *reports,
bool use_factory_settings,
bool use_empty_data,
+ bool use_data,
bool use_userdef,
const char *filepath_startup_override,
const char *app_template_override,
bool *r_is_factory_startup);
void wm_file_read_report(bContext *C, struct Main *bmain);
+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);
void WM_OT_userpref_autoexec_path_add(struct wmOperatorType *ot);
void WM_OT_userpref_autoexec_path_remove(struct wmOperatorType *ot);
void WM_OT_save_userpref(struct wmOperatorType *ot);
+void WM_OT_read_userpref(struct wmOperatorType *ot);
+void WM_OT_read_factory_userpref(struct wmOperatorType *ot);
void WM_OT_read_history(struct wmOperatorType *ot);
void WM_OT_read_homefile(struct wmOperatorType *ot);
void WM_OT_read_factory_settings(struct wmOperatorType *ot);