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:
authorAntonioya <blendergit@gmail.com>2019-07-23 10:46:29 +0300
committerAntonioya <blendergit@gmail.com>2019-07-23 10:46:29 +0300
commit2204bfcf9e1c3a38e60830bd97775dd72158f4d6 (patch)
tree4f9c827389a23a431f8771b4ca02f410860c0242 /source/blender
parentf64db794ee690f05905ace0a66d81d2e75549b90 (diff)
parent34ad6da4a06ef46cd19945f61cc5f968538546a8 (diff)
Merge branch 'master' into temp-gpencil-drw-engine
Diffstat (limited to 'source/blender')
-rw-r--r--source/blender/alembic/intern/abc_exporter.cc9
-rw-r--r--source/blender/alembic/intern/abc_mesh.cc14
-rw-r--r--source/blender/alembic/intern/abc_object.cc3
-rw-r--r--source/blender/blenkernel/BKE_action.h1
-rw-r--r--source/blender/blenkernel/BKE_armature.h2
-rw-r--r--source/blender/blenkernel/BKE_blender_version.h2
-rw-r--r--source/blender/blenkernel/BKE_collection.h2
-rw-r--r--source/blender/blenkernel/BKE_gpencil.h1
-rw-r--r--source/blender/blenkernel/BKE_gpencil_modifier.h23
-rw-r--r--source/blender/blenkernel/BKE_library.h2
-rw-r--r--source/blender/blenkernel/BKE_library_query.h7
-rw-r--r--source/blender/blenkernel/BKE_mesh_iterators.h5
-rw-r--r--source/blender/blenkernel/BKE_modifier.h1
-rw-r--r--source/blender/blenkernel/BKE_multires.h4
-rw-r--r--source/blender/blenkernel/BKE_object.h1
-rw-r--r--source/blender/blenkernel/BKE_packedFile.h96
-rw-r--r--source/blender/blenkernel/BKE_rigidbody.h6
-rw-r--r--source/blender/blenkernel/BKE_screen.h3
-rw-r--r--source/blender/blenkernel/BKE_text.h51
-rw-r--r--source/blender/blenkernel/BKE_undo_system.h7
-rw-r--r--source/blender/blenkernel/intern/action.c53
-rw-r--r--source/blender/blenkernel/intern/armature.c25
-rw-r--r--source/blender/blenkernel/intern/blendfile.c9
-rw-r--r--source/blender/blenkernel/intern/brush.c14
-rw-r--r--source/blender/blenkernel/intern/cachefile.c8
-rw-r--r--source/blender/blenkernel/intern/cloth.c6
-rw-r--r--source/blender/blenkernel/intern/collection.c12
-rw-r--r--source/blender/blenkernel/intern/colortools.c82
-rw-r--r--source/blender/blenkernel/intern/curve.c29
-rw-r--r--source/blender/blenkernel/intern/customdata.c7
-rw-r--r--source/blender/blenkernel/intern/data_transfer.c6
-rw-r--r--source/blender/blenkernel/intern/dynamicpaint.c34
-rw-r--r--source/blender/blenkernel/intern/font.c25
-rw-r--r--source/blender/blenkernel/intern/gpencil.c82
-rw-r--r--source/blender/blenkernel/intern/gpencil_modifier.c85
-rw-r--r--source/blender/blenkernel/intern/image.c31
-rw-r--r--source/blender/blenkernel/intern/image_gen.c8
-rw-r--r--source/blender/blenkernel/intern/layer.c7
-rw-r--r--source/blender/blenkernel/intern/library.c10
-rw-r--r--source/blender/blenkernel/intern/mask_rasterize.c12
-rw-r--r--source/blender/blenkernel/intern/mball_tessellate.c2
-rw-r--r--source/blender/blenkernel/intern/mesh.c24
-rw-r--r--source/blender/blenkernel/intern/mesh_convert.c5
-rw-r--r--source/blender/blenkernel/intern/mesh_evaluate.c6
-rw-r--r--source/blender/blenkernel/intern/mesh_iterators.c48
-rw-r--r--source/blender/blenkernel/intern/mesh_mapping.c31
-rw-r--r--source/blender/blenkernel/intern/modifier.c35
-rw-r--r--source/blender/blenkernel/intern/multires.c14
-rw-r--r--source/blender/blenkernel/intern/node.c2
-rw-r--r--source/blender/blenkernel/intern/object.c3
-rw-r--r--source/blender/blenkernel/intern/object_update.c16
-rw-r--r--source/blender/blenkernel/intern/packedFile.c149
-rw-r--r--source/blender/blenkernel/intern/particle.c6
-rw-r--r--source/blender/blenkernel/intern/particle_distribute.c34
-rw-r--r--source/blender/blenkernel/intern/pointcache.c4
-rw-r--r--source/blender/blenkernel/intern/rigidbody.c60
-rw-r--r--source/blender/blenkernel/intern/scene.c18
-rw-r--r--source/blender/blenkernel/intern/screen.c17
-rw-r--r--source/blender/blenkernel/intern/sequencer.c7
-rw-r--r--source/blender/blenkernel/intern/smoke.c4
-rw-r--r--source/blender/blenkernel/intern/softbody.c6
-rw-r--r--source/blender/blenkernel/intern/sound.c6
-rw-r--r--source/blender/blenkernel/intern/subdiv_ccg.c18
-rw-r--r--source/blender/blenkernel/intern/subdiv_mesh.c32
-rw-r--r--source/blender/blenkernel/intern/text.c1430
-rw-r--r--source/blender/blenkernel/intern/tracking_stabilize.c4
-rw-r--r--source/blender/blenkernel/intern/undo_system.c97
-rw-r--r--source/blender/blenkernel/intern/writeffmpeg.c8
-rw-r--r--source/blender/blenlib/BLI_math_geom.h7
-rw-r--r--source/blender/blenlib/intern/BLI_heap.c2
-rw-r--r--source/blender/blenlib/intern/math_geom.c40
-rw-r--r--source/blender/blenlib/intern/path_util.c4
-rw-r--r--source/blender/blenlib/intern/storage.c36
-rw-r--r--source/blender/blenloader/intern/readfile.c71
-rw-r--r--source/blender/blenloader/intern/versioning_280.c35
-rw-r--r--source/blender/blenloader/intern/writefile.c6
-rw-r--r--source/blender/bmesh/intern/bmesh_mesh_conv.c2
-rw-r--r--source/blender/bmesh/operators/bmo_inset.c2
-rw-r--r--source/blender/bmesh/tools/bmesh_bevel.c2
-rw-r--r--source/blender/bmesh/tools/bmesh_intersect.c2
-rw-r--r--source/blender/collada/ArmatureImporter.cpp4
-rw-r--r--source/blender/collada/BCAnimationSampler.cpp17
-rw-r--r--source/blender/collada/DocumentImporter.cpp3
-rw-r--r--source/blender/collada/EffectExporter.cpp18
-rw-r--r--source/blender/collada/Materials.cpp47
-rw-r--r--source/blender/depsgraph/DEG_depsgraph_build.h3
-rw-r--r--source/blender/depsgraph/DEG_depsgraph_query.h11
-rw-r--r--source/blender/depsgraph/intern/builder/deg_builder_nodes.cc47
-rw-r--r--source/blender/depsgraph/intern/builder/deg_builder_nodes.h1
-rw-r--r--source/blender/depsgraph/intern/builder/deg_builder_nodes_scene.cc2
-rw-r--r--source/blender/depsgraph/intern/builder/deg_builder_relations.cc74
-rw-r--r--source/blender/depsgraph/intern/builder/deg_builder_relations.h3
-rw-r--r--source/blender/depsgraph/intern/builder/deg_builder_relations_scene.cc3
-rw-r--r--source/blender/depsgraph/intern/builder/deg_builder_rna.cc4
-rw-r--r--source/blender/depsgraph/intern/builder/deg_builder_rna.h2
-rw-r--r--source/blender/depsgraph/intern/depsgraph_build.cc33
-rw-r--r--source/blender/depsgraph/intern/depsgraph_query.cc2
-rw-r--r--source/blender/depsgraph/intern/depsgraph_query_foreach.cc106
-rw-r--r--source/blender/depsgraph/intern/eval/deg_eval_copy_on_write.cc76
-rw-r--r--source/blender/depsgraph/intern/node/deg_node.cc128
-rw-r--r--source/blender/depsgraph/intern/node/deg_node.h10
-rw-r--r--source/blender/draw/engines/eevee/eevee_depth_of_field.c3
-rw-r--r--source/blender/draw/engines/eevee/eevee_effects.c6
-rw-r--r--source/blender/draw/engines/eevee/eevee_engine.c10
-rw-r--r--source/blender/draw/engines/eevee/eevee_lightprobes.c3
-rw-r--r--source/blender/draw/engines/eevee/eevee_lookdev.c2
-rw-r--r--source/blender/draw/engines/eevee/eevee_materials.c9
-rw-r--r--source/blender/draw/engines/eevee/eevee_private.h14
-rw-r--r--source/blender/draw/engines/eevee/eevee_render.c32
-rw-r--r--source/blender/draw/engines/eevee/eevee_screen_raytrace.c9
-rw-r--r--source/blender/draw/engines/eevee/eevee_temporal_sampling.c1
-rw-r--r--source/blender/draw/engines/eevee/eevee_volumes.c2
-rw-r--r--source/blender/draw/engines/eevee/shaders/bsdf_common_lib.glsl3
-rw-r--r--source/blender/draw/engines/eevee/shaders/common_uniforms_lib.glsl1
-rw-r--r--source/blender/draw/engines/eevee/shaders/lit_surface_frag.glsl295
-rw-r--r--source/blender/draw/engines/eevee/shaders/volumetric_integration_frag.glsl4
-rw-r--r--source/blender/draw/engines/eevee/shaders/volumetric_resolve_frag.glsl4
-rw-r--r--source/blender/draw/engines/gpencil/gpencil_draw_utils.c8
-rw-r--r--source/blender/draw/engines/gpencil/gpencil_engine.c11
-rw-r--r--source/blender/draw/engines/gpencil/gpencil_engine.h16
-rw-r--r--source/blender/draw/engines/gpencil/gpencil_render.c9
-rw-r--r--source/blender/draw/engines/gpencil/shaders/gpencil_fill_frag.glsl14
-rw-r--r--source/blender/draw/engines/workbench/shaders/workbench_prepass_vert.glsl12
-rw-r--r--source/blender/draw/engines/workbench/shaders/workbench_shadow_geom.glsl3
-rw-r--r--source/blender/draw/engines/workbench/workbench_data.c10
-rw-r--r--source/blender/draw/engines/workbench/workbench_deferred.c108
-rw-r--r--source/blender/draw/engines/workbench/workbench_effect_dof.c2
-rw-r--r--source/blender/draw/engines/workbench/workbench_forward.c118
-rw-r--r--source/blender/draw/engines/workbench/workbench_materials.c101
-rw-r--r--source/blender/draw/engines/workbench/workbench_private.h47
-rw-r--r--source/blender/draw/intern/draw_armature.c47
-rw-r--r--source/blender/draw/intern/draw_cache.c4
-rw-r--r--source/blender/draw/intern/draw_cache_impl_curve.c3
-rw-r--r--source/blender/draw/intern/draw_cache_impl_mesh.c292
-rw-r--r--source/blender/draw/intern/draw_cache_impl_particles.c17
-rw-r--r--source/blender/draw/intern/draw_hair_private.h2
-rw-r--r--source/blender/draw/intern/draw_instance_data.c3
-rw-r--r--source/blender/draw/intern/draw_manager.c33
-rw-r--r--source/blender/draw/intern/draw_manager_shader.c17
-rw-r--r--source/blender/draw/modes/edit_mesh_mode_text.c2
-rw-r--r--source/blender/draw/modes/edit_text_mode.c4
-rw-r--r--source/blender/draw/modes/object_mode.c19
-rw-r--r--source/blender/draw/modes/overlay_mode.c13
-rw-r--r--source/blender/draw/modes/paint_texture_mode.c210
-rw-r--r--source/blender/draw/modes/paint_vertex_mode.c5
-rw-r--r--source/blender/draw/modes/shaders/edit_lattice_overlay_loosevert_vert.glsl2
-rw-r--r--source/blender/draw/modes/shaders/paint_texture_frag.glsl23
-rw-r--r--source/blender/draw/modes/shaders/paint_texture_vert.glsl12
-rw-r--r--source/blender/draw/modes/shaders/paint_vertex_vert.glsl4
-rw-r--r--source/blender/draw/modes/shaders/paint_wire_vert.glsl10
-rw-r--r--source/blender/draw/modes/shaders/particle_strand_vert.glsl7
-rw-r--r--source/blender/editors/animation/anim_channels_edit.c3
-rw-r--r--source/blender/editors/animation/anim_filter.c6
-rw-r--r--source/blender/editors/animation/anim_motion_paths.c4
-rw-r--r--source/blender/editors/animation/keyframing.c33
-rw-r--r--source/blender/editors/armature/armature_add.c2
-rw-r--r--source/blender/editors/armature/armature_edit.c5
-rw-r--r--source/blender/editors/armature/armature_relations.c5
-rw-r--r--source/blender/editors/armature/armature_utils.c12
-rw-r--r--source/blender/editors/armature/editarmature_undo.c3
-rw-r--r--source/blender/editors/armature/pose_edit.c4
-rw-r--r--source/blender/editors/armature/pose_select.c48
-rw-r--r--source/blender/editors/armature/pose_slide.c2
-rw-r--r--source/blender/editors/curve/editcurve_undo.c6
-rw-r--r--source/blender/editors/curve/editfont.c16
-rw-r--r--source/blender/editors/curve/editfont_undo.c11
-rw-r--r--source/blender/editors/gizmo_library/gizmo_types/cage2d_gizmo.c1
-rw-r--r--source/blender/editors/gizmo_library/gizmo_types/dial3d_gizmo.c21
-rw-r--r--source/blender/editors/gpencil/drawgpencil.c2
-rw-r--r--source/blender/editors/gpencil/gpencil_brush.c23
-rw-r--r--source/blender/editors/gpencil/gpencil_data.c58
-rw-r--r--source/blender/editors/gpencil/gpencil_edit.c84
-rw-r--r--source/blender/editors/gpencil/gpencil_interpolate.c5
-rw-r--r--source/blender/editors/gpencil/gpencil_paint.c2
-rw-r--r--source/blender/editors/gpencil/gpencil_primitive.c9
-rw-r--r--source/blender/editors/include/BIF_glutil.h2
-rw-r--r--source/blender/editors/include/ED_armature.h6
-rw-r--r--source/blender/editors/include/ED_mesh.h3
-rw-r--r--source/blender/editors/include/ED_object.h3
-rw-r--r--source/blender/editors/include/ED_render.h3
-rw-r--r--source/blender/editors/include/ED_screen.h1
-rw-r--r--source/blender/editors/include/ED_text.h4
-rw-r--r--source/blender/editors/include/ED_transform_snap_object_context.h20
-rw-r--r--source/blender/editors/include/ED_undo.h3
-rw-r--r--source/blender/editors/include/UI_icons.h6
-rw-r--r--source/blender/editors/include/UI_interface.h2
-rw-r--r--source/blender/editors/include/UI_resources.h1
-rw-r--r--source/blender/editors/include/UI_view2d.h2
-rw-r--r--source/blender/editors/interface/interface.c3
-rw-r--r--source/blender/editors/interface/interface_align.c2
-rw-r--r--source/blender/editors/interface/interface_context_menu.c34
-rw-r--r--source/blender/editors/interface/interface_eyedropper_colorband.c48
-rw-r--r--source/blender/editors/interface/interface_eyedropper_depth.c6
-rw-r--r--source/blender/editors/interface/interface_handlers.c56
-rw-r--r--source/blender/editors/interface/interface_icons.c5
-rw-r--r--source/blender/editors/interface/interface_ops.c25
-rw-r--r--source/blender/editors/interface/interface_region_color_picker.c20
-rw-r--r--source/blender/editors/interface/interface_region_hud.c6
-rw-r--r--source/blender/editors/interface/interface_region_popover.c4
-rw-r--r--source/blender/editors/interface/interface_templates.c2
-rw-r--r--source/blender/editors/interface/interface_widgets.c2
-rw-r--r--source/blender/editors/interface/resources.c20
-rw-r--r--source/blender/editors/io/io_collada.c12
-rw-r--r--source/blender/editors/lattice/editlattice_undo.c17
-rw-r--r--source/blender/editors/mask/mask_add.c6
-rw-r--r--source/blender/editors/mask/mask_ops.c3
-rw-r--r--source/blender/editors/mesh/editmesh_bevel.c4
-rw-r--r--source/blender/editors/mesh/editmesh_tools.c709
-rw-r--r--source/blender/editors/mesh/editmesh_undo.c3
-rw-r--r--source/blender/editors/mesh/mesh_data.c34
-rw-r--r--source/blender/editors/metaball/editmball_undo.c3
-rw-r--r--source/blender/editors/object/object_add.c161
-rw-r--r--source/blender/editors/object/object_bake_api.c36
-rw-r--r--source/blender/editors/object/object_constraint.c182
-rw-r--r--source/blender/editors/object/object_select.c19
-rw-r--r--source/blender/editors/object/object_transform.c37
-rw-r--r--source/blender/editors/object/object_vgroup.c19
-rw-r--r--source/blender/editors/physics/particle_edit.c40
-rw-r--r--source/blender/editors/physics/particle_edit_undo.c3
-rw-r--r--source/blender/editors/physics/physics_fluid.c3
-rw-r--r--source/blender/editors/render/render_internal.c19
-rw-r--r--source/blender/editors/render/render_preview.c33
-rw-r--r--source/blender/editors/screen/glutil.c14
-rw-r--r--source/blender/editors/screen/screen_ops.c23
-rw-r--r--source/blender/editors/screen/screen_user_menu.c2
-rw-r--r--source/blender/editors/screen/screendump.c21
-rw-r--r--source/blender/editors/screen/workspace_edit.c64
-rw-r--r--source/blender/editors/sculpt_paint/paint_cursor.c6
-rw-r--r--source/blender/editors/sculpt_paint/paint_curve_undo.c3
-rw-r--r--source/blender/editors/sculpt_paint/paint_hide.c7
-rw-r--r--source/blender/editors/sculpt_paint/paint_image_proj.c5
-rw-r--r--source/blender/editors/sculpt_paint/paint_image_undo.c6
-rw-r--r--source/blender/editors/sculpt_paint/paint_mask.c6
-rw-r--r--source/blender/editors/sculpt_paint/paint_vertex.c59
-rw-r--r--source/blender/editors/sculpt_paint/sculpt.c4
-rw-r--r--source/blender/editors/sculpt_paint/sculpt_undo.c10
-rw-r--r--source/blender/editors/sound/sound_ops.c7
-rw-r--r--source/blender/editors/space_clip/clip_draw.c6
-rw-r--r--source/blender/editors/space_clip/clip_ops.c5
-rw-r--r--source/blender/editors/space_clip/space_clip.c8
-rw-r--r--source/blender/editors/space_clip/tracking_ops_plane.c6
-rw-r--r--source/blender/editors/space_file/file_ops.c8
-rw-r--r--source/blender/editors/space_image/image_draw.c5
-rw-r--r--source/blender/editors/space_image/image_ops.c10
-rw-r--r--source/blender/editors/space_image/space_image.c10
-rw-r--r--source/blender/editors/space_info/info_ops.c17
-rw-r--r--source/blender/editors/space_node/node_edit.c2
-rw-r--r--source/blender/editors/space_node/node_view.c2
-rw-r--r--source/blender/editors/space_outliner/outliner_collections.c2
-rw-r--r--source/blender/editors/space_outliner/outliner_draw.c79
-rw-r--r--source/blender/editors/space_outliner/outliner_tools.c97
-rw-r--r--source/blender/editors/space_outliner/outliner_tree.c4
-rw-r--r--source/blender/editors/space_sequencer/sequencer_draw.c8
-rw-r--r--source/blender/editors/space_text/text_autocomplete.c16
-rw-r--r--source/blender/editors/space_text/text_ops.c82
-rw-r--r--source/blender/editors/space_text/text_undo.c155
-rw-r--r--source/blender/editors/space_userpref/userpref_ops.c4
-rw-r--r--source/blender/editors/space_view3d/space_view3d.c3
-rw-r--r--source/blender/editors/space_view3d/view3d_draw.c14
-rw-r--r--source/blender/editors/space_view3d/view3d_edit.c5
-rw-r--r--source/blender/editors/space_view3d/view3d_gizmo_preselect_type.c2
-rw-r--r--source/blender/editors/space_view3d/view3d_gizmo_ruler.c41
-rw-r--r--source/blender/editors/space_view3d/view3d_iterators.c12
-rw-r--r--source/blender/editors/space_view3d/view3d_select.c94
-rw-r--r--source/blender/editors/space_view3d/view3d_snap.c36
-rw-r--r--source/blender/editors/space_view3d/view3d_view.c22
-rw-r--r--source/blender/editors/transform/transform.c58
-rw-r--r--source/blender/editors/transform/transform_constraints.c26
-rw-r--r--source/blender/editors/transform/transform_conversions.c113
-rw-r--r--source/blender/editors/transform/transform_gizmo_3d.c12
-rw-r--r--source/blender/editors/transform/transform_ops.c13
-rw-r--r--source/blender/editors/transform/transform_snap.c9
-rw-r--r--source/blender/editors/transform/transform_snap_object.c22
-rw-r--r--source/blender/editors/undo/ed_undo.c41
-rw-r--r--source/blender/editors/undo/memfile_undo.c6
-rw-r--r--source/blender/editors/util/ed_util.c16
-rw-r--r--source/blender/editors/util/select_buffer_utils.c6
-rw-r--r--source/blender/editors/uvedit/uvedit_draw.c9
-rw-r--r--source/blender/editors/uvedit/uvedit_unwrap_ops.c1
-rw-r--r--source/blender/freestyle/intern/python/BPy_FrsMaterial.cpp4
-rw-r--r--source/blender/freestyle/intern/python/BPy_StrokeAttribute.cpp4
-rw-r--r--source/blender/freestyle/intern/python/Interface0D/CurvePoint/BPy_StrokeVertex.cpp8
-rw-r--r--source/blender/freestyle/intern/python/Interface1D/BPy_Stroke.cpp10
-rw-r--r--source/blender/freestyle/intern/scene_graph/IndexedFaceSet.cpp2
-rw-r--r--source/blender/freestyle/intern/scene_graph/IndexedFaceSet.h2
-rw-r--r--source/blender/freestyle/intern/winged_edge/WXEdge.h2
-rw-r--r--source/blender/gpencil_modifiers/intern/MOD_gpencil_util.c5
-rw-r--r--source/blender/gpu/GPU_state.h2
-rw-r--r--source/blender/gpu/GPU_vertex_format.h2
-rw-r--r--source/blender/gpu/intern/gpu_buffers.c8
-rw-r--r--source/blender/gpu/intern/gpu_draw.c3
-rw-r--r--source/blender/gpu/intern/gpu_element.c2
-rw-r--r--source/blender/gpu/intern/gpu_extensions.c6
-rw-r--r--source/blender/gpu/intern/gpu_framebuffer.c2
-rw-r--r--source/blender/gpu/intern/gpu_matrix.c2
-rw-r--r--source/blender/gpu/intern/gpu_select_sample_query.c13
-rw-r--r--source/blender/gpu/intern/gpu_shader_interface.c6
-rw-r--r--source/blender/gpu/intern/gpu_state.c14
-rw-r--r--source/blender/gpu/intern/gpu_texture.c7
-rw-r--r--source/blender/gpu/intern/gpu_vertex_format.c5
-rw-r--r--source/blender/gpu/shaders/gpu_shader_gpencil_fill_frag.glsl20
-rw-r--r--source/blender/gpu/shaders/gpu_shader_material.glsl2
-rw-r--r--source/blender/imbuf/IMB_imbuf.h3
-rw-r--r--source/blender/imbuf/intern/allocimbuf.c11
-rw-r--r--source/blender/imbuf/intern/oiio/openimageio_api.cpp23
-rw-r--r--source/blender/imbuf/intern/openexr/openexr_api.cpp35
-rw-r--r--source/blender/imbuf/intern/rectop.c69
-rw-r--r--source/blender/makesdna/DNA_action_types.h1
-rw-r--r--source/blender/makesdna/DNA_customdata_types.h10
-rw-r--r--source/blender/makesdna/DNA_material_types.h2
-rw-r--r--source/blender/makesdna/DNA_meshdata_types.h1
-rw-r--r--source/blender/makesdna/DNA_packedFile_types.h16
-rw-r--r--source/blender/makesdna/DNA_text_types.h2
-rw-r--r--source/blender/makesdna/DNA_view3d_types.h4
-rw-r--r--source/blender/makesrna/intern/rna_action.c7
-rw-r--r--source/blender/makesrna/intern/rna_armature.c17
-rw-r--r--source/blender/makesrna/intern/rna_brush.c7
-rw-r--r--source/blender/makesrna/intern/rna_cloth.c2
-rw-r--r--source/blender/makesrna/intern/rna_gpencil.c35
-rw-r--r--source/blender/makesrna/intern/rna_gpencil_modifier.c2
-rw-r--r--source/blender/makesrna/intern/rna_image_api.c7
-rw-r--r--source/blender/makesrna/intern/rna_layer.c17
-rw-r--r--source/blender/makesrna/intern/rna_main_api.c2
-rw-r--r--source/blender/makesrna/intern/rna_material.c6
-rw-r--r--source/blender/makesrna/intern/rna_mesh.c3
-rw-r--r--source/blender/makesrna/intern/rna_nodetree.c8
-rw-r--r--source/blender/makesrna/intern/rna_object.c6
-rw-r--r--source/blender/makesrna/intern/rna_object_api.c84
-rw-r--r--source/blender/makesrna/intern/rna_object_force.c2
-rw-r--r--source/blender/makesrna/intern/rna_packedfile.c2
-rw-r--r--source/blender/makesrna/intern/rna_particle.c6
-rw-r--r--source/blender/makesrna/intern/rna_rna.c4
-rw-r--r--source/blender/makesrna/intern/rna_scene.c9
-rw-r--r--source/blender/makesrna/intern/rna_screen.c2
-rw-r--r--source/blender/makesrna/intern/rna_sculpt_paint.c5
-rw-r--r--source/blender/makesrna/intern/rna_sound.c24
-rw-r--r--source/blender/makesrna/intern/rna_sound_api.c8
-rw-r--r--source/blender/makesrna/intern/rna_space.c57
-rw-r--r--source/blender/makesrna/intern/rna_text_api.c4
-rw-r--r--source/blender/makesrna/intern/rna_userdef.c2
-rw-r--r--source/blender/makesrna/intern/rna_vfont_api.c8
-rw-r--r--source/blender/makesrna/intern/rna_wm.c20
-rw-r--r--source/blender/makesrna/intern/rna_wm_gizmo.c42
-rw-r--r--source/blender/modifiers/intern/MOD_bevel.c7
-rw-r--r--source/blender/modifiers/intern/MOD_cloth.c14
-rw-r--r--source/blender/modifiers/intern/MOD_decimate.c4
-rw-r--r--source/blender/modifiers/intern/MOD_dynamicpaint.c7
-rw-r--r--source/blender/modifiers/intern/MOD_mirror.c2
-rw-r--r--source/blender/modifiers/intern/MOD_particlesystem.c18
-rw-r--r--source/blender/modifiers/intern/MOD_screw.c13
-rw-r--r--source/blender/modifiers/intern/MOD_solidify.c6
-rw-r--r--source/blender/nodes/composite/nodes/node_composite_image.c2
-rw-r--r--source/blender/nodes/composite/nodes/node_composite_movieclip.c2
-rw-r--r--source/blender/nodes/composite/nodes/node_composite_moviedistortion.c2
-rw-r--r--source/blender/nodes/composite/nodes/node_composite_stabilize2d.c2
-rw-r--r--source/blender/nodes/composite/nodes/node_composite_switchview.c3
-rw-r--r--source/blender/nodes/shader/nodes/node_shader_math.c53
-rw-r--r--source/blender/nodes/shader/nodes/node_shader_shaderToRgb.c4
-rw-r--r--source/blender/nodes/shader/nodes/node_shader_vectMath.c4
-rw-r--r--source/blender/physics/intern/hair_volume.cpp4
-rw-r--r--source/blender/python/generic/imbuf_py_api.c52
-rw-r--r--source/blender/python/intern/bpy.c52
-rw-r--r--source/blender/python/intern/bpy_interface.c2
-rw-r--r--source/blender/python/mathutils/mathutils_Vector.c914
-rw-r--r--source/blender/render/intern/source/render_result.c6
-rw-r--r--source/blender/windowmanager/WM_api.h7
-rw-r--r--source/blender/windowmanager/WM_types.h369
-rw-r--r--source/blender/windowmanager/gizmo/WM_gizmo_types.h5
-rw-r--r--source/blender/windowmanager/gizmo/intern/wm_gizmo_group.c9
-rw-r--r--source/blender/windowmanager/gizmo/intern/wm_gizmo_map.c59
-rw-r--r--source/blender/windowmanager/intern/wm_draw.c44
-rw-r--r--source/blender/windowmanager/intern/wm_event_system.c22
-rw-r--r--source/blender/windowmanager/intern/wm_files.c39
-rw-r--r--source/blender/windowmanager/intern/wm_files_link.c44
-rw-r--r--source/blender/windowmanager/intern/wm_init_exit.c2
-rw-r--r--source/blender/windowmanager/intern/wm_jobs.c19
-rw-r--r--source/blender/windowmanager/intern/wm_operators.c272
-rw-r--r--source/blender/windowmanager/intern/wm_utils.c2
-rw-r--r--source/blender/windowmanager/intern/wm_window.c19
379 files changed, 6318 insertions, 5054 deletions
diff --git a/source/blender/alembic/intern/abc_exporter.cc b/source/blender/alembic/intern/abc_exporter.cc
index e39b5686c82..56fb5a68402 100644
--- a/source/blender/alembic/intern/abc_exporter.cc
+++ b/source/blender/alembic/intern/abc_exporter.cc
@@ -165,6 +165,15 @@ static bool export_object(const ExportSettings *const settings,
}
}
+ Object *ob_eval = DEG_get_evaluated_object(settings->depsgraph, base->object);
+ if ((ob_eval->id.tag & LIB_TAG_COPIED_ON_WRITE) == 0) {
+ /* XXX fix after 2.80: the object was not part of the depsgraph, and thus we cannot get the
+ * evaluated copy to export. This will be handled more elegantly in the new
+ * AbstractHierarchyIterator that Sybren is working on. This condition is temporary, and avoids
+ * a BLI_assert() failure getting the evaluated mesh of this object. */
+ return false;
+ }
+
// if (settings->renderable_only && (ob->restrictflag & OB_RESTRICT_RENDER)) {
// return false;
// }
diff --git a/source/blender/alembic/intern/abc_mesh.cc b/source/blender/alembic/intern/abc_mesh.cc
index de227be0044..b0129a358ec 100644
--- a/source/blender/alembic/intern/abc_mesh.cc
+++ b/source/blender/alembic/intern/abc_mesh.cc
@@ -409,6 +409,7 @@ void AbcGenericMeshWriter::writeMesh(struct Mesh *mesh)
{
std::vector<Imath::V3f> points, normals;
std::vector<int32_t> poly_verts, loop_counts;
+ std::vector<Imath::V3f> velocities;
bool smooth_normal = false;
@@ -458,9 +459,7 @@ void AbcGenericMeshWriter::writeMesh(struct Mesh *mesh)
}
if (m_is_liquid) {
- std::vector<Imath::V3f> velocities;
getVelocities(mesh, velocities);
-
m_mesh_sample.setVelocities(V3fArraySample(velocities));
}
@@ -973,8 +972,7 @@ static void *add_customdata_cb(void *user_data, const char *name, int data_type)
return cd_ptr;
}
- /* create a new layer, taking care to construct the hopefully-soon-to-be-removed
- * CD_MTEXPOLY layer too, with the same name. */
+ /* Create a new layer. */
numloops = mesh->totloop;
cd_ptr = CustomData_add_layer_named(loopdata, cd_data_type, CD_DEFAULT, NULL, numloops, name);
return cd_ptr;
@@ -1124,7 +1122,9 @@ Mesh *AbcMeshReader::read_mesh(Mesh *existing_mesh,
sample = m_schema.getValue(sample_sel);
}
catch (Alembic::Util::Exception &ex) {
- *err_str = "Error reading mesh sample; more detail on the console";
+ if (err_str != nullptr) {
+ *err_str = "Error reading mesh sample; more detail on the console";
+ }
printf("Alembic: error reading mesh sample for '%s/%s' at time %f: %s\n",
m_iobject.getFullName().c_str(),
m_schema.getName().c_str(),
@@ -1419,7 +1419,9 @@ Mesh *AbcSubDReader::read_mesh(Mesh *existing_mesh,
sample = m_schema.getValue(sample_sel);
}
catch (Alembic::Util::Exception &ex) {
- *err_str = "Error reading mesh sample; more detail on the console";
+ if (err_str != nullptr) {
+ *err_str = "Error reading mesh sample; more detail on the console";
+ }
printf("Alembic: error reading mesh sample for '%s/%s' at time %f: %s\n",
m_iobject.getFullName().c_str(),
m_schema.getName().c_str(),
diff --git a/source/blender/alembic/intern/abc_object.cc b/source/blender/alembic/intern/abc_object.cc
index e437273c1be..54450ce1cb2 100644
--- a/source/blender/alembic/intern/abc_object.cc
+++ b/source/blender/alembic/intern/abc_object.cc
@@ -263,9 +263,6 @@ void AbcObjectReader::setupObjectTransform(const float time)
data->cache_file = m_settings->cache_file;
id_us_plus(&data->cache_file->id);
-
- data->reader = reinterpret_cast<CacheReader *>(this);
- this->incref();
}
}
diff --git a/source/blender/blenkernel/BKE_action.h b/source/blender/blenkernel/BKE_action.h
index 69f3070fcba..a4863780d2e 100644
--- a/source/blender/blenkernel/BKE_action.h
+++ b/source/blender/blenkernel/BKE_action.h
@@ -160,6 +160,7 @@ void BKE_pose_copy_data(struct bPose **dst, const struct bPose *src, const bool
void BKE_pose_channel_copy_data(struct bPoseChannel *pchan, const struct bPoseChannel *pchan_from);
struct bPoseChannel *BKE_pose_channel_find_name(const struct bPose *pose, const char *name);
struct bPoseChannel *BKE_pose_channel_active(struct Object *ob);
+struct bPoseChannel *BKE_pose_channel_active_or_first_selected(struct Object *ob);
struct bPoseChannel *BKE_pose_channel_verify(struct bPose *pose, const char *name);
struct bPoseChannel *BKE_pose_channel_get_mirrored(const struct bPose *pose, const char *name);
diff --git a/source/blender/blenkernel/BKE_armature.h b/source/blender/blenkernel/BKE_armature.h
index 6839e13ffe1..73e62f6a7b3 100644
--- a/source/blender/blenkernel/BKE_armature.h
+++ b/source/blender/blenkernel/BKE_armature.h
@@ -90,6 +90,8 @@ void BKE_armature_bone_hash_free(struct bArmature *arm);
bool BKE_armature_bone_flag_test_recursive(const struct Bone *bone, int flag);
+void BKE_armature_refresh_layer_used(struct bArmature *arm);
+
float distfactor_to_bone(
const float vec[3], const float b1[3], const float b2[3], float r1, float r2, float rdist);
diff --git a/source/blender/blenkernel/BKE_blender_version.h b/source/blender/blenkernel/BKE_blender_version.h
index 5de8ad68c96..a400e4411cf 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 74
+#define BLENDER_SUBVERSION 75
/** Several breakages with 280, e.g. collections vs layers. */
#define BLENDER_MINVERSION 280
#define BLENDER_MINSUBVERSION 0
diff --git a/source/blender/blenkernel/BKE_collection.h b/source/blender/blenkernel/BKE_collection.h
index c1e36f5dd83..972ae5e8628 100644
--- a/source/blender/blenkernel/BKE_collection.h
+++ b/source/blender/blenkernel/BKE_collection.h
@@ -85,7 +85,7 @@ struct Scene *BKE_collection_master_scene_search(const struct Main *bmain,
/* Collection Objects */
-bool BKE_collection_has_object(struct Collection *collection, struct Object *ob);
+bool BKE_collection_has_object(struct Collection *collection, const struct Object *ob);
bool BKE_collection_has_object_recursive(struct Collection *collection, struct Object *ob);
struct Collection *BKE_collection_object_find(struct Main *bmain,
struct Scene *scene,
diff --git a/source/blender/blenkernel/BKE_gpencil.h b/source/blender/blenkernel/BKE_gpencil.h
index 0e3b0181fb9..ae1000d1b99 100644
--- a/source/blender/blenkernel/BKE_gpencil.h
+++ b/source/blender/blenkernel/BKE_gpencil.h
@@ -215,6 +215,7 @@ bool BKE_gpencil_smooth_stroke(struct bGPDstroke *gps, int i, float inf);
bool BKE_gpencil_smooth_stroke_strength(struct bGPDstroke *gps, int point_index, float influence);
bool BKE_gpencil_smooth_stroke_thickness(struct bGPDstroke *gps, int point_index, float influence);
bool BKE_gpencil_smooth_stroke_uv(struct bGPDstroke *gps, int point_index, float influence);
+bool BKE_gpencil_close_stroke(struct bGPDstroke *gps);
void BKE_gpencil_get_range_selected(struct bGPDlayer *gpl, int *r_initframe, int *r_endframe);
float BKE_gpencil_multiframe_falloff_calc(
diff --git a/source/blender/blenkernel/BKE_gpencil_modifier.h b/source/blender/blenkernel/BKE_gpencil_modifier.h
index d616c74520a..1f2f8ee57bf 100644
--- a/source/blender/blenkernel/BKE_gpencil_modifier.h
+++ b/source/blender/blenkernel/BKE_gpencil_modifier.h
@@ -52,10 +52,10 @@ struct bGPDstroke;
((((_md)->mode & eGpencilModifierMode_Editmode) == 0) && (_is_edit))
typedef enum {
- /* Should not be used, only for None modifier type */
+ /** Should not be used, only for None modifier type. */
eGpencilModifierTypeType_None,
- /* grease pencil modifiers */
+ /** Grease pencil modifiers. */
eGpencilModifierTypeType_Gpencil,
} GpencilModifierTypeType;
@@ -63,25 +63,26 @@ typedef enum {
eGpencilModifierTypeFlag_SupportsMapping = (1 << 0),
eGpencilModifierTypeFlag_SupportsEditmode = (1 << 1),
- /* For modifiers that support editmode this determines if the
- * modifier should be enabled by default in editmode. This should
+ /**
+ * For modifiers that support edit-mode this determines if the
+ * modifier should be enabled by default in edit-mode. This should
* only be used by modifiers that are relatively speedy and
- * also generally used in editmode, otherwise let the user enable
- * it by hand.
+ * also generally used in edit-mode, otherwise let the user enable it by hand.
*/
eGpencilModifierTypeFlag_EnableInEditmode = (1 << 2),
- /* For modifiers that require original data and so cannot
- * be placed after any non-deformative modifier.
+ /**
+ * For modifiers that require original data and so cannot
+ * be placed after any non-deform modifier.
*/
eGpencilModifierTypeFlag_RequiresOriginalData = (1 << 3),
- /* max one per type */
+ /** Max one per type. */
eGpencilModifierTypeFlag_Single = (1 << 4),
- /* can't be added manually by user */
+ /** Can't be added manually by user. */
eGpencilModifierTypeFlag_NoUserAdd = (1 << 5),
- /* can't be applied */
+ /** Can't be applied. */
eGpencilModifierTypeFlag_NoApply = (1 << 6),
} GpencilModifierTypeFlag;
diff --git a/source/blender/blenkernel/BKE_library.h b/source/blender/blenkernel/BKE_library.h
index 6f4dc3aff3b..28769ba7de9 100644
--- a/source/blender/blenkernel/BKE_library.h
+++ b/source/blender/blenkernel/BKE_library.h
@@ -231,7 +231,7 @@ void BKE_main_lib_objects_recalc_all(struct Main *bmain);
void BKE_main_id_repair_duplicate_names_listbase(struct ListBase *lb);
#define MAX_ID_FULL_NAME (64 + 64 + 3 + 1) /* 64 is MAX_ID_NAME - 2 */
-#define MAX_ID_FULL_NAME_UI (MAX_ID_FULL_NAME + 3) /* Adds 'keycode' two letters at begining. */
+#define MAX_ID_FULL_NAME_UI (MAX_ID_FULL_NAME + 3) /* Adds 'keycode' two letters at beginning. */
void BKE_id_full_name_get(char name[MAX_ID_FULL_NAME], const struct ID *id);
void BKE_id_full_name_ui_prefix_get(char name[MAX_ID_FULL_NAME_UI], const struct ID *id);
diff --git a/source/blender/blenkernel/BKE_library_query.h b/source/blender/blenkernel/BKE_library_query.h
index 4f74b2b5a6b..b959b55b1d6 100644
--- a/source/blender/blenkernel/BKE_library_query.h
+++ b/source/blender/blenkernel/BKE_library_query.h
@@ -65,9 +65,10 @@ enum {
enum {
IDWALK_RET_NOP = 0,
- IDWALK_RET_STOP_ITER = 1 << 0, /* Completely stop iteration. */
- IDWALK_RET_STOP_RECURSION =
- 1 << 1, /* Stop recursion, that is, do not loop over ID used by current one. */
+ /** Completely stop iteration. */
+ IDWALK_RET_STOP_ITER = 1 << 0,
+ /** Stop recursion, that is, do not loop over ID used by current one. */
+ IDWALK_RET_STOP_RECURSION = 1 << 1,
};
/**
diff --git a/source/blender/blenkernel/BKE_mesh_iterators.h b/source/blender/blenkernel/BKE_mesh_iterators.h
index 7bbd64c0bac..28fd4b8bc28 100644
--- a/source/blender/blenkernel/BKE_mesh_iterators.h
+++ b/source/blender/blenkernel/BKE_mesh_iterators.h
@@ -59,6 +59,11 @@ void BKE_mesh_foreach_mapped_face_center(
void (*func)(void *userData, int index, const float cent[3], const float no[3]),
void *userData,
MeshForeachFlag flag);
+void BKE_mesh_foreach_mapped_subdiv_face_center(
+ struct Mesh *mesh,
+ void (*func)(void *userData, int index, const float cent[3], const float no[3]),
+ void *userData,
+ MeshForeachFlag flag);
void BKE_mesh_foreach_mapped_vert_coords_get(struct Mesh *me_eval,
float (*r_cos)[3],
diff --git a/source/blender/blenkernel/BKE_modifier.h b/source/blender/blenkernel/BKE_modifier.h
index 30a366805b6..4aab2a346e7 100644
--- a/source/blender/blenkernel/BKE_modifier.h
+++ b/source/blender/blenkernel/BKE_modifier.h
@@ -382,6 +382,7 @@ struct Object *modifiers_isDeformedByMeshDeform(struct Object *ob);
struct Object *modifiers_isDeformedByLattice(struct Object *ob);
struct Object *modifiers_isDeformedByCurve(struct Object *ob);
bool modifiers_usesArmature(struct Object *ob, struct bArmature *arm);
+bool modifiers_usesSubsurfFacedots(struct Scene *scene, struct Object *ob);
bool modifiers_isCorrectableDeformed(struct Scene *scene, struct Object *ob);
void modifier_freeTemporaryData(struct ModifierData *md);
bool modifiers_isPreview(struct Object *ob);
diff --git a/source/blender/blenkernel/BKE_multires.h b/source/blender/blenkernel/BKE_multires.h
index 33672b5d397..c5955a9af8d 100644
--- a/source/blender/blenkernel/BKE_multires.h
+++ b/source/blender/blenkernel/BKE_multires.h
@@ -49,7 +49,9 @@ void multires_customdata_delete(struct Mesh *me);
void multires_set_tot_level(struct Object *ob, struct MultiresModifierData *mmd, int lvl);
-void multires_mark_as_modified(struct Object *ob, enum MultiresModifiedFlags flags);
+void multires_mark_as_modified(struct Depsgraph *depsgraph,
+ struct Object *object,
+ enum MultiresModifiedFlags flags);
void multires_force_update(struct Object *ob);
void multires_force_render_update(struct Object *ob);
diff --git a/source/blender/blenkernel/BKE_object.h b/source/blender/blenkernel/BKE_object.h
index fdd61580d9e..f59bf3579be 100644
--- a/source/blender/blenkernel/BKE_object.h
+++ b/source/blender/blenkernel/BKE_object.h
@@ -295,6 +295,7 @@ void BKE_object_eval_transform_all(struct Depsgraph *depsgraph,
void BKE_object_eval_update_shading(struct Depsgraph *depsgraph, struct Object *object);
void BKE_object_data_select_update(struct Depsgraph *depsgraph, struct ID *object_data);
+void BKE_object_select_update(struct Depsgraph *depsgraph, struct Object *object);
void BKE_object_eval_eval_base_flags(struct Depsgraph *depsgraph,
struct Scene *scene,
diff --git a/source/blender/blenkernel/BKE_packedFile.h b/source/blender/blenkernel/BKE_packedFile.h
index ad0f474a730..ab8d07d18e0 100644
--- a/source/blender/blenkernel/BKE_packedFile.h
+++ b/source/blender/blenkernel/BKE_packedFile.h
@@ -33,50 +33,84 @@ struct ReportList;
struct VFont;
struct bSound;
+enum ePF_FileCompare {
+ PF_CMP_EQUAL = 0,
+ PF_CMP_DIFFERS = 1,
+ PF_CMP_NOFILE = 2,
+};
+
+enum ePF_FileStatus {
+ PF_WRITE_ORIGINAL = 3,
+ PF_WRITE_LOCAL = 4,
+ PF_USE_LOCAL = 5,
+ PF_USE_ORIGINAL = 6,
+ PF_KEEP = 7,
+ PF_REMOVE = 8,
+ PF_NOOP = 9,
+
+ PF_ASK = 10,
+};
+
/* pack */
-struct PackedFile *dupPackedFile(const struct PackedFile *pf_src);
-struct PackedFile *newPackedFile(struct ReportList *reports,
- const char *filename,
- const char *relabase);
-struct PackedFile *newPackedFileMemory(void *mem, int memlen);
+struct PackedFile *BKE_packedfile_duplicate(const struct PackedFile *pf_src);
+struct PackedFile *BKE_packedfile_new(struct ReportList *reports,
+ const char *filename,
+ const char *relabase);
+struct PackedFile *BKE_packedfile_new_from_memory(void *mem, int memlen);
-void packAll(struct Main *bmain, struct ReportList *reports, bool verbose);
-void packLibraries(struct Main *bmain, struct ReportList *reports);
+void BKE_packedfile_pack_all(struct Main *bmain, struct ReportList *reports, bool verbose);
+void BKE_packedfile_pack_all_libraries(struct Main *bmain, struct ReportList *reports);
/* unpack */
-char *unpackFile(struct ReportList *reports,
- const char *ref_file_name,
- const char *abs_name,
- const char *local_name,
- struct PackedFile *pf,
- int how);
-int unpackVFont(struct Main *bmain, struct ReportList *reports, struct VFont *vfont, int how);
-int unpackSound(struct Main *bmain, struct ReportList *reports, struct bSound *sound, int how);
-int unpackImage(struct Main *bmain, struct ReportList *reports, struct Image *ima, int how);
-void unpackAll(struct Main *bmain, struct ReportList *reports, int how);
-int unpackLibraries(struct Main *bmain, struct ReportList *reports);
+char *BKE_packedfile_unpack_to_file(struct ReportList *reports,
+ const char *ref_file_name,
+ const char *abs_name,
+ const char *local_name,
+ struct PackedFile *pf,
+ enum ePF_FileStatus how);
+int BKE_packedfile_unpack_vfont(struct Main *bmain,
+ struct ReportList *reports,
+ struct VFont *vfont,
+ enum ePF_FileStatus how);
+int BKE_packedfile_unpack_sound(struct Main *bmain,
+ struct ReportList *reports,
+ struct bSound *sound,
+ enum ePF_FileStatus how);
+int BKE_packedfile_unpack_image(struct Main *bmain,
+ struct ReportList *reports,
+ struct Image *ima,
+ enum ePF_FileStatus how);
+void BKE_packedfile_unpack_all(struct Main *bmain,
+ struct ReportList *reports,
+ enum ePF_FileStatus how);
+int BKE_packedfile_unpack_all_libraries(struct Main *bmain, struct ReportList *reports);
-int writePackedFile(struct ReportList *reports,
- const char *ref_file_name,
- const char *filename,
- struct PackedFile *pf,
- const bool guimode);
+int BKE_packedfile_write_to_file(struct ReportList *reports,
+ const char *ref_file_name,
+ const char *filename,
+ struct PackedFile *pf,
+ const bool guimode);
/* free */
-void freePackedFile(struct PackedFile *pf);
+void BKE_packedfile_free(struct PackedFile *pf);
/* info */
-int countPackedFiles(struct Main *bmain);
-int checkPackedFile(const char *ref_file_name, const char *filename, struct PackedFile *pf);
+int BKE_packedfile_count_all(struct Main *bmain);
+enum ePF_FileCompare BKE_packedfile_compare_to_file(const char *ref_file_name,
+ const char *filename,
+ struct PackedFile *pf);
/* read */
-int seekPackedFile(struct PackedFile *pf, int offset, int whence);
-void rewindPackedFile(struct PackedFile *pf);
-int readPackedFile(struct PackedFile *pf, void *data, int size);
+int BKE_packedfile_seek(struct PackedFile *pf, int offset, int whence);
+void BKE_packedfile_rewind(struct PackedFile *pf);
+int BKE_packedfile_read(struct PackedFile *pf, void *data, int size);
/* ID should be not NULL, return 1 if there's a packed file */
-bool BKE_pack_check(struct ID *id);
+bool BKE_packedfile_id_check(struct ID *id);
/* ID should be not NULL, throws error when ID is Library */
-void BKE_unpack_id(struct Main *bmain, struct ID *id, struct ReportList *reports, int how);
+void BKE_packedfile_id_unpack(struct Main *bmain,
+ struct ID *id,
+ struct ReportList *reports,
+ enum ePF_FileStatus how);
#endif
diff --git a/source/blender/blenkernel/BKE_rigidbody.h b/source/blender/blenkernel/BKE_rigidbody.h
index cc3f5bbb42e..4c023f54e04 100644
--- a/source/blender/blenkernel/BKE_rigidbody.h
+++ b/source/blender/blenkernel/BKE_rigidbody.h
@@ -44,8 +44,10 @@ void BKE_rigidbody_free_constraint(struct Object *ob);
/* ...... */
-struct RigidBodyOb *BKE_rigidbody_copy_object(const struct Object *ob, const int flag);
-struct RigidBodyCon *BKE_rigidbody_copy_constraint(const struct Object *ob, const int flag);
+void BKE_rigidbody_object_copy(struct Main *bmain,
+ struct Object *ob_dst,
+ const struct Object *ob_src,
+ const int flag);
/* Callback format for performing operations on ID-pointers for rigidbody world. */
typedef void (*RigidbodyWorldIDFunc)(struct RigidBodyWorld *rbw,
diff --git a/source/blender/blenkernel/BKE_screen.h b/source/blender/blenkernel/BKE_screen.h
index dcf6d6c3907..5d3e7ad5ec2 100644
--- a/source/blender/blenkernel/BKE_screen.h
+++ b/source/blender/blenkernel/BKE_screen.h
@@ -350,6 +350,9 @@ void BKE_region_callback_refresh_tag_gizmomap_set(void (*callback)(struct wmGizm
struct ARegion *BKE_area_find_region_type(const struct ScrArea *sa, int type);
struct ARegion *BKE_area_find_region_active_win(struct ScrArea *sa);
struct ARegion *BKE_area_find_region_xy(struct ScrArea *sa, const int regiontype, int x, int y);
+struct ARegion *BKE_screen_find_region_xy(struct bScreen *sc, const int regiontype, int x, int y)
+ ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1);
+
struct ScrArea *BKE_screen_find_area_from_space(struct bScreen *sc,
struct SpaceLink *sl) ATTR_WARN_UNUSED_RESULT
ATTR_NONNULL(1, 2);
diff --git a/source/blender/blenkernel/BKE_text.h b/source/blender/blenkernel/BKE_text.h
index d26b9a86635..6509788932c 100644
--- a/source/blender/blenkernel/BKE_text.h
+++ b/source/blender/blenkernel/BKE_text.h
@@ -30,7 +30,6 @@ extern "C" {
struct Main;
struct Text;
struct TextLine;
-struct TextUndoBuf;
void BKE_text_free_lines(struct Text *text);
void BKE_text_free(struct Text *text);
@@ -49,12 +48,12 @@ void BKE_text_copy_data(struct Main *bmain,
const int flag);
struct Text *BKE_text_copy(struct Main *bmain, const struct Text *ta);
void BKE_text_make_local(struct Main *bmain, struct Text *text, const bool lib_local);
-void BKE_text_clear(struct Text *text, struct TextUndoBuf *utxt);
-void BKE_text_write(struct Text *text, struct TextUndoBuf *utxt, const char *str);
+void BKE_text_clear(struct Text *text);
+void BKE_text_write(struct Text *text, const char *str);
int BKE_text_file_modified_check(struct Text *text);
void BKE_text_file_modified_ignore(struct Text *text);
-char *txt_to_buf(struct Text *text);
+char *txt_to_buf(struct Text *text, int *r_buf_strlen);
void txt_clean_text(struct Text *text);
void txt_order_cursors(struct Text *text, const bool reverse);
int txt_find_string(struct Text *text, const char *findstr, int wrap, int match_case);
@@ -77,29 +76,26 @@ void txt_move_eol(struct Text *text, const bool sel);
void txt_move_toline(struct Text *text, unsigned int line, const bool sel);
void txt_move_to(struct Text *text, unsigned int line, unsigned int ch, const bool sel);
void txt_pop_sel(struct Text *text);
-void txt_delete_char(struct Text *text, struct TextUndoBuf *utxt);
-void txt_delete_word(struct Text *text, struct TextUndoBuf *utxt);
-void txt_delete_selected(struct Text *text, struct TextUndoBuf *utxt);
+void txt_delete_char(struct Text *text);
+void txt_delete_word(struct Text *text);
+void txt_delete_selected(struct Text *text);
void txt_sel_all(struct Text *text);
void txt_sel_clear(struct Text *text);
void txt_sel_line(struct Text *text);
-char *txt_sel_to_buf(struct Text *text);
-void txt_insert_buf(struct Text *text, struct TextUndoBuf *utxt, const char *in_buffer);
-void txt_undo_add_op(struct Text *text, struct TextUndoBuf *utxt, int op);
-void txt_do_undo(struct Text *text, struct TextUndoBuf *utxt);
-void txt_do_redo(struct Text *text, struct TextUndoBuf *utxt);
-void txt_split_curline(struct Text *text, struct TextUndoBuf *utxt);
-void txt_backspace_char(struct Text *text, struct TextUndoBuf *utxt);
-void txt_backspace_word(struct Text *text, struct TextUndoBuf *utxt);
-bool txt_add_char(struct Text *text, struct TextUndoBuf *utxt, unsigned int add);
-bool txt_add_raw_char(struct Text *text, struct TextUndoBuf *utxt, unsigned int add);
-bool txt_replace_char(struct Text *text, struct TextUndoBuf *utxt, unsigned int add);
-void txt_unindent(struct Text *text, struct TextUndoBuf *utxt);
-void txt_comment(struct Text *text, struct TextUndoBuf *utxt);
-void txt_indent(struct Text *text, struct TextUndoBuf *utxt);
-void txt_uncomment(struct Text *text, struct TextUndoBuf *utxt);
-void txt_move_lines(struct Text *text, struct TextUndoBuf *utxt, const int direction);
-void txt_duplicate_line(struct Text *text, struct TextUndoBuf *utxt);
+char *txt_sel_to_buf(struct Text *text, int *r_buf_strlen);
+void txt_insert_buf(struct Text *text, const char *in_buffer);
+void txt_split_curline(struct Text *text);
+void txt_backspace_char(struct Text *text);
+void txt_backspace_word(struct Text *text);
+bool txt_add_char(struct Text *text, unsigned int add);
+bool txt_add_raw_char(struct Text *text, unsigned int add);
+bool txt_replace_char(struct Text *text, unsigned int add);
+void txt_unindent(struct Text *text);
+void txt_comment(struct Text *text);
+void txt_indent(struct Text *text);
+void txt_uncomment(struct Text *text);
+void txt_move_lines(struct Text *text, const int direction);
+void txt_duplicate_line(struct Text *text);
int txt_setcurr_tab_spaces(struct Text *text, int space);
bool txt_cursor_is_line_start(struct Text *text);
bool txt_cursor_is_line_end(struct Text *text);
@@ -125,10 +121,9 @@ enum {
TXT_MOVE_LINE_DOWN = 1,
};
-typedef struct TextUndoBuf {
- char *buf;
- int pos, len;
-} TextUndoBuf;
+/* Fast non-validating buffer conversion for undo. */
+char *txt_to_buf_for_undo(struct Text *text, int *r_buf_strlen);
+void txt_from_buf_for_undo(struct Text *text, const char *buf, int buf_len);
#ifdef __cplusplus
}
diff --git a/source/blender/blenkernel/BKE_undo_system.h b/source/blender/blenkernel/BKE_undo_system.h
index d4cb9331605..50c29c456d1 100644
--- a/source/blender/blenkernel/BKE_undo_system.h
+++ b/source/blender/blenkernel/BKE_undo_system.h
@@ -101,12 +101,13 @@ typedef struct UndoType {
* None of these callbacks manage list add/removal.
*
* Note that 'step_encode_init' is optional,
- * some undo types need to perform operatons before undo push finishes.
+ * some undo types need to perform operations before undo push finishes.
*/
void (*step_encode_init)(struct bContext *C, UndoStep *us);
bool (*step_encode)(struct bContext *C, struct Main *bmain, UndoStep *us);
- void (*step_decode)(struct bContext *C, struct Main *bmain, UndoStep *us, int dir);
+ void (*step_decode)(
+ struct bContext *C, struct Main *bmain, UndoStep *us, int dir, bool is_final);
/**
* \note When freeing all steps,
@@ -122,7 +123,7 @@ typedef struct UndoType {
int step_size;
} UndoType;
-/* expose since we need to perform operations on spesific undo types (rarely). */
+/* Expose since we need to perform operations on specific undo types (rarely). */
extern const UndoType *BKE_UNDOSYS_TYPE_IMAGE;
extern const UndoType *BKE_UNDOSYS_TYPE_MEMFILE;
extern const UndoType *BKE_UNDOSYS_TYPE_PAINTCURVE;
diff --git a/source/blender/blenkernel/intern/action.c b/source/blender/blenkernel/intern/action.c
index 65b837048cb..a7159f85dc2 100644
--- a/source/blender/blenkernel/intern/action.c
+++ b/source/blender/blenkernel/intern/action.c
@@ -43,6 +43,7 @@
#include "BLT_translation.h"
#include "BKE_action.h"
+#include "BKE_armature.h"
#include "BKE_anim.h"
#include "BKE_animsys.h"
#include "BKE_constraint.h"
@@ -525,6 +526,38 @@ bPoseChannel *BKE_pose_channel_active(Object *ob)
}
/**
+ * Use this when detecting the "other selected bone",
+ * when we have multiple armatures in pose mode.
+ *
+ * In this case the active-selected is an obvious choice when finding the target for a
+ * constraint for eg. however from the users perspective the active pose bone of the
+ * active object is the _real_ active bone, so any other non-active selected bone
+ * is a candidate for being the other selected bone, see: T58447.
+ */
+bPoseChannel *BKE_pose_channel_active_or_first_selected(struct Object *ob)
+{
+ bArmature *arm = (ob) ? ob->data : NULL;
+
+ if (ELEM(NULL, ob, ob->pose, arm)) {
+ return NULL;
+ }
+
+ bPoseChannel *pchan = BKE_pose_channel_active(ob);
+ if (pchan && (pchan->bone->flag & BONE_SELECTED) && PBONE_VISIBLE(arm, pchan->bone)) {
+ return pchan;
+ }
+
+ for (pchan = ob->pose->chanbase.first; pchan; pchan = pchan->next) {
+ if (pchan->bone != NULL) {
+ if ((pchan->bone->flag & BONE_SELECTED) && PBONE_VISIBLE(arm, pchan->bone)) {
+ return pchan;
+ }
+ }
+ }
+ return NULL;
+}
+
+/**
* \see #ED_armature_ebone_get_mirrored (edit-mode, matching function)
*/
bPoseChannel *BKE_pose_channel_get_mirrored(const bPose *pose, const char *name)
@@ -729,6 +762,21 @@ void BKE_pose_channels_hash_free(bPose *pose)
}
}
+static void pose_channels_remove_internal_links(Object *ob, bPoseChannel *unlinked_pchan)
+{
+ LISTBASE_FOREACH (bPoseChannel *, pchan, &ob->pose->chanbase) {
+ if (pchan->bbone_prev == unlinked_pchan) {
+ pchan->bbone_prev = NULL;
+ }
+ if (pchan->bbone_next == unlinked_pchan) {
+ pchan->bbone_next = NULL;
+ }
+ if (pchan->custom_tx == unlinked_pchan) {
+ pchan->custom_tx = NULL;
+ }
+ }
+}
+
/**
* Selectively remove pose channels.
*/
@@ -747,6 +795,7 @@ void BKE_pose_channels_remove(Object *ob,
if (filter_fn(pchan->name, user_data)) {
/* Bone itself is being removed */
BKE_pose_channel_free(pchan);
+ pose_channels_remove_internal_links(ob, pchan);
if (ob->pose->chanhash) {
BLI_ghash_remove(ob->pose->chanhash, pchan->name, NULL, NULL);
}
@@ -1522,8 +1571,8 @@ void what_does_obaction(
workob->constraints.first = ob->constraints.first;
workob->constraints.last = ob->constraints.last;
- workob->pose =
- pose; /* need to set pose too, since this is used for both types of Action Constraint */
+ /* Need to set pose too, since this is used for both types of Action Constraint. */
+ workob->pose = pose;
if (pose) {
/* This function is most likely to be used with a temporary pose with a single bone in there.
* For such cases it makes no sense to create hash since it'll only waste CPU ticks on memory
diff --git a/source/blender/blenkernel/intern/armature.c b/source/blender/blenkernel/intern/armature.c
index df22aa1dcfb..c36acd1eae1 100644
--- a/source/blender/blenkernel/intern/armature.c
+++ b/source/blender/blenkernel/intern/armature.c
@@ -324,6 +324,24 @@ bool BKE_armature_bone_flag_test_recursive(const Bone *bone, int flag)
}
}
+static void armature_refresh_layer_used_recursive(bArmature *arm, ListBase *bones)
+{
+ for (Bone *bone = bones->first; bone; bone = bone->next) {
+ arm->layer_used |= bone->layer;
+ armature_refresh_layer_used_recursive(arm, &bone->childbase);
+ }
+}
+
+/* Update the layers_used variable after bones are moved between layer
+ * NOTE: Used to be done in drawing code in 2.7, but that won't work with
+ * Copy-on-Write, as drawing uses evaluated copies.
+ */
+void BKE_armature_refresh_layer_used(bArmature *arm)
+{
+ arm->layer_used = 0;
+ armature_refresh_layer_used_recursive(arm, &arm->bonebase);
+}
+
/* Finds the best possible extension to the name on a particular axis. (For renaming, check for
* unique names afterwards) strip_number: removes number extensions (TODO: not used)
* axis: the axis to name on
@@ -1370,7 +1388,12 @@ static void armature_vert_task(void *__restrict userdata,
if (use_dverts || armature_def_nr != -1) {
if (data->mesh) {
BLI_assert(i < data->mesh->totvert);
- dvert = data->mesh->dvert + i;
+ if (data->mesh->dvert != NULL) {
+ dvert = data->mesh->dvert + i;
+ }
+ else {
+ dvert = NULL;
+ }
}
else if (data->dverts && i < data->target_totvert) {
dvert = data->dverts + i;
diff --git a/source/blender/blenkernel/intern/blendfile.c b/source/blender/blenkernel/intern/blendfile.c
index 570805a01d0..afbd2627a2a 100644
--- a/source/blender/blenkernel/intern/blendfile.c
+++ b/source/blender/blenkernel/intern/blendfile.c
@@ -670,9 +670,14 @@ WorkspaceConfigFileData *BKE_blendfile_workspace_config_read(const char *filepat
}
if (bfd) {
- workspace_config = MEM_mallocN(sizeof(*workspace_config), __func__);
+ workspace_config = MEM_callocN(sizeof(*workspace_config), __func__);
workspace_config->main = bfd->main;
- workspace_config->workspaces = bfd->main->workspaces;
+
+ /* Only 2.80+ files have actual workspaces, don't try to use screens
+ * from older versions. */
+ if (bfd->main->versionfile >= 280) {
+ workspace_config->workspaces = bfd->main->workspaces;
+ }
MEM_freeN(bfd);
}
diff --git a/source/blender/blenkernel/intern/brush.c b/source/blender/blenkernel/intern/brush.c
index 78d965564e6..ec9a774a65c 100644
--- a/source/blender/blenkernel/intern/brush.c
+++ b/source/blender/blenkernel/intern/brush.c
@@ -73,8 +73,8 @@ static void brush_defaults(Brush *brush)
brush->topology_rake_factor = 0.0f;
brush->crease_pinch_factor = 0.5f;
brush->sculpt_plane = SCULPT_DISP_DIR_AREA;
- brush->plane_offset =
- 0.0f; /* how far above or below the plane that is found by averaging the faces */
+ /* How far above or below the plane that is found by averaging the faces. */
+ brush->plane_offset = 0.0f;
brush->plane_trim = 0.5f;
brush->clone.alpha = 0.5f;
brush->normal_weight = 0.0f;
@@ -82,7 +82,8 @@ static void brush_defaults(Brush *brush)
brush->flag |= BRUSH_ALPHA_PRESSURE;
/* BRUSH PAINT TOOL SETTINGS */
- brush->rgb[0] = 1.0f; /* default rgb color of the brush when painting - white */
+ /* Default rgb color of the brush when painting - white. */
+ brush->rgb[0] = 1.0f;
brush->rgb[1] = 1.0f;
brush->rgb[2] = 1.0f;
@@ -90,13 +91,14 @@ static void brush_defaults(Brush *brush)
/* BRUSH STROKE SETTINGS */
brush->flag |= (BRUSH_SPACE | BRUSH_SPACE_ATTEN);
- brush->spacing =
- 10; /* how far each brush dot should be spaced as a percentage of brush diameter */
+ /* How far each brush dot should be spaced as a percentage of brush diameter. */
+ brush->spacing = 10;
brush->smooth_stroke_radius = 75;
brush->smooth_stroke_factor = 0.9f;
- brush->rate = 0.1f; /* time delay between dots of paint or sculpting when doing airbrush mode */
+ /* Time delay between dots of paint or sculpting when doing airbrush mode. */
+ brush->rate = 0.1f;
brush->jitter = 0.0f;
diff --git a/source/blender/blenkernel/intern/cachefile.c b/source/blender/blenkernel/intern/cachefile.c
index 272413ece4a..2d6256f12e2 100644
--- a/source/blender/blenkernel/intern/cachefile.c
+++ b/source/blender/blenkernel/intern/cachefile.c
@@ -100,11 +100,11 @@ void BKE_cachefile_reader_open(CacheFile *cache_file,
void BKE_cachefile_reader_free(CacheFile *cache_file, struct CacheReader **reader)
{
#ifdef WITH_ALEMBIC
- if (cache_file) {
- BLI_assert(cache_file->id.tag & LIB_TAG_COPIED_ON_WRITE);
- }
-
if (*reader != NULL) {
+ if (cache_file) {
+ BLI_assert(cache_file->id.tag & LIB_TAG_COPIED_ON_WRITE);
+ }
+
CacheReader_free(*reader);
*reader = NULL;
diff --git a/source/blender/blenkernel/intern/cloth.c b/source/blender/blenkernel/intern/cloth.c
index dc238641a86..63d58f7e32e 100644
--- a/source/blender/blenkernel/intern/cloth.c
+++ b/source/blender/blenkernel/intern/cloth.c
@@ -105,8 +105,10 @@ void cloth_init(ClothModifierData *clmd)
clmd->sim_parms->maxspringlen = 10;
clmd->sim_parms->vgroup_mass = 0;
clmd->sim_parms->vgroup_shrink = 0;
- clmd->sim_parms->shrink_min =
- 0.0f; /* min amount the fabric will shrink by 0.0 = no shrinking, 1.0 = shrink to nothing*/
+
+ /* Min amount the fabric will shrink by 0.0 = no shrinking, 1.0 = shrink to nothing. */
+ clmd->sim_parms->shrink_min = 0.0f;
+
clmd->sim_parms->avg_spring_len = 0.0;
clmd->sim_parms->presets = 2; /* cotton as start setting */
clmd->sim_parms->timescale = 1.0f; /* speed factor, describes how fast cloth moves */
diff --git a/source/blender/blenkernel/intern/collection.c b/source/blender/blenkernel/intern/collection.c
index ac55846714b..965f6e4bc51 100644
--- a/source/blender/blenkernel/intern/collection.c
+++ b/source/blender/blenkernel/intern/collection.c
@@ -287,16 +287,6 @@ static Collection *collection_duplicate_recursive(Main *bmain,
collection_object_add(bmain, collection_new, ob_new, 0, true);
collection_object_remove(bmain, collection_new, ob_old, false);
-
- if (ob_new->rigidbody_object != NULL) {
- BLI_assert(ob_old->rigidbody_object != NULL);
- for (Scene *scene = bmain->scenes.first; scene != NULL; scene = scene->id.next) {
- if (scene->rigidbody_world != NULL &&
- BKE_collection_has_object(scene->rigidbody_world->group, ob_old)) {
- collection_object_add(bmain, scene->rigidbody_world->group, ob_new, 0, true);
- }
- }
- }
}
}
@@ -572,7 +562,7 @@ bool BKE_collection_object_cyclic_check(Main *bmain, Object *object, Collection
/******************* Collection Object Membership *******************/
-bool BKE_collection_has_object(Collection *collection, Object *ob)
+bool BKE_collection_has_object(Collection *collection, const Object *ob)
{
if (ELEM(NULL, collection, ob)) {
return false;
diff --git a/source/blender/blenkernel/intern/colortools.c b/source/blender/blenkernel/intern/colortools.c
index 45cb5e817d2..863d6351738 100644
--- a/source/blender/blenkernel/intern/colortools.c
+++ b/source/blender/blenkernel/intern/colortools.c
@@ -628,8 +628,6 @@ static void curvemap_make_table(CurveMap *cuma, const rctf *clipr)
{
CurveMapPoint *cmp = cuma->curve;
BezTriple *bezt;
- float *fp, *allpoints, *lastpoint, curf, range;
- int a, totpoint;
if (cuma->curve == NULL) {
return;
@@ -642,7 +640,7 @@ static void curvemap_make_table(CurveMap *cuma, const rctf *clipr)
/* hrmf... we now rely on blender ipo beziers, these are more advanced */
bezt = MEM_callocN(cuma->totpoint * sizeof(BezTriple), "beztarr");
- for (a = 0; a < cuma->totpoint; a++) {
+ for (int a = 0; a < cuma->totpoint; a++) {
cuma->mintable = min_ff(cuma->mintable, cmp[a].x);
cuma->maxtable = max_ff(cuma->maxtable, cmp[a].x);
bezt[a].vec[1][0] = cmp[a].x;
@@ -659,7 +657,7 @@ static void curvemap_make_table(CurveMap *cuma, const rctf *clipr)
}
const BezTriple *bezt_prev = NULL;
- for (a = 0; a < cuma->totpoint; a++) {
+ for (int a = 0; a < cuma->totpoint; a++) {
const BezTriple *bezt_next = (a != cuma->totpoint - 1) ? &bezt[a + 1] : NULL;
calchandle_curvemap(&bezt[a], bezt_prev, bezt_next);
bezt_prev = &bezt[a];
@@ -687,7 +685,7 @@ static void curvemap_make_table(CurveMap *cuma, const rctf *clipr)
sub_v3_v3v3(bezt[0].vec[0], bezt[0].vec[1], vec);
}
}
- a = cuma->totpoint - 1;
+ int a = cuma->totpoint - 1;
if (bezt[a].h2 == HD_AUTO) {
hlen = len_v3v3(bezt[a].vec[1], bezt[a].vec[0]); /* original handle length */
@@ -710,23 +708,25 @@ static void curvemap_make_table(CurveMap *cuma, const rctf *clipr)
if (cuma->table) {
MEM_freeN(cuma->table);
}
- totpoint = (cuma->totpoint - 1) * CM_RESOL;
- fp = allpoints = MEM_callocN(totpoint * 2 * sizeof(float), "table");
- for (a = 0; a < cuma->totpoint - 1; a++, fp += 2 * CM_RESOL) {
+ int totpoint = (cuma->totpoint - 1) * CM_RESOL;
+ float *allpoints = MEM_callocN(totpoint * 2 * sizeof(float), "table");
+ float *point = allpoints;
+
+ for (int a = 0; a < cuma->totpoint - 1; a++, point += 2 * CM_RESOL) {
correct_bezpart(bezt[a].vec[1], bezt[a].vec[2], bezt[a + 1].vec[0], bezt[a + 1].vec[1]);
BKE_curve_forward_diff_bezier(bezt[a].vec[1][0],
bezt[a].vec[2][0],
bezt[a + 1].vec[0][0],
bezt[a + 1].vec[1][0],
- fp,
+ point,
CM_RESOL - 1,
2 * sizeof(float));
BKE_curve_forward_diff_bezier(bezt[a].vec[1][1],
bezt[a].vec[2][1],
bezt[a + 1].vec[0][1],
bezt[a + 1].vec[1][1],
- fp + 1,
+ point + 1,
CM_RESOL - 1,
2 * sizeof(float));
}
@@ -734,49 +734,63 @@ static void curvemap_make_table(CurveMap *cuma, const rctf *clipr)
/* store first and last handle for extrapolation, unit length */
cuma->ext_in[0] = bezt[0].vec[0][0] - bezt[0].vec[1][0];
cuma->ext_in[1] = bezt[0].vec[0][1] - bezt[0].vec[1][1];
- range = sqrtf(cuma->ext_in[0] * cuma->ext_in[0] + cuma->ext_in[1] * cuma->ext_in[1]);
- cuma->ext_in[0] /= range;
- cuma->ext_in[1] /= range;
-
- a = cuma->totpoint - 1;
- cuma->ext_out[0] = bezt[a].vec[1][0] - bezt[a].vec[2][0];
- cuma->ext_out[1] = bezt[a].vec[1][1] - bezt[a].vec[2][1];
- range = sqrtf(cuma->ext_out[0] * cuma->ext_out[0] + cuma->ext_out[1] * cuma->ext_out[1]);
- cuma->ext_out[0] /= range;
- cuma->ext_out[1] /= range;
+ float ext_in_range = sqrtf(cuma->ext_in[0] * cuma->ext_in[0] +
+ cuma->ext_in[1] * cuma->ext_in[1]);
+ cuma->ext_in[0] /= ext_in_range;
+ cuma->ext_in[1] /= ext_in_range;
+
+ int out_a = cuma->totpoint - 1;
+ cuma->ext_out[0] = bezt[out_a].vec[1][0] - bezt[out_a].vec[2][0];
+ cuma->ext_out[1] = bezt[out_a].vec[1][1] - bezt[out_a].vec[2][1];
+ float ext_out_range = sqrtf(cuma->ext_out[0] * cuma->ext_out[0] +
+ cuma->ext_out[1] * cuma->ext_out[1]);
+ cuma->ext_out[0] /= ext_out_range;
+ cuma->ext_out[1] /= ext_out_range;
/* cleanup */
MEM_freeN(bezt);
- range = CM_TABLEDIV * (cuma->maxtable - cuma->mintable);
+ float range = CM_TABLEDIV * (cuma->maxtable - cuma->mintable);
cuma->range = 1.0f / range;
/* now make a table with CM_TABLE equal x distances */
- fp = allpoints;
- lastpoint = allpoints + 2 * (totpoint - 1);
+ float *firstpoint = allpoints;
+ float *lastpoint = allpoints + 2 * (totpoint - 1);
+ point = allpoints;
+
cmp = MEM_callocN((CM_TABLE + 1) * sizeof(CurveMapPoint), "dist table");
- for (a = 0; a <= CM_TABLE; a++) {
- curf = cuma->mintable + range * (float)a;
- cmp[a].x = curf;
+ for (int a = 0; a <= CM_TABLE; a++) {
+ float cur_x = cuma->mintable + range * (float)a;
+ cmp[a].x = cur_x;
- /* get the first x coordinate larger than curf */
- while (curf >= fp[0] && fp != lastpoint) {
- fp += 2;
+ /* Get the first point with x coordinate larger than cur_x. */
+ while (cur_x >= point[0] && point != lastpoint) {
+ point += 2;
}
- if (fp == allpoints || (curf >= fp[0] && fp == lastpoint)) {
- cmp[a].y = curvemap_calc_extend(cuma, curf, allpoints, lastpoint);
+
+ /* Check if we are on or outside the start or end point. */
+ if (point == firstpoint || (point == lastpoint && cur_x >= point[0])) {
+ if (compare_ff(cur_x, point[0], 1e-6f)) {
+ /* When on the point exactly, use the value directly to avoid precision
+ * issues with extrapolation of extreme slopes. */
+ cmp[a].y = point[1];
+ }
+ else {
+ /* Extrapolate values that lie outside the start and end point. */
+ cmp[a].y = curvemap_calc_extend(cuma, cur_x, firstpoint, lastpoint);
+ }
}
else {
- float fac1 = fp[0] - fp[-2];
- float fac2 = fp[0] - curf;
+ float fac1 = point[0] - point[-2];
+ float fac2 = point[0] - cur_x;
if (fac1 > FLT_EPSILON) {
fac1 = fac2 / fac1;
}
else {
fac1 = 0.0f;
}
- cmp[a].y = fac1 * fp[-1] + (1.0f - fac1) * fp[1];
+ cmp[a].y = fac1 * point[-1] + (1.0f - fac1) * point[1];
}
}
diff --git a/source/blender/blenkernel/intern/curve.c b/source/blender/blenkernel/intern/curve.c
index 5945fa4bf33..931c0ed73d3 100644
--- a/source/blender/blenkernel/intern/curve.c
+++ b/source/blender/blenkernel/intern/curve.c
@@ -54,6 +54,7 @@
#include "BKE_material.h"
#include "DEG_depsgraph.h"
+#include "DEG_depsgraph_query.h"
#include "CLG_log.h"
@@ -1817,8 +1818,9 @@ void BKE_curve_bevel_make(Object *ob, ListBase *disp)
fp[3] = fp[4] = 0.0;
fp[5] = cu->ext1;
}
- else if ((cu->flag & (CU_FRONT | CU_BACK)) == 0 &&
- cu->ext1 == 0.0f) { /* we make a full round bevel in that case */
+ else if ((cu->flag & (CU_FRONT | CU_BACK)) == 0 && cu->ext1 == 0.0f) {
+ /* We make a full round bevel in that case. */
+
nr = 4 + 2 * cu->bevresol;
dl = MEM_callocN(sizeof(DispList), "makebevelcurve p1");
@@ -4741,8 +4743,8 @@ bool BKE_nurb_check_valid_u(const Nurb *nu)
if (nu->pntsu < nu->orderu) {
return false;
}
- if (((nu->flagu & CU_NURB_CYCLIC) == 0) &&
- (nu->flagu & CU_NURB_BEZIER)) { /* Bezier U Endpoints */
+ if (((nu->flagu & CU_NURB_CYCLIC) == 0) && (nu->flagu & CU_NURB_BEZIER)) {
+ /* Bezier U Endpoints */
if (nu->orderu == 4) {
if (nu->pntsu < 5) {
return false; /* bezier with 4 orderu needs 5 points */
@@ -4768,8 +4770,8 @@ bool BKE_nurb_check_valid_v(const Nurb *nu)
if (nu->pntsv < nu->orderv) {
return false;
}
- if (((nu->flagv & CU_NURB_CYCLIC) == 0) &&
- (nu->flagv & CU_NURB_BEZIER)) { /* Bezier V Endpoints */
+ if (((nu->flagv & CU_NURB_CYCLIC) == 0) && (nu->flagv & CU_NURB_BEZIER)) {
+ /* Bezier V Endpoints */
if (nu->orderv == 4) {
if (nu->pntsv < 5) {
return false; /* bezier with 4 orderu needs 5 points */
@@ -5431,8 +5433,19 @@ void BKE_curve_rect_from_textbox(const struct Curve *cu,
void BKE_curve_eval_geometry(Depsgraph *depsgraph, Curve *curve)
{
DEG_debug_print_eval(depsgraph, __func__, curve->id.name, curve);
- if (curve->bb == NULL || (curve->bb->flag & BOUNDBOX_DIRTY)) {
- BKE_curve_texspace_calc(curve);
+ BKE_curve_texspace_calc(curve);
+ if (DEG_is_active(depsgraph)) {
+ Curve *curve_orig = (Curve *)DEG_get_original_id(&curve->id);
+ BoundBox *bb = curve->bb;
+ if (bb != NULL) {
+ if (curve_orig->bb == NULL) {
+ curve_orig->bb = MEM_mallocN(sizeof(*curve_orig->bb), __func__);
+ }
+ *curve_orig->bb = *bb;
+ copy_v3_v3(curve_orig->loc, curve->loc);
+ copy_v3_v3(curve_orig->size, curve->size);
+ copy_v3_v3(curve_orig->rot, curve->rot);
+ }
}
}
diff --git a/source/blender/blenkernel/intern/customdata.c b/source/blender/blenkernel/intern/customdata.c
index 76098db5fd1..1fb29745dba 100644
--- a/source/blender/blenkernel/intern/customdata.c
+++ b/source/blender/blenkernel/intern/customdata.c
@@ -26,6 +26,9 @@
#include "MEM_guardedalloc.h"
+/* Since we have versioning code here (CustomData_verify_versions()). */
+#define DNA_DEPRECATED_ALLOW
+
#include "DNA_customdata_types.h"
#include "DNA_meshdata_types.h"
#include "DNA_ID.h"
@@ -4191,8 +4194,8 @@ bool CustomData_verify_versions(struct CustomData *data, int index)
* Better to be safe here, and fix issue on the fly rather than crash... */
/* 0 structnum is used in writing code to tag layer types that should not be written. */
else if (typeInfo->structnum == 0 &&
- /* XXX Not sure why those two are exception, maybe that should be fixed? */
- !ELEM(layer->type, CD_PAINT_MASK, CD_FACEMAP)) {
+ /* XXX Not sure why those three are exception, maybe that should be fixed? */
+ !ELEM(layer->type, CD_PAINT_MASK, CD_FACEMAP, CD_MTEXPOLY)) {
keeplayer = false;
CLOG_WARN(&LOG, ".blend file read: removing a data layer that should not have been written");
}
diff --git a/source/blender/blenkernel/intern/data_transfer.c b/source/blender/blenkernel/intern/data_transfer.c
index 8dcf1f0d001..0414c6d0a02 100644
--- a/source/blender/blenkernel/intern/data_transfer.c
+++ b/source/blender/blenkernel/intern/data_transfer.c
@@ -1,3 +1,4 @@
+
/*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
@@ -85,6 +86,7 @@ void BKE_object_data_transfer_dttypes_to_cdmask(const int dtdata_types,
}
else if (cddata_type == CD_FAKE_LNOR) {
r_data_masks->vmask |= CD_MASK_NORMAL;
+ r_data_masks->pmask |= CD_MASK_NORMAL;
r_data_masks->lmask |= CD_MASK_NORMAL | CD_MASK_CUSTOMLOOPNORMAL;
}
}
@@ -1408,8 +1410,8 @@ bool BKE_object_data_transfer_ex(struct Depsgraph *depsgraph,
SpaceTransform auto_space_transform;
Mesh *me_src;
- bool dirty_nors_dst =
- true; /* Assumed always true if not using an evaluated mesh as destination. */
+ /* Assumed always true if not using an evaluated mesh as destination. */
+ bool dirty_nors_dst = true;
int i;
MDeformVert *mdef = NULL;
diff --git a/source/blender/blenkernel/intern/dynamicpaint.c b/source/blender/blenkernel/intern/dynamicpaint.c
index 8c6fbe98000..7e916feac24 100644
--- a/source/blender/blenkernel/intern/dynamicpaint.c
+++ b/source/blender/blenkernel/intern/dynamicpaint.c
@@ -1232,6 +1232,8 @@ void dynamicPaint_Modifier_copy(const struct DynamicPaintModifierData *pmd,
dynamicPaint_freeSurface(tpmd, tpmd->canvas->surfaces.first);
}
+ tpmd->canvas->active_sur = pmd->canvas->active_sur;
+
/* copy existing surfaces */
for (surface = pmd->canvas->surfaces.first; surface; surface = surface->next) {
DynamicPaintSurface *t_surface = dynamicPaint_createNewSurface(tpmd->canvas, NULL);
@@ -1298,7 +1300,7 @@ void dynamicPaint_Modifier_copy(const struct DynamicPaintModifierData *pmd,
BLI_strncpy(t_surface->output_name2, surface->output_name2, sizeof(t_surface->output_name2));
}
}
- else if (tpmd->brush) {
+ if (tpmd->brush) {
DynamicPaintBrushSettings *brush = pmd->brush, *t_brush = tpmd->brush;
t_brush->pmd = tpmd;
@@ -1930,7 +1932,8 @@ static Mesh *dynamicPaint_Modifier_apply(DynamicPaintModifierData *pmd, Object *
{
Mesh *result = BKE_mesh_copy_for_eval(mesh, false);
- if (pmd->canvas && !(pmd->canvas->flags & MOD_DPAINT_BAKING)) {
+ if (pmd->canvas && !(pmd->canvas->flags & MOD_DPAINT_BAKING) &&
+ pmd->type == MOD_DYNAMICPAINT_TYPE_CANVAS) {
DynamicPaintSurface *surface;
bool update_normals = false;
@@ -2020,6 +2023,8 @@ static Mesh *dynamicPaint_Modifier_apply(DynamicPaintModifierData *pmd, Object *
if (defgrp_index != -1 && !dvert && (surface->output_name[0] != '\0')) {
dvert = CustomData_add_layer(
&result->vdata, CD_MDEFORMVERT, CD_CALLOC, NULL, sData->total_points);
+ /* Make the dvert layer easily accessible from the mesh data. */
+ result->dvert = dvert;
}
if (defgrp_index != -1 && dvert) {
int i;
@@ -2070,7 +2075,7 @@ static Mesh *dynamicPaint_Modifier_apply(DynamicPaintModifierData *pmd, Object *
}
}
/* make a copy of mesh to use as brush data */
- if (pmd->brush) {
+ else if (pmd->brush && pmd->type == MOD_DYNAMICPAINT_TYPE_BRUSH) {
DynamicPaintRuntime *runtime_data = dynamicPaint_Modifier_runtime_ensure(pmd);
if (runtime_data->brush_mesh != NULL) {
BKE_id_free(NULL, runtime_data->brush_mesh);
@@ -2198,24 +2203,11 @@ Mesh *dynamicPaint_Modifier_do(DynamicPaintModifierData *pmd,
Object *ob,
Mesh *mesh)
{
- if (pmd->canvas) {
- Mesh *ret;
-
- /* Update canvas data for a new frame */
- dynamicPaint_frameUpdate(pmd, depsgraph, scene, ob, mesh);
-
- /* Return output mesh */
- ret = dynamicPaint_Modifier_apply(pmd, ob, mesh);
+ /* Update canvas data for a new frame */
+ dynamicPaint_frameUpdate(pmd, depsgraph, scene, ob, mesh);
- return ret;
- }
- else {
- /* Update canvas data for a new frame */
- dynamicPaint_frameUpdate(pmd, depsgraph, scene, ob, mesh);
-
- /* Return output mesh */
- return dynamicPaint_Modifier_apply(pmd, ob, mesh);
- }
+ /* Return output mesh */
+ return dynamicPaint_Modifier_apply(pmd, ob, mesh);
}
/* -------------------------------------------------------------------- */
@@ -6252,7 +6244,7 @@ static int dynamicPaint_doStep(Depsgraph *depsgraph,
if (md && md->mode & (eModifierMode_Realtime | eModifierMode_Render)) {
DynamicPaintModifierData *pmd2 = (DynamicPaintModifierData *)md;
/* make sure we're dealing with a brush */
- if (pmd2->brush) {
+ if (pmd2->brush && pmd2->type == MOD_DYNAMICPAINT_TYPE_BRUSH) {
DynamicPaintBrushSettings *brush = pmd2->brush;
/* calculate brush speed vectors if required */
diff --git a/source/blender/blenkernel/intern/font.c b/source/blender/blenkernel/intern/font.c
index 3f8fc697c6c..a0216e9b413 100644
--- a/source/blender/blenkernel/intern/font.c
+++ b/source/blender/blenkernel/intern/font.c
@@ -86,7 +86,7 @@ void BKE_vfont_free_data(struct VFont *vfont)
}
if (vfont->temp_pf) {
- freePackedFile(vfont->temp_pf); /* NULL when the font file can't be found on disk */
+ BKE_packedfile_free(vfont->temp_pf); /* NULL when the font file can't be found on disk */
vfont->temp_pf = NULL;
}
}
@@ -97,7 +97,7 @@ void BKE_vfont_free(struct VFont *vf)
BKE_vfont_free_data(vf);
if (vf->packedfile) {
- freePackedFile(vf->packedfile);
+ BKE_packedfile_free(vf->packedfile);
vf->packedfile = NULL;
}
}
@@ -114,7 +114,7 @@ void BKE_vfont_copy_data(Main *UNUSED(bmain),
vfont_dst->temp_pf = NULL;
if (vfont_dst->packedfile) {
- vfont_dst->packedfile = dupPackedFile(vfont_dst->packedfile);
+ vfont_dst->packedfile = BKE_packedfile_duplicate(vfont_dst->packedfile);
}
if (vfont_dst->data) {
@@ -148,7 +148,7 @@ static PackedFile *get_builtin_packedfile(void)
memcpy(mem, builtin_font_data, builtin_font_size);
- return newPackedFileMemory(mem, builtin_font_size);
+ return BKE_packedfile_new_from_memory(mem, builtin_font_size);
}
}
@@ -183,14 +183,15 @@ static VFontData *vfont_get_data(VFont *vfont)
/* We need to copy a tmp font to memory unless it is already there */
if (vfont->temp_pf == NULL) {
- vfont->temp_pf = dupPackedFile(pf);
+ vfont->temp_pf = BKE_packedfile_duplicate(pf);
}
}
else {
- pf = newPackedFile(NULL, vfont->name, ID_BLEND_PATH_FROM_GLOBAL(&vfont->id));
+ pf = BKE_packedfile_new(NULL, vfont->name, ID_BLEND_PATH_FROM_GLOBAL(&vfont->id));
if (vfont->temp_pf == NULL) {
- vfont->temp_pf = newPackedFile(NULL, vfont->name, ID_BLEND_PATH_FROM_GLOBAL(&vfont->id));
+ vfont->temp_pf = BKE_packedfile_new(
+ NULL, vfont->name, ID_BLEND_PATH_FROM_GLOBAL(&vfont->id));
}
}
if (!pf) {
@@ -208,7 +209,7 @@ static VFontData *vfont_get_data(VFont *vfont)
if (pf) {
vfont->data = BLI_vfontdata_from_freetypefont(pf);
if (pf != vfont->packedfile) {
- freePackedFile(pf);
+ BKE_packedfile_free(pf);
}
}
@@ -234,7 +235,7 @@ void BKE_vfont_init(VFont *vfont)
}
/* Free the packed file */
- freePackedFile(pf);
+ BKE_packedfile_free(pf);
}
}
@@ -253,7 +254,7 @@ VFont *BKE_vfont_load(Main *bmain, const char *filepath)
}
else {
BLI_split_file_part(filepath, filename, sizeof(filename));
- pf = newPackedFile(NULL, filepath, BKE_main_blendfile_path(bmain));
+ pf = BKE_packedfile_new(NULL, filepath, BKE_main_blendfile_path(bmain));
is_builtin = false;
}
@@ -279,13 +280,13 @@ VFont *BKE_vfont_load(Main *bmain, const char *filepath)
/* Do not add FO_BUILTIN_NAME to temporary listbase */
if (!STREQ(filename, FO_BUILTIN_NAME)) {
- vfont->temp_pf = newPackedFile(NULL, filepath, BKE_main_blendfile_path(bmain));
+ vfont->temp_pf = BKE_packedfile_new(NULL, filepath, BKE_main_blendfile_path(bmain));
}
}
/* Free the packed file */
if (!vfont || vfont->packedfile != pf) {
- freePackedFile(pf);
+ BKE_packedfile_free(pf);
}
}
diff --git a/source/blender/blenkernel/intern/gpencil.c b/source/blender/blenkernel/intern/gpencil.c
index 842fa85bf76..058c0d10b8e 100644
--- a/source/blender/blenkernel/intern/gpencil.c
+++ b/source/blender/blenkernel/intern/gpencil.c
@@ -1324,6 +1324,7 @@ void BKE_gpencil_transform(bGPdata *gpd, float mat[4][4])
return;
}
+ const float scalef = mat4_to_scale(mat);
for (bGPDlayer *gpl = gpd->layers.first; gpl; gpl = gpl->next) {
/* FIXME: For now, we just skip parented layers.
* Otherwise, we have to update each frame to find
@@ -1340,6 +1341,7 @@ void BKE_gpencil_transform(bGPdata *gpd, float mat[4][4])
for (pt = gps->points, i = 0; i < gps->totpoints; pt++, i++) {
mul_m4_v3(mat, &pt->x);
+ pt->pressure *= scalef;
}
/* TODO: Do we need to do this? distortion may mean we need to re-triangulate */
@@ -1958,3 +1960,83 @@ bool BKE_gpencil_trim_stroke(bGPDstroke *gps)
}
return intersect;
}
+
+/**
+ * Close stroke
+ * \param gps: Stroke to close
+ */
+bool BKE_gpencil_close_stroke(bGPDstroke *gps)
+{
+ bGPDspoint *pt1 = NULL;
+ bGPDspoint *pt2 = NULL;
+
+ /* Only can close a stroke with 3 points or more. */
+ if (gps->totpoints < 3) {
+ return false;
+ }
+
+ /* Calc average distance between points to get same level of sampling. */
+ float dist_tot = 0.0f;
+ for (int i = 0; i < gps->totpoints - 1; i++) {
+ pt1 = &gps->points[i];
+ pt2 = &gps->points[i + 1];
+ dist_tot += len_v3v3(&pt1->x, &pt2->x);
+ }
+ /* Calc the average distance. */
+ float dist_avg = dist_tot / (gps->totpoints - 1);
+
+ /* Calc distance between last and first point. */
+ pt1 = &gps->points[gps->totpoints - 1];
+ pt2 = &gps->points[0];
+ float dist_close = len_v3v3(&pt1->x, &pt2->x);
+
+ /* Calc number of points required using the average distance. */
+ int tot_newpoints = MAX2(dist_close / dist_avg, 1);
+
+ /* Resize stroke array. */
+ int old_tot = gps->totpoints;
+ gps->totpoints += tot_newpoints;
+ gps->points = MEM_recallocN(gps->points, sizeof(*gps->points) * gps->totpoints);
+ if (gps->dvert != NULL) {
+ gps->dvert = MEM_recallocN(gps->dvert, sizeof(*gps->dvert) * gps->totpoints);
+ }
+
+ /* Generate new points */
+ pt1 = &gps->points[old_tot - 1];
+ pt2 = &gps->points[0];
+ bGPDspoint *pt = &gps->points[old_tot];
+ for (int i = 1; i < tot_newpoints + 1; i++, pt++) {
+ float step = ((float)i / (float)tot_newpoints);
+ /* Clamp last point to be near, but not on top of first point. */
+ CLAMP(step, 0.0f, 0.99f);
+
+ /* Average point. */
+ interp_v3_v3v3(&pt->x, &pt1->x, &pt2->x, step);
+ pt->pressure = interpf(pt2->pressure, pt1->pressure, step);
+ pt->strength = interpf(pt2->strength, pt1->strength, step);
+ pt->flag = 0;
+
+ /* Set weights. */
+ if (gps->dvert != NULL) {
+ MDeformVert *dvert1 = &gps->dvert[old_tot - 1];
+ MDeformWeight *dw1 = defvert_verify_index(dvert1, 0);
+ float weight_1 = dw1 ? dw1->weight : 0.0f;
+
+ MDeformVert *dvert2 = &gps->dvert[0];
+ MDeformWeight *dw2 = defvert_verify_index(dvert2, 0);
+ float weight_2 = dw2 ? dw2->weight : 0.0f;
+
+ MDeformVert *dvert_final = &gps->dvert[old_tot + i - 1];
+ dvert_final->totweight = 0;
+ MDeformWeight *dw = defvert_verify_index(dvert_final, 0);
+ if (dvert_final->dw) {
+ dw->weight = interpf(weight_2, weight_1, step);
+ }
+ }
+ }
+
+ /* Enable cyclic flag. */
+ gps->flag |= GP_STROKE_CYCLIC;
+
+ return true;
+}
diff --git a/source/blender/blenkernel/intern/gpencil_modifier.c b/source/blender/blenkernel/intern/gpencil_modifier.c
index 2b27854ba82..7907be40984 100644
--- a/source/blender/blenkernel/intern/gpencil_modifier.c
+++ b/source/blender/blenkernel/intern/gpencil_modifier.c
@@ -28,6 +28,7 @@
#include "BLI_blenlib.h"
#include "BLI_utildefines.h"
#include "BLI_math_vector.h"
+#include "BLI_math_geom.h"
#include "BLI_string_utils.h"
#include "BLT_translation.h"
@@ -86,48 +87,6 @@ void BKE_gpencil_stroke_normal(const bGPDstroke *gps, float r_normal[3])
normalize_v3(r_normal);
}
-/* Get points of stroke always flat to view not affected by camera view or view position */
-static void gpencil_stroke_project_2d(const bGPDspoint *points, int totpoints, vec2f *points2d)
-{
- const bGPDspoint *pt0 = &points[0];
- const bGPDspoint *pt1 = &points[1];
- const bGPDspoint *pt3 = &points[(int)(totpoints * 0.75)];
-
- float locx[3];
- float locy[3];
- float loc3[3];
- float normal[3];
-
- /* local X axis (p0 -> p1) */
- sub_v3_v3v3(locx, &pt1->x, &pt0->x);
-
- /* point vector at 3/4 */
- sub_v3_v3v3(loc3, &pt3->x, &pt0->x);
-
- /* vector orthogonal to polygon plane */
- cross_v3_v3v3(normal, locx, loc3);
-
- /* local Y axis (cross to normal/x axis) */
- cross_v3_v3v3(locy, normal, locx);
-
- /* Normalize vectors */
- normalize_v3(locx);
- normalize_v3(locy);
-
- /* Get all points in local space */
- for (int i = 0; i < totpoints; i++) {
- const bGPDspoint *pt = &points[i];
- float loc[3];
-
- /* Get local space using first point as origin */
- sub_v3_v3v3(loc, &pt->x, &pt0->x);
-
- vec2f *point = &points2d[i];
- point->x = dot_v3v3(loc, locx);
- point->y = dot_v3v3(loc, locy);
- }
-}
-
/* Stroke Simplify ------------------------------------- */
/* Reduce a series of points to a simplified version, but
@@ -136,15 +95,15 @@ static void gpencil_stroke_project_2d(const bGPDspoint *points, int totpoints, v
* Ramer - Douglas - Peucker algorithm
* by http ://en.wikipedia.org/wiki/Ramer-Douglas-Peucker_algorithm
*/
-static void gpencil_rdp_stroke(bGPDstroke *gps, vec2f *points2d, float epsilon)
+void BKE_gpencil_simplify_stroke(bGPDstroke *gps, float epsilon)
{
- vec2f *old_points2d = points2d;
+ bGPDspoint *old_points = MEM_dupallocN(gps->points);
int totpoints = gps->totpoints;
char *marked = NULL;
char work;
- int start = 1;
- int end = gps->totpoints - 2;
+ int start = 0;
+ int end = gps->totpoints - 1;
marked = MEM_callocN(totpoints, "GP marked array");
marked[start] = 1;
@@ -163,7 +122,6 @@ static void gpencil_rdp_stroke(bGPDstroke *gps, vec2f *points2d, float epsilon)
/* while not over interval */
while (ls < end) {
int max_i = 0;
- float v1[2];
/* divided to get more control */
float max_dist = epsilon / 10.0f;
@@ -172,25 +130,14 @@ static void gpencil_rdp_stroke(bGPDstroke *gps, vec2f *points2d, float epsilon)
le++;
}
- /* perpendicular vector to ls-le */
- v1[1] = old_points2d[le].x - old_points2d[ls].x;
- v1[0] = old_points2d[ls].y - old_points2d[le].y;
-
for (int i = ls + 1; i < le; i++) {
- float mul;
+ float point_on_line[3];
float dist;
- float v2[2];
-
- v2[0] = old_points2d[i].x - old_points2d[ls].x;
- v2[1] = old_points2d[i].y - old_points2d[ls].y;
-
- if (v2[0] == 0 && v2[1] == 0) {
- continue;
- }
- mul = (float)(v1[0] * v2[0] + v1[1] * v2[1]) / (float)(v2[0] * v2[0] + v2[1] * v2[1]);
+ closest_to_line_segment_v3(
+ point_on_line, &old_points[i].x, &old_points[ls].x, &old_points[le].x);
- dist = mul * mul * (v2[0] * v2[0] + v2[1] * v2[1]);
+ dist = len_v3v3(point_on_line, &old_points[i].x);
if (dist > max_dist) {
max_dist = dist;
@@ -210,7 +157,6 @@ static void gpencil_rdp_stroke(bGPDstroke *gps, vec2f *points2d, float epsilon)
}
/* adding points marked */
- bGPDspoint *old_points = MEM_dupallocN(gps->points);
MDeformVert *old_dvert = NULL;
MDeformVert *dvert_src = NULL;
@@ -253,19 +199,6 @@ static void gpencil_rdp_stroke(bGPDstroke *gps, vec2f *points2d, float epsilon)
MEM_SAFE_FREE(marked);
}
-/* Simplify stroke using Ramer-Douglas-Peucker algorithm */
-void BKE_gpencil_simplify_stroke(bGPDstroke *gps, float factor)
-{
- /* first create temp data and convert points to 2D */
- vec2f *points2d = MEM_mallocN(sizeof(vec2f) * gps->totpoints, "GP Stroke temp 2d points");
-
- gpencil_stroke_project_2d(gps->points, gps->totpoints, points2d);
-
- gpencil_rdp_stroke(gps, points2d, factor);
-
- MEM_SAFE_FREE(points2d);
-}
-
/* Simplify alternate vertex of stroke except extremes */
void BKE_gpencil_simplify_fixed(bGPDstroke *gps)
{
diff --git a/source/blender/blenkernel/intern/image.c b/source/blender/blenkernel/intern/image.c
index 72bad56990f..8e04ef2d3ca 100644
--- a/source/blender/blenkernel/intern/image.c
+++ b/source/blender/blenkernel/intern/image.c
@@ -198,7 +198,7 @@ static void image_free_packedfiles(Image *ima)
while (ima->packedfiles.last) {
ImagePackedFile *imapf = ima->packedfiles.last;
if (imapf->packedfile) {
- freePackedFile(imapf->packedfile);
+ BKE_packedfile_free(imapf->packedfile);
}
BLI_remlink(&ima->packedfiles, imapf);
MEM_freeN(imapf);
@@ -377,7 +377,7 @@ static void copy_image_packedfiles(ListBase *lb_dst, const ListBase *lb_src)
STRNCPY(imapf_dst->filepath, imapf_src->filepath);
if (imapf_src->packedfile) {
- imapf_dst->packedfile = dupPackedFile(imapf_src->packedfile);
+ imapf_dst->packedfile = BKE_packedfile_duplicate(imapf_src->packedfile);
}
BLI_addtail(lb_dst, imapf_dst);
@@ -617,6 +617,7 @@ static ImBuf *add_ibuf_size(unsigned int width,
ImBuf *ibuf;
unsigned char *rect = NULL;
float *rect_float = NULL;
+ float fill_color[4];
if (floatbuf) {
ibuf = IMB_allocImBuf(width, height, depth, IB_rectfloat);
@@ -632,6 +633,15 @@ static ImBuf *add_ibuf_size(unsigned int width,
rect_float = ibuf->rect_float;
IMB_colormanagement_check_is_data(ibuf, colorspace_settings->name);
}
+
+ if (IMB_colormanagement_space_name_is_data(colorspace_settings->name)) {
+ copy_v4_v4(fill_color, color);
+ }
+ else {
+ /* The input color here should ideally be linear already, but for now
+ * we just convert and postpone breaking the API for later. */
+ srgb_to_linearrgb_v4(fill_color, color);
+ }
}
else {
ibuf = IMB_allocImBuf(width, height, depth, IB_rect);
@@ -647,6 +657,8 @@ static ImBuf *add_ibuf_size(unsigned int width,
rect = (unsigned char *)ibuf->rect;
IMB_colormanagement_assign_rect_colorspace(ibuf, colorspace_settings->name);
}
+
+ copy_v4_v4(fill_color, color);
}
if (!ibuf) {
@@ -663,7 +675,7 @@ static ImBuf *add_ibuf_size(unsigned int width,
BKE_image_buf_fill_checker_color(rect, rect_float, width, height);
break;
default:
- BKE_image_buf_fill_color(rect, rect_float, width, height, color);
+ BKE_image_buf_fill_color(rect, rect_float, width, height, fill_color);
break;
}
@@ -838,7 +850,7 @@ void BKE_image_packfiles(ReportList *reports, Image *ima, const char *basepath)
if (totfiles == 1) {
ImagePackedFile *imapf = MEM_mallocN(sizeof(ImagePackedFile), "Image packed file");
BLI_addtail(&ima->packedfiles, imapf);
- imapf->packedfile = newPackedFile(reports, ima->name, basepath);
+ imapf->packedfile = BKE_packedfile_new(reports, ima->name, basepath);
if (imapf->packedfile) {
STRNCPY(imapf->filepath, ima->name);
}
@@ -852,7 +864,7 @@ void BKE_image_packfiles(ReportList *reports, Image *ima, const char *basepath)
ImagePackedFile *imapf = MEM_mallocN(sizeof(ImagePackedFile), "Image packed file");
BLI_addtail(&ima->packedfiles, imapf);
- imapf->packedfile = newPackedFile(reports, iv->filepath, basepath);
+ imapf->packedfile = BKE_packedfile_new(reports, iv->filepath, basepath);
if (imapf->packedfile) {
STRNCPY(imapf->filepath, iv->filepath);
}
@@ -876,7 +888,7 @@ void BKE_image_packfiles_from_mem(ReportList *reports,
else {
ImagePackedFile *imapf = MEM_mallocN(sizeof(ImagePackedFile), __func__);
BLI_addtail(&ima->packedfiles, imapf);
- imapf->packedfile = newPackedFileMemory(data, data_len);
+ imapf->packedfile = BKE_packedfile_new_from_memory(data, data_len);
STRNCPY(imapf->filepath, ima->name);
}
}
@@ -3241,9 +3253,9 @@ void BKE_image_signal(Main *bmain, Image *ima, ImageUser *iuser, int signal)
ImagePackedFile *imapf;
for (imapf = ima->packedfiles.first; imapf; imapf = imapf->next) {
PackedFile *pf;
- pf = newPackedFile(NULL, imapf->filepath, ID_BLEND_PATH(bmain, &ima->id));
+ pf = BKE_packedfile_new(NULL, imapf->filepath, ID_BLEND_PATH(bmain, &ima->id));
if (pf) {
- freePackedFile(imapf->packedfile);
+ BKE_packedfile_free(imapf->packedfile);
imapf->packedfile = pf;
}
else {
@@ -4014,7 +4026,8 @@ static ImBuf *load_image_single(Image *ima,
BLI_addtail(&ima->packedfiles, imapf);
STRNCPY(imapf->filepath, filepath);
- imapf->packedfile = newPackedFile(NULL, filepath, ID_BLEND_PATH_FROM_GLOBAL(&ima->id));
+ imapf->packedfile = BKE_packedfile_new(
+ NULL, filepath, ID_BLEND_PATH_FROM_GLOBAL(&ima->id));
}
}
}
diff --git a/source/blender/blenkernel/intern/image_gen.c b/source/blender/blenkernel/intern/image_gen.c
index c7fdfb60a1c..bb2c086f02c 100644
--- a/source/blender/blenkernel/intern/image_gen.c
+++ b/source/blender/blenkernel/intern/image_gen.c
@@ -46,11 +46,9 @@ static void image_buf_fill_color_slice(
/* blank image */
if (rect_float) {
- float linear_color[4];
- srgb_to_linearrgb_v4(linear_color, color);
for (y = 0; y < height; y++) {
for (x = 0; x < width; x++) {
- copy_v4_v4(rect_float, linear_color);
+ copy_v4_v4(rect_float, color);
rect_float += 4;
}
}
@@ -242,9 +240,9 @@ static void checker_board_color_fill(
}
for (y = offset; y < height + offset; y++) {
+ /* Use a number lower then 1.0 else its too bright. */
+ hsv[2] = 0.1 + (y * (0.4 / total_height));
- hsv[2] = 0.1 +
- (y * (0.4 / total_height)); /* use a number lower then 1.0 else its too bright */
for (x = 0; x < width; x++) {
hsv[0] = (float)((double)(x / hue_step) * 1.0 / width * hue_step);
hsv_to_rgb_v(hsv, rgb);
diff --git a/source/blender/blenkernel/intern/layer.c b/source/blender/blenkernel/intern/layer.c
index 2b064c6b2a7..7dc04214ba5 100644
--- a/source/blender/blenkernel/intern/layer.c
+++ b/source/blender/blenkernel/intern/layer.c
@@ -745,9 +745,6 @@ static short layer_collection_sync(ViewLayer *view_layer,
}
lc->runtime_flag |= LAYER_COLLECTION_HAS_OBJECTS;
-
- /* Make sure flags on base are usable right away. */
- BKE_base_eval_flags(base);
}
runtime_flag |= lc->runtime_flag;
@@ -814,6 +811,10 @@ void BKE_layer_collection_sync(const Scene *scene, ViewLayer *view_layer)
BLI_freelistN(&view_layer->object_bases);
view_layer->object_bases = new_object_bases;
+ for (Base *base = view_layer->object_bases.first; base; base = base->next) {
+ BKE_base_eval_flags(base);
+ }
+
/* Always set a valid active collection. */
LayerCollection *active = view_layer->active_collection;
diff --git a/source/blender/blenkernel/intern/library.c b/source/blender/blenkernel/intern/library.c
index 974c6d6e0a6..b62ec88ed24 100644
--- a/source/blender/blenkernel/intern/library.c
+++ b/source/blender/blenkernel/intern/library.c
@@ -1502,7 +1502,7 @@ void *BKE_libblock_copy_for_localize(const ID *id)
void BKE_library_free(Library *lib)
{
if (lib->packedfile) {
- freePackedFile(lib->packedfile);
+ BKE_packedfile_free(lib->packedfile);
}
}
@@ -1855,8 +1855,9 @@ static void library_make_local_copying_check(ID *id,
MainIDRelationsEntry *entry = BLI_ghash_lookup(id_relations->id_used_to_user, id);
BLI_gset_insert(loop_tags, id);
for (; entry != NULL; entry = entry->next) {
- ID *par_id =
- (ID *)entry->id_pointer; /* used_to_user stores ID pointer, not pointer to ID pointer... */
+
+ /* Used_to_user stores ID pointer, not pointer to ID pointer. */
+ ID *par_id = (ID *)entry->id_pointer;
/* Our oh-so-beloved 'from' pointers... */
if (entry->usage_flag & IDWALK_CB_LOOPBACK) {
@@ -1912,7 +1913,8 @@ static void library_make_local_copying_check(ID *id,
* \param bmain: Almost certainly global main.
* \param lib: If not NULL, only make local data-blocks from this library.
* \param untagged_only: If true, only make local data-blocks not tagged with
- * LIB_TAG_PRE_EXISTING. \param set_fake: If true, set fake user on all localized data-blocks
+ * LIB_TAG_PRE_EXISTING.
+ * \param set_fake: If true, set fake user on all localized data-blocks
* (except group and objects ones).
*/
/* Note: Old (2.77) version was simply making (tagging) data-blocks as local,
diff --git a/source/blender/blenkernel/intern/mask_rasterize.c b/source/blender/blenkernel/intern/mask_rasterize.c
index f5f0dbc6610..2ab5b69a022 100644
--- a/source/blender/blenkernel/intern/mask_rasterize.c
+++ b/source/blender/blenkernel/intern/mask_rasterize.c
@@ -721,7 +721,7 @@ void BKE_maskrasterize_handle_init(MaskRasterHandle *mr_handle,
}
if (is_fill) {
- /* applt intersections depending on fill settings */
+ /* Apply intersections depending on fill settings. */
if (spline->flag & MASK_SPLINE_NOINTERSECT) {
BKE_mask_spline_feather_collapse_inner_loops(
spline, diff_feather_points, tot_diff_feather_points);
@@ -730,8 +730,10 @@ void BKE_maskrasterize_handle_init(MaskRasterHandle *mr_handle,
copy_v2_v2(co, diff_points[0]);
sf_vert_prev = BLI_scanfill_vert_add(&sf_ctx, co);
sf_vert_prev->tmp.u = sf_vert_tot;
- sf_vert_prev->keyindex = sf_vert_tot +
- tot_diff_point; /* absolute index of feather vert */
+
+ /* Absolute index of feather vert. */
+ sf_vert_prev->keyindex = sf_vert_tot + tot_diff_point;
+
sf_vert_tot++;
/* TODO, an alternate functions so we can avoid double vector copy! */
@@ -965,8 +967,8 @@ void BKE_maskrasterize_handle_init(MaskRasterHandle *mr_handle,
}
/* --- inefficient self-intersect case --- */
- /* if self intersections are found, its too trickty to attempt to map vertices
- * so just realloc and add entirely new vertices - the result of the self-intersect check
+ /* if self intersections are found, its too tricky to attempt to map vertices
+ * so just realloc and add entirely new vertices - the result of the self-intersect check.
*/
if ((masklay->flag & MASK_LAYERFLAG_FILL_OVERLAP) &&
(is_isect = BLI_scanfill_calc_self_isect(
diff --git a/source/blender/blenkernel/intern/mball_tessellate.c b/source/blender/blenkernel/intern/mball_tessellate.c
index 1218e78c6f0..687bd0a32c5 100644
--- a/source/blender/blenkernel/intern/mball_tessellate.c
+++ b/source/blender/blenkernel/intern/mball_tessellate.c
@@ -607,7 +607,7 @@ static void docube(PROCESS *process, CUBE *cube)
}
}
- /* Using faces[] table, adds neighbouring cube if surface intersects face in this direction. */
+ /* Using faces[] table, adds neighboring cube if surface intersects face in this direction. */
if (MB_BIT(faces[index], 0)) {
add_cube(process, cube->i - 1, cube->j, cube->k);
}
diff --git a/source/blender/blenkernel/intern/mesh.c b/source/blender/blenkernel/intern/mesh.c
index 755a8036e8e..f5e93dcf9b7 100644
--- a/source/blender/blenkernel/intern/mesh.c
+++ b/source/blender/blenkernel/intern/mesh.c
@@ -50,6 +50,7 @@
#include "BKE_editmesh.h"
#include "DEG_depsgraph.h"
+#include "DEG_depsgraph_query.h"
enum {
MESHCMP_DVERT_WEIGHTMISMATCH = 1,
@@ -557,8 +558,9 @@ void BKE_mesh_copy_data(Main *bmain, Mesh *me_dst, const Mesh *me_src, const int
/* XXX WHAT? Why? Comment, please! And pretty sure this is not valid for regular Mesh copying? */
me_dst->runtime.is_original = false;
- const bool do_tessface = ((me_src->totface != 0) &&
- (me_src->totpoly == 0)); /* only do tessface if we have no polys */
+ /* Only do tessface if we have no polys. */
+ const bool do_tessface = ((me_src->totface != 0) && (me_src->totpoly == 0));
+
CustomData_MeshMasks mask = CD_MASK_MESH;
if (me_src->id.tag & LIB_TAG_NO_MAIN) {
@@ -663,6 +665,7 @@ static Mesh *mesh_new_nomain_from_template_ex(const Mesh *me_src,
me_dst->cd_flag = me_src->cd_flag;
me_dst->editflag = me_src->editflag;
+ me_dst->texflag = me_src->texflag;
CustomData_copy(&me_src->vdata, &me_dst->vdata, mask.vmask, CD_CALLOC, verts_len);
CustomData_copy(&me_src->edata, &me_dst->edata, mask.emask, CD_CALLOC, edges_len);
@@ -1995,9 +1998,7 @@ void BKE_mesh_split_faces(Mesh *mesh, bool free_loop_normals)
void BKE_mesh_eval_geometry(Depsgraph *depsgraph, Mesh *mesh)
{
DEG_debug_print_eval(depsgraph, __func__, mesh->id.name, mesh);
- if (mesh->bb == NULL || (mesh->bb->flag & BOUNDBOX_DIRTY)) {
- BKE_mesh_texspace_calc(mesh);
- }
+ BKE_mesh_texspace_calc(mesh);
/* Clear autospace flag in evaluated mesh, so that texspace does not get recomputed when bbox is
* (e.g. after modifiers, etc.) */
mesh->texflag &= ~ME_AUTOSPACE;
@@ -2009,4 +2010,17 @@ void BKE_mesh_eval_geometry(Depsgraph *depsgraph, Mesh *mesh)
BKE_id_free(NULL, mesh->runtime.mesh_eval);
mesh->runtime.mesh_eval = NULL;
}
+ if (DEG_is_active(depsgraph)) {
+ Mesh *mesh_orig = (Mesh *)DEG_get_original_id(&mesh->id);
+ BoundBox *bb = mesh->bb;
+ if (bb != NULL) {
+ if (mesh_orig->bb == NULL) {
+ mesh_orig->bb = MEM_mallocN(sizeof(*mesh_orig->bb), __func__);
+ }
+ *mesh_orig->bb = *bb;
+ copy_v3_v3(mesh_orig->loc, mesh->loc);
+ copy_v3_v3(mesh_orig->size, mesh->size);
+ copy_v3_v3(mesh_orig->rot, mesh->rot);
+ }
+ }
}
diff --git a/source/blender/blenkernel/intern/mesh_convert.c b/source/blender/blenkernel/intern/mesh_convert.c
index dd36da44b92..fec83ebc899 100644
--- a/source/blender/blenkernel/intern/mesh_convert.c
+++ b/source/blender/blenkernel/intern/mesh_convert.c
@@ -1048,6 +1048,7 @@ static Mesh *mesh_new_from_curve_type_object(Object *object)
/* 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->data);
BKE_id_free(NULL, temp_object);
return NULL;
}
@@ -1216,6 +1217,10 @@ Mesh *BKE_mesh_new_from_object_to_bmain(Main *bmain,
bool preserve_all_data_layers)
{
Mesh *mesh = BKE_mesh_new_from_object(depsgraph, object, preserve_all_data_layers);
+ if (mesh == NULL) {
+ /* Unable to convert the object to a mesh. */
+ return NULL;
+ }
/* Make sure mesh only points original datablocks, also increase users of materials and other
* possibly referenced data-blocks.
diff --git a/source/blender/blenkernel/intern/mesh_evaluate.c b/source/blender/blenkernel/intern/mesh_evaluate.c
index f53700fbfb0..17b22a6d095 100644
--- a/source/blender/blenkernel/intern/mesh_evaluate.c
+++ b/source/blender/blenkernel/intern/mesh_evaluate.c
@@ -1164,8 +1164,10 @@ static void split_loop_nor_fan_do(LoopSplitTaskDataCommon *common_data, LoopSpli
*/
const unsigned int mv_pivot_index = ml_curr->v; /* The vertex we are "fanning" around! */
const MVert *mv_pivot = &mverts[mv_pivot_index];
- const MEdge *me_org =
- &medges[ml_curr->e]; /* ml_curr would be mlfan_prev if we needed that one */
+
+ /* ml_curr would be mlfan_prev if we needed that one. */
+ const MEdge *me_org = &medges[ml_curr->e];
+
const int *e2lfan_curr;
float vec_curr[3], vec_prev[3], vec_org[3];
const MLoop *mlfan_curr;
diff --git a/source/blender/blenkernel/intern/mesh_iterators.c b/source/blender/blenkernel/intern/mesh_iterators.c
index df6517066b8..f2ed9456b11 100644
--- a/source/blender/blenkernel/intern/mesh_iterators.c
+++ b/source/blender/blenkernel/intern/mesh_iterators.c
@@ -180,6 +180,54 @@ void BKE_mesh_foreach_mapped_face_center(
}
}
+/* Copied from cdDM_foreachMappedFaceCenter */
+void BKE_mesh_foreach_mapped_subdiv_face_center(
+ Mesh *mesh,
+ void (*func)(void *userData, int index, const float cent[3], const float no[3]),
+ void *userData,
+ MeshForeachFlag flag)
+{
+ const MPoly *mp = mesh->mpoly;
+ const MLoop *ml;
+ const MVert *mv;
+ float _no_buf[3];
+ float *no = (flag & MESH_FOREACH_USE_NORMAL) ? _no_buf : NULL;
+ const int *index = CustomData_get_layer(&mesh->pdata, CD_ORIGINDEX);
+
+ if (index) {
+ for (int i = 0; i < mesh->totpoly; i++, mp++) {
+ const int orig = *index++;
+ if (orig == ORIGINDEX_NONE) {
+ continue;
+ }
+ ml = &mesh->mloop[mp->loopstart];
+ for (int j = 0; j < mp->totloop; j++, ml++) {
+ mv = &mesh->mvert[ml->v];
+ if (mv->flag & ME_VERT_FACEDOT) {
+ if (flag & MESH_FOREACH_USE_NORMAL) {
+ normal_short_to_float_v3(no, mv->no);
+ }
+ func(userData, orig, mv->co, no);
+ }
+ }
+ }
+ }
+ else {
+ for (int i = 0; i < mesh->totpoly; i++, mp++) {
+ ml = &mesh->mloop[mp->loopstart];
+ for (int j = 0; j < mp->totloop; j++, ml++) {
+ mv = &mesh->mvert[ml->v];
+ if (mv->flag & ME_VERT_FACEDOT) {
+ if (flag & MESH_FOREACH_USE_NORMAL) {
+ normal_short_to_float_v3(no, mv->no);
+ }
+ func(userData, i, mv->co, no);
+ }
+ }
+ }
+ }
+}
+
/* Helpers based on above foreach loopers> */
typedef struct MappedVCosData {
diff --git a/source/blender/blenkernel/intern/mesh_mapping.c b/source/blender/blenkernel/intern/mesh_mapping.c
index 40e300e6e2d..78c0fa184f4 100644
--- a/source/blender/blenkernel/intern/mesh_mapping.c
+++ b/source/blender/blenkernel/intern/mesh_mapping.c
@@ -631,6 +631,8 @@ typedef bool (*MeshRemap_CheckIslandBoundary)(const struct MPoly *mpoly,
const struct MLoop *mloop,
const struct MEdge *medge,
const int nbr_egde_users,
+ const struct MPoly *mpoly_array,
+ const struct MeshElemMap *edge_poly_map,
void *user_data);
static void poly_edge_loop_islands_calc(const MEdge *medge,
@@ -656,8 +658,10 @@ static void poly_edge_loop_islands_calc(const MEdge *medge,
int poly_prev = 0;
const int temp_poly_group_id = 3; /* Placeholder value. */
- const int poly_group_id_overflowed =
- 5; /* Group we could not find any available bit, will be reset to 0 at end */
+
+ /* Group we could not find any available bit, will be reset to 0 at end. */
+ const int poly_group_id_overflowed = 5;
+
int tot_group = 0;
bool group_id_overflow = false;
@@ -728,7 +732,7 @@ static void poly_edge_loop_islands_calc(const MEdge *medge,
const MeshElemMap *map_ele = &edge_poly_map[me_idx];
const int *p = map_ele->indices;
int i = map_ele->count;
- if (!edge_boundary_check(mp, ml, me, i, edge_boundary_check_data)) {
+ if (!edge_boundary_check(mp, ml, me, i, mpoly, map_ele, edge_boundary_check_data)) {
for (; i--; p++) {
/* if we meet other non initialized its a bug */
BLI_assert(ELEM(poly_groups[*p], 0, poly_group_id));
@@ -780,8 +784,10 @@ static void poly_edge_loop_islands_calc(const MEdge *medge,
"Warning, could not find an available id for current smooth group, faces will me "
"marked "
"as out of any smooth group...\n");
- poly_group_id =
- poly_group_id_overflowed; /* Can't use 0, will have to set them to this value later. */
+
+ /* Can't use 0, will have to set them to this value later. */
+ poly_group_id = poly_group_id_overflowed;
+
group_id_overflow = true;
}
if (gid_bit > tot_group) {
@@ -828,11 +834,20 @@ static bool poly_is_island_boundary_smooth_cb(const MPoly *mp,
const MLoop *UNUSED(ml),
const MEdge *me,
const int nbr_egde_users,
+ const MPoly *mpoly_array,
+ const MeshElemMap *edge_poly_map,
void *UNUSED(user_data))
{
- /* Edge is sharp if its poly is sharp, or edge itself is sharp,
+ /* Edge is sharp if one of its polys is flat, or edge itself is sharp,
* or edge is not used by exactly two polygons. */
- return (!(mp->flag & ME_SMOOTH) || (me->flag & ME_SHARP) || (nbr_egde_users != 2));
+ if ((mp->flag & ME_SMOOTH) && !(me->flag & ME_SHARP) && (nbr_egde_users == 2)) {
+ /* In that case, edge appears to be smooth, but we need to check its other poly too. */
+ const MPoly *mp_other = (mp == &mpoly_array[edge_poly_map->indices[0]]) ?
+ &mpoly_array[edge_poly_map->indices[1]] :
+ &mpoly_array[edge_poly_map->indices[0]];
+ return (mp_other->flag & ME_SMOOTH) != 0;
+ }
+ return true;
}
/**
@@ -998,6 +1013,8 @@ static bool mesh_check_island_boundary_uv(const MPoly *UNUSED(mp),
const MLoop *ml,
const MEdge *me,
const int UNUSED(nbr_egde_users),
+ const MPoly *UNUSED(mpoly_array),
+ const MeshElemMap *UNUSED(edge_poly_map),
void *user_data)
{
if (user_data) {
diff --git a/source/blender/blenkernel/intern/modifier.c b/source/blender/blenkernel/intern/modifier.c
index 2254207e545..c23fe30d311 100644
--- a/source/blender/blenkernel/intern/modifier.c
+++ b/source/blender/blenkernel/intern/modifier.c
@@ -778,6 +778,41 @@ bool modifiers_usesArmature(Object *ob, bArmature *arm)
return false;
}
+bool modifiers_usesSubsurfFacedots(struct Scene *scene, Object *ob)
+{
+ /* Search (backward) in the modifier stack to find if we have a subsurf modifier (enabled) before
+ * the last modifier displayed on cage (or if the subsurf is the last). */
+ VirtualModifierData virtualModifierData;
+ ModifierData *md = modifiers_getVirtualModifierList(ob, &virtualModifierData);
+ int cage_index = modifiers_getCageIndex(scene, ob, NULL, 1);
+ if (cage_index == -1) {
+ return false;
+ }
+ /* Find first modifier enabled on cage. */
+ for (int i = 0; md && i < cage_index; i++) {
+ md = md->next;
+ }
+ /* Now from this point, search for subsurf modifier. */
+ for (; md; md = md->prev) {
+ const ModifierTypeInfo *mti = modifierType_getInfo(md->type);
+ if (md->type == eModifierType_Subsurf) {
+ ModifierMode mode = eModifierMode_Realtime | eModifierMode_Editmode;
+ if (modifier_isEnabled(scene, md, mode)) {
+ return true;
+ }
+ }
+ else if (mti->type == eModifierTypeType_OnlyDeform) {
+ /* Theses modifiers do not reset the subdiv flag nor change the topology.
+ * We can still search for a subsurf modifier. */
+ }
+ else {
+ /* Other modifiers may reset the subdiv facedot flag or create. */
+ return false;
+ }
+ }
+ return false;
+}
+
bool modifier_isCorrectableDeformed(ModifierData *md)
{
const ModifierTypeInfo *mti = modifierType_getInfo(md->type);
diff --git a/source/blender/blenkernel/intern/multires.c b/source/blender/blenkernel/intern/multires.c
index 17d6b623b33..29337ca9985 100644
--- a/source/blender/blenkernel/intern/multires.c
+++ b/source/blender/blenkernel/intern/multires.c
@@ -385,12 +385,20 @@ static void multires_ccg_mark_as_modified(SubdivCCG *subdiv_ccg, MultiresModifie
}
}
-void multires_mark_as_modified(Object *ob, MultiresModifiedFlags flags)
+void multires_mark_as_modified(Depsgraph *depsgraph, Object *object, MultiresModifiedFlags flags)
{
- if (ob == NULL) {
+ if (object == NULL) {
return;
}
- Mesh *mesh = ob->data;
+ /* NOTE: CCG live inside of evaluated object.
+ *
+ * While this is a bit weird to tag the only one, this is how other areas were built
+ * historically: they are tagging multires for update and then rely on object re-evaluation to
+ * do an actual update.
+ *
+ * In a longer term maybe special dependency graph tag can help sanitizing this a bit. */
+ Object *object_eval = DEG_get_evaluated_object(depsgraph, object);
+ Mesh *mesh = object_eval->data;
SubdivCCG *subdiv_ccg = mesh->runtime.subdiv_ccg;
if (subdiv_ccg == NULL) {
return;
diff --git a/source/blender/blenkernel/intern/node.c b/source/blender/blenkernel/intern/node.c
index 62357b7f878..775f6eb37a7 100644
--- a/source/blender/blenkernel/intern/node.c
+++ b/source/blender/blenkernel/intern/node.c
@@ -2455,7 +2455,7 @@ static void ntree_interface_identifier(bNodeTree *ntree,
char *description)
{
/* There is a possibility that different node tree names get mapped to the same identifier
- * after sanitization (e.g. "SomeGroup_A", "SomeGroup.A" both get sanitized to "SomeGroup_A").
+ * after sanitation (e.g. "SomeGroup_A", "SomeGroup.A" both get sanitized to "SomeGroup_A").
* On top of the sanitized id string add a number suffix if necessary to avoid duplicates.
*/
identifier[0] = '\0';
diff --git a/source/blender/blenkernel/intern/object.c b/source/blender/blenkernel/intern/object.c
index 2a66edc8d42..d7256cc9604 100644
--- a/source/blender/blenkernel/intern/object.c
+++ b/source/blender/blenkernel/intern/object.c
@@ -1417,8 +1417,7 @@ void BKE_object_copy_data(Main *bmain, Object *ob_dst, const Object *ob_src, con
}
}
BKE_object_copy_softbody(ob_dst, ob_src, flag_subdata);
- ob_dst->rigidbody_object = BKE_rigidbody_copy_object(ob_src, flag_subdata);
- ob_dst->rigidbody_constraint = BKE_rigidbody_copy_constraint(ob_src, flag_subdata);
+ BKE_rigidbody_object_copy(bmain, ob_dst, ob_src, flag_subdata);
BKE_object_copy_particlesystems(ob_dst, ob_src, flag_subdata);
diff --git a/source/blender/blenkernel/intern/object_update.c b/source/blender/blenkernel/intern/object_update.c
index 6a6adb82225..202eadaa35a 100644
--- a/source/blender/blenkernel/intern/object_update.c
+++ b/source/blender/blenkernel/intern/object_update.c
@@ -31,6 +31,7 @@
#include "BLI_blenlib.h"
#include "BLI_utildefines.h"
+#include "BLI_threads.h"
#include "BLI_math.h"
#include "BKE_animsys.h"
@@ -393,6 +394,21 @@ void BKE_object_data_select_update(Depsgraph *depsgraph, ID *object_data)
}
}
+void BKE_object_select_update(Depsgraph *depsgraph, Object *object)
+{
+ DEG_debug_print_eval(depsgraph, __func__, object->id.name, object);
+ if (object->type == OB_MESH && !object->runtime.is_mesh_eval_owned) {
+ Mesh *mesh_input = object->runtime.mesh_orig;
+ Mesh_Runtime *mesh_runtime = &mesh_input->runtime;
+ BLI_mutex_lock(mesh_runtime->eval_mutex);
+ BKE_object_data_select_update(depsgraph, object->data);
+ BLI_mutex_unlock(mesh_runtime->eval_mutex);
+ }
+ else {
+ BKE_object_data_select_update(depsgraph, object->data);
+ }
+}
+
void BKE_object_eval_eval_base_flags(Depsgraph *depsgraph,
Scene *scene,
const int view_layer_index,
diff --git a/source/blender/blenkernel/intern/packedFile.c b/source/blender/blenkernel/intern/packedFile.c
index dd91878a15b..8e647757b40 100644
--- a/source/blender/blenkernel/intern/packedFile.c
+++ b/source/blender/blenkernel/intern/packedFile.c
@@ -49,7 +49,7 @@
#include "BKE_report.h"
#include "BKE_sound.h"
-int seekPackedFile(PackedFile *pf, int offset, int whence)
+int BKE_packedfile_seek(PackedFile *pf, int offset, int whence)
{
int oldseek = -1, seek = 0;
@@ -81,12 +81,12 @@ int seekPackedFile(PackedFile *pf, int offset, int whence)
return (oldseek);
}
-void rewindPackedFile(PackedFile *pf)
+void BKE_packedfile_rewind(PackedFile *pf)
{
- seekPackedFile(pf, 0, SEEK_SET);
+ BKE_packedfile_seek(pf, 0, SEEK_SET);
}
-int readPackedFile(PackedFile *pf, void *data, int size)
+int BKE_packedfile_read(PackedFile *pf, void *data, int size)
{
if ((pf != NULL) && (size >= 0) && (data != NULL)) {
if (size + pf->seek > pf->size) {
@@ -109,7 +109,7 @@ int readPackedFile(PackedFile *pf, void *data, int size)
return (size);
}
-int countPackedFiles(Main *bmain)
+int BKE_packedfile_count_all(Main *bmain)
{
Image *ima;
VFont *vf;
@@ -138,18 +138,18 @@ int countPackedFiles(Main *bmain)
return count;
}
-void freePackedFile(PackedFile *pf)
+void BKE_packedfile_free(PackedFile *pf)
{
if (pf) {
MEM_freeN(pf->data);
MEM_freeN(pf);
}
else {
- printf("freePackedFile: Trying to free a NULL pointer\n");
+ printf("%s: Trying to free a NULL pointer\n", __func__);
}
}
-PackedFile *dupPackedFile(const PackedFile *pf_src)
+PackedFile *BKE_packedfile_duplicate(const PackedFile *pf_src)
{
PackedFile *pf_dst;
@@ -159,7 +159,7 @@ PackedFile *dupPackedFile(const PackedFile *pf_src)
return pf_dst;
}
-PackedFile *newPackedFileMemory(void *mem, int memlen)
+PackedFile *BKE_packedfile_new_from_memory(void *mem, int memlen)
{
PackedFile *pf = MEM_callocN(sizeof(*pf), "PackedFile");
pf->data = mem;
@@ -168,7 +168,7 @@ PackedFile *newPackedFileMemory(void *mem, int memlen)
return pf;
}
-PackedFile *newPackedFile(ReportList *reports, const char *filename, const char *basepath)
+PackedFile *BKE_packedfile_new(ReportList *reports, const char *filename, const char *basepath)
{
PackedFile *pf = NULL;
int file, filelen;
@@ -207,7 +207,7 @@ PackedFile *newPackedFile(ReportList *reports, const char *filename, const char
data = MEM_mallocN(filelen, "packFile");
}
if (read(file, data, filelen) == filelen) {
- pf = newPackedFileMemory(data, filelen);
+ pf = BKE_packedfile_new_from_memory(data, filelen);
}
else {
MEM_freeN(data);
@@ -222,7 +222,7 @@ PackedFile *newPackedFile(ReportList *reports, const char *filename, const char
}
/* no libraries for now */
-void packAll(Main *bmain, ReportList *reports, bool verbose)
+void BKE_packedfile_pack_all(Main *bmain, ReportList *reports, bool verbose)
{
Image *ima;
VFont *vfont;
@@ -247,14 +247,14 @@ void packAll(Main *bmain, ReportList *reports, bool verbose)
for (vfont = bmain->fonts.first; vfont; vfont = vfont->id.next) {
if (vfont->packedfile == NULL && !ID_IS_LINKED(vfont) &&
BKE_vfont_is_builtin(vfont) == false) {
- vfont->packedfile = newPackedFile(reports, vfont->name, BKE_main_blendfile_path(bmain));
+ vfont->packedfile = BKE_packedfile_new(reports, vfont->name, BKE_main_blendfile_path(bmain));
tot++;
}
}
for (sound = bmain->sounds.first; sound; sound = sound->id.next) {
if (sound->packedfile == NULL && !ID_IS_LINKED(sound)) {
- sound->packedfile = newPackedFile(reports, sound->name, BKE_main_blendfile_path(bmain));
+ sound->packedfile = BKE_packedfile_new(reports, sound->name, BKE_main_blendfile_path(bmain));
tot++;
}
}
@@ -267,11 +267,11 @@ void packAll(Main *bmain, ReportList *reports, bool verbose)
}
}
-int writePackedFile(ReportList *reports,
- const char *ref_file_name,
- const char *filename,
- PackedFile *pf,
- const bool guimode)
+int BKE_packedfile_write_to_file(ReportList *reports,
+ const char *ref_file_name,
+ const char *filename,
+ PackedFile *pf,
+ const bool guimode)
{
int file, number;
int ret_value = RET_OK;
@@ -349,10 +349,12 @@ int writePackedFile(ReportList *reports,
* - PF_DIFFERENT: the packed file and original file differ
* - PF_NOFILE: the original file doesn't exist
*/
-int checkPackedFile(const char *ref_file_name, const char *filename, PackedFile *pf)
+enum ePF_FileCompare BKE_packedfile_compare_to_file(const char *ref_file_name,
+ const char *filename,
+ PackedFile *pf)
{
BLI_stat_t st;
- int ret_val, i, len, file;
+ enum ePF_FileCompare ret_val;
char buf[4096];
char name[FILE_MAX];
@@ -360,35 +362,35 @@ int checkPackedFile(const char *ref_file_name, const char *filename, PackedFile
BLI_path_abs(name, ref_file_name);
if (BLI_stat(name, &st) == -1) {
- ret_val = PF_NOFILE;
+ ret_val = PF_CMP_NOFILE;
}
else if (st.st_size != pf->size) {
- ret_val = PF_DIFFERS;
+ ret_val = PF_CMP_DIFFERS;
}
else {
/* we'll have to compare the two... */
- file = BLI_open(name, O_BINARY | O_RDONLY, 0);
+ const int file = BLI_open(name, O_BINARY | O_RDONLY, 0);
if (file == -1) {
- ret_val = PF_NOFILE;
+ ret_val = PF_CMP_NOFILE;
}
else {
- ret_val = PF_EQUAL;
+ ret_val = PF_CMP_EQUAL;
- for (i = 0; i < pf->size; i += sizeof(buf)) {
- len = pf->size - i;
+ for (int i = 0; i < pf->size; i += sizeof(buf)) {
+ int len = pf->size - i;
if (len > sizeof(buf)) {
len = sizeof(buf);
}
if (read(file, buf, len) != len) {
/* read error ... */
- ret_val = PF_DIFFERS;
+ ret_val = PF_CMP_DIFFERS;
break;
}
else {
if (memcmp(buf, ((char *)pf->data) + i, len)) {
- ret_val = PF_DIFFERS;
+ ret_val = PF_CMP_DIFFERS;
break;
}
}
@@ -402,7 +404,8 @@ int checkPackedFile(const char *ref_file_name, const char *filename, PackedFile
}
/**
- * unpackFile() looks at the existing files (abs_name, local_name) and a packed file.
+ * #BKE_packedfile_unpack_to_file() looks at the existing files (abs_name, local_name)
+ * and a packed file.
*
* It returns a char *to the existing file name / new file name or NULL when
* there was an error or when the user decides to cancel the operation.
@@ -410,19 +413,18 @@ int checkPackedFile(const char *ref_file_name, const char *filename, PackedFile
* \warning 'abs_name' may be relative still! (use a "//" prefix)
* be sure to run #BLI_path_abs on it first.
*/
-char *unpackFile(ReportList *reports,
- const char *ref_file_name,
- const char *abs_name,
- const char *local_name,
- PackedFile *pf,
- int how)
+char *BKE_packedfile_unpack_to_file(ReportList *reports,
+ const char *ref_file_name,
+ const char *abs_name,
+ const char *local_name,
+ PackedFile *pf,
+ enum ePF_FileStatus how)
{
char *newname = NULL;
const char *temp = NULL;
if (pf != NULL) {
switch (how) {
- case -1:
case PF_KEEP:
break;
case PF_REMOVE:
@@ -443,7 +445,7 @@ char *unpackFile(ReportList *reports,
ATTR_FALLTHROUGH;
}
case PF_WRITE_LOCAL:
- if (writePackedFile(reports, ref_file_name, local_name, pf, 1) == RET_OK) {
+ if (BKE_packedfile_write_to_file(reports, ref_file_name, local_name, pf, 1) == RET_OK) {
temp = local_name;
}
break;
@@ -463,12 +465,12 @@ char *unpackFile(ReportList *reports,
ATTR_FALLTHROUGH;
}
case PF_WRITE_ORIGINAL:
- if (writePackedFile(reports, ref_file_name, abs_name, pf, 1) == RET_OK) {
+ if (BKE_packedfile_write_to_file(reports, ref_file_name, abs_name, pf, 1) == RET_OK) {
temp = abs_name;
}
break;
default:
- printf("unpackFile: unknown return_value %d\n", how);
+ printf("%s: unknown return_value %u\n", __func__, how);
break;
}
@@ -525,7 +527,10 @@ static void unpack_generate_paths(const char *name,
}
}
-int unpackVFont(Main *bmain, ReportList *reports, VFont *vfont, int how)
+int BKE_packedfile_unpack_vfont(Main *bmain,
+ ReportList *reports,
+ VFont *vfont,
+ enum ePF_FileStatus how)
{
char localname[FILE_MAX], absname[FILE_MAX];
char *newname;
@@ -534,11 +539,11 @@ int unpackVFont(Main *bmain, ReportList *reports, VFont *vfont, int how)
if (vfont != NULL) {
unpack_generate_paths(
vfont->name, (ID *)vfont, absname, localname, sizeof(absname), sizeof(localname));
- newname = unpackFile(
+ newname = BKE_packedfile_unpack_to_file(
reports, BKE_main_blendfile_path(bmain), absname, localname, vfont->packedfile, how);
if (newname != NULL) {
ret_value = RET_OK;
- freePackedFile(vfont->packedfile);
+ BKE_packedfile_free(vfont->packedfile);
vfont->packedfile = NULL;
BLI_strncpy(vfont->name, newname, sizeof(vfont->name));
MEM_freeN(newname);
@@ -548,7 +553,10 @@ int unpackVFont(Main *bmain, ReportList *reports, VFont *vfont, int how)
return (ret_value);
}
-int unpackSound(Main *bmain, ReportList *reports, bSound *sound, int how)
+int BKE_packedfile_unpack_sound(Main *bmain,
+ ReportList *reports,
+ bSound *sound,
+ enum ePF_FileStatus how)
{
char localname[FILE_MAX], absname[FILE_MAX];
char *newname;
@@ -557,13 +565,13 @@ int unpackSound(Main *bmain, ReportList *reports, bSound *sound, int how)
if (sound != NULL) {
unpack_generate_paths(
sound->name, (ID *)sound, absname, localname, sizeof(absname), sizeof(localname));
- newname = unpackFile(
+ newname = BKE_packedfile_unpack_to_file(
reports, BKE_main_blendfile_path(bmain), absname, localname, sound->packedfile, how);
if (newname != NULL) {
BLI_strncpy(sound->name, newname, sizeof(sound->name));
MEM_freeN(newname);
- freePackedFile(sound->packedfile);
+ BKE_packedfile_free(sound->packedfile);
sound->packedfile = NULL;
BKE_sound_load(bmain, sound);
@@ -575,7 +583,10 @@ int unpackSound(Main *bmain, ReportList *reports, bSound *sound, int how)
return (ret_value);
}
-int unpackImage(Main *bmain, ReportList *reports, Image *ima, int how)
+int BKE_packedfile_unpack_image(Main *bmain,
+ ReportList *reports,
+ Image *ima,
+ enum ePF_FileStatus how)
{
int ret_value = RET_ERROR;
@@ -587,14 +598,14 @@ int unpackImage(Main *bmain, ReportList *reports, Image *ima, int how)
unpack_generate_paths(
imapf->filepath, (ID *)ima, absname, localname, sizeof(absname), sizeof(localname));
- newname = unpackFile(
+ newname = BKE_packedfile_unpack_to_file(
reports, BKE_main_blendfile_path(bmain), absname, localname, imapf->packedfile, how);
if (newname != NULL) {
ImageView *iv;
ret_value = ret_value == RET_ERROR ? RET_ERROR : RET_OK;
- freePackedFile(imapf->packedfile);
+ BKE_packedfile_free(imapf->packedfile);
imapf->packedfile = NULL;
/* update the new corresponding view filepath */
@@ -625,7 +636,7 @@ int unpackImage(Main *bmain, ReportList *reports, Image *ima, int how)
return (ret_value);
}
-int unpackLibraries(Main *bmain, ReportList *reports)
+int BKE_packedfile_unpack_all_libraries(Main *bmain, ReportList *reports)
{
Library *lib;
char *newname;
@@ -634,18 +645,18 @@ int unpackLibraries(Main *bmain, ReportList *reports)
for (lib = bmain->libraries.first; lib; lib = lib->id.next) {
if (lib->packedfile && lib->name[0]) {
- newname = unpackFile(reports,
- BKE_main_blendfile_path(bmain),
- lib->filepath,
- lib->filepath,
- lib->packedfile,
- PF_WRITE_ORIGINAL);
+ newname = BKE_packedfile_unpack_to_file(reports,
+ BKE_main_blendfile_path(bmain),
+ lib->filepath,
+ lib->filepath,
+ lib->packedfile,
+ PF_WRITE_ORIGINAL);
if (newname != NULL) {
ret_value = RET_OK;
printf("Unpacked .blend library: %s\n", newname);
- freePackedFile(lib->packedfile);
+ BKE_packedfile_free(lib->packedfile);
lib->packedfile = NULL;
MEM_freeN(newname);
@@ -656,7 +667,7 @@ int unpackLibraries(Main *bmain, ReportList *reports)
return (ret_value);
}
-void packLibraries(Main *bmain, ReportList *reports)
+void BKE_packedfile_pack_all_libraries(Main *bmain, ReportList *reports)
{
Library *lib;
@@ -674,12 +685,12 @@ void packLibraries(Main *bmain, ReportList *reports)
for (lib = bmain->libraries.first; lib; lib = lib->id.next) {
if (lib->packedfile == NULL) {
- lib->packedfile = newPackedFile(reports, lib->name, BKE_main_blendfile_path(bmain));
+ lib->packedfile = BKE_packedfile_new(reports, lib->name, BKE_main_blendfile_path(bmain));
}
}
}
-void unpackAll(Main *bmain, ReportList *reports, int how)
+void BKE_packedfile_unpack_all(Main *bmain, ReportList *reports, enum ePF_FileStatus how)
{
Image *ima;
VFont *vf;
@@ -687,25 +698,25 @@ void unpackAll(Main *bmain, ReportList *reports, int how)
for (ima = bmain->images.first; ima; ima = ima->id.next) {
if (BKE_image_has_packedfile(ima)) {
- unpackImage(bmain, reports, ima, how);
+ BKE_packedfile_unpack_image(bmain, reports, ima, how);
}
}
for (vf = bmain->fonts.first; vf; vf = vf->id.next) {
if (vf->packedfile) {
- unpackVFont(bmain, reports, vf, how);
+ BKE_packedfile_unpack_vfont(bmain, reports, vf, how);
}
}
for (sound = bmain->sounds.first; sound; sound = sound->id.next) {
if (sound->packedfile) {
- unpackSound(bmain, reports, sound, how);
+ BKE_packedfile_unpack_sound(bmain, reports, sound, how);
}
}
}
/* ID should be not NULL, return 1 if there's a packed file */
-bool BKE_pack_check(ID *id)
+bool BKE_packedfile_id_check(ID *id)
{
switch (GS(id->name)) {
case ID_IM: {
@@ -731,27 +742,27 @@ bool BKE_pack_check(ID *id)
}
/* ID should be not NULL */
-void BKE_unpack_id(Main *bmain, ID *id, ReportList *reports, int how)
+void BKE_packedfile_id_unpack(Main *bmain, ID *id, ReportList *reports, enum ePF_FileStatus how)
{
switch (GS(id->name)) {
case ID_IM: {
Image *ima = (Image *)id;
if (BKE_image_has_packedfile(ima)) {
- unpackImage(bmain, reports, ima, how);
+ BKE_packedfile_unpack_image(bmain, reports, ima, how);
}
break;
}
case ID_VF: {
VFont *vf = (VFont *)id;
if (vf->packedfile) {
- unpackVFont(bmain, reports, vf, how);
+ BKE_packedfile_unpack_vfont(bmain, reports, vf, how);
}
break;
}
case ID_SO: {
bSound *snd = (bSound *)id;
if (snd->packedfile) {
- unpackSound(bmain, reports, snd, how);
+ BKE_packedfile_unpack_sound(bmain, reports, snd, how);
}
break;
}
diff --git a/source/blender/blenkernel/intern/particle.c b/source/blender/blenkernel/intern/particle.c
index 13649eaf096..079a348745c 100644
--- a/source/blender/blenkernel/intern/particle.c
+++ b/source/blender/blenkernel/intern/particle.c
@@ -1645,7 +1645,7 @@ static int psys_map_index_on_dm(Mesh *mesh,
* to their new location, which means a different index, and for faces
* also a new face interpolation weights */
if (from == PART_FROM_VERT) {
- if (index_dmcache == DMCACHE_NOTFOUND || index_dmcache > mesh->totvert) {
+ if (index_dmcache == DMCACHE_NOTFOUND || index_dmcache >= mesh->totvert) {
return 0;
}
@@ -3291,6 +3291,10 @@ void psys_cache_edit_paths(Depsgraph *depsgraph,
int segments = 1 << pset->draw_step;
int totpart = edit->totpoint, recalc_set = 0;
+ if (edit->psmd_eval == NULL) {
+ return;
+ }
+
segments = MAX2(segments, 4);
if (!cache || edit->totpoint != edit->totcached) {
diff --git a/source/blender/blenkernel/intern/particle_distribute.c b/source/blender/blenkernel/intern/particle_distribute.c
index 070c3c7a566..27d85b91ba4 100644
--- a/source/blender/blenkernel/intern/particle_distribute.c
+++ b/source/blender/blenkernel/intern/particle_distribute.c
@@ -232,6 +232,8 @@ static void distribute_grid(Mesh *mesh, ParticleSystem *psys)
/* lets intersect the faces */
for (i = 0; i < totface; i++, mface++) {
+ ParticleData *pa1 = NULL, *pa2 = NULL;
+
copy_v3_v3(v1, mvert[mface->v1].co);
copy_v3_v3(v2, mvert[mface->v2].co);
copy_v3_v3(v3, mvert[mface->v3].co);
@@ -239,24 +241,32 @@ static void distribute_grid(Mesh *mesh, ParticleSystem *psys)
bool intersects_tri = isect_ray_tri_watertight_v3(
co1, &isect_precalc, v1, v2, v3, &lambda, NULL);
if (intersects_tri) {
- if (from == PART_FROM_FACE) {
- (pa + (int)(lambda * size[a]) * a0mul)->flag &= ~PARS_UNEXIST;
- }
- else { /* store number of intersections */
- (pa + (int)(lambda * size[a]) * a0mul)->hair_index++;
- }
+ pa1 = (pa + (int)(lambda * size[a]) * a0mul);
}
if (mface->v4 && (!intersects_tri || from == PART_FROM_VOLUME)) {
copy_v3_v3(v4, mvert[mface->v4].co);
if (isect_ray_tri_watertight_v3(co1, &isect_precalc, v1, v3, v4, &lambda, NULL)) {
- if (from == PART_FROM_FACE) {
- (pa + (int)(lambda * size[a]) * a0mul)->flag &= ~PARS_UNEXIST;
- }
- else {
- (pa + (int)(lambda * size[a]) * a0mul)->hair_index++;
- }
+ pa2 = (pa + (int)(lambda * size[a]) * a0mul);
+ }
+ }
+
+ if (pa1) {
+ if (from == PART_FROM_FACE) {
+ pa1->flag &= ~PARS_UNEXIST;
+ }
+ else { /* store number of intersections */
+ pa1->hair_index++;
+ }
+ }
+
+ if (pa2 && pa2 != pa1) {
+ if (from == PART_FROM_FACE) {
+ pa2->flag &= ~PARS_UNEXIST;
+ }
+ else { /* store number of intersections */
+ pa2->hair_index++;
}
}
}
diff --git a/source/blender/blenkernel/intern/pointcache.c b/source/blender/blenkernel/intern/pointcache.c
index d441ffdc8ff..b577efd2a22 100644
--- a/source/blender/blenkernel/intern/pointcache.c
+++ b/source/blender/blenkernel/intern/pointcache.c
@@ -1590,7 +1590,7 @@ void BKE_ptcache_id_from_softbody(PTCacheID *pid, Object *ob, SoftBody *sb)
pid->stack_index = pid->cache->index;
- pid->default_step = 10;
+ pid->default_step = 1;
pid->max_step = 20;
pid->file_type = PTCACHE_FILE_PTCACHE;
}
@@ -1655,7 +1655,7 @@ void BKE_ptcache_id_from_particles(PTCacheID *pid, Object *ob, ParticleSystem *p
pid->info_types = (1 << BPHYS_DATA_TIMES);
- pid->default_step = 10;
+ pid->default_step = 1;
pid->max_step = 20;
pid->file_type = PTCACHE_FILE_PTCACHE;
}
diff --git a/source/blender/blenkernel/intern/rigidbody.c b/source/blender/blenkernel/intern/rigidbody.c
index a3a0ebd6cb3..c9b18dfc7e6 100644
--- a/source/blender/blenkernel/intern/rigidbody.c
+++ b/source/blender/blenkernel/intern/rigidbody.c
@@ -34,6 +34,7 @@
#include "MEM_guardedalloc.h"
#include "BLI_math.h"
+#include "BLI_listbase.h"
#ifdef WITH_BULLET
# include "RBI_api.h"
@@ -228,7 +229,7 @@ void BKE_rigidbody_free_constraint(Object *ob)
* be added to relevant groups later...
*/
-RigidBodyOb *BKE_rigidbody_copy_object(const Object *ob, const int flag)
+static RigidBodyOb *rigidbody_copy_object(const Object *ob, const int flag)
{
RigidBodyOb *rboN = NULL;
@@ -249,7 +250,7 @@ RigidBodyOb *BKE_rigidbody_copy_object(const Object *ob, const int flag)
return rboN;
}
-RigidBodyCon *BKE_rigidbody_copy_constraint(const Object *ob, const int UNUSED(flag))
+static RigidBodyCon *rigidbody_copy_constraint(const Object *ob, const int UNUSED(flag))
{
RigidBodyCon *rbcN = NULL;
@@ -268,6 +269,54 @@ RigidBodyCon *BKE_rigidbody_copy_constraint(const Object *ob, const int UNUSED(f
return rbcN;
}
+void BKE_rigidbody_object_copy(Main *bmain, Object *ob_dst, const Object *ob_src, const int flag)
+{
+ ob_dst->rigidbody_object = rigidbody_copy_object(ob_src, flag);
+ ob_dst->rigidbody_constraint = rigidbody_copy_constraint(ob_src, flag);
+
+ if (flag & LIB_ID_CREATE_NO_MAIN) {
+ return;
+ }
+
+ /* We have to ensure that duplicated object ends up in relevant rigidbody collections...
+ * Otherwise duplicating the RB data itself is meaningless. */
+ LISTBASE_FOREACH (Scene *, scene, &bmain->scenes) {
+ RigidBodyWorld *rigidbody_world = scene->rigidbody_world;
+
+ if (rigidbody_world != NULL) {
+ bool need_objects_update = false;
+ bool need_constraints_update = false;
+
+ if (ob_dst->rigidbody_object) {
+ if (BKE_collection_has_object(rigidbody_world->group, ob_src)) {
+ BKE_collection_object_add(bmain, rigidbody_world->group, ob_dst);
+ need_objects_update = true;
+ }
+ }
+ if (ob_dst->rigidbody_constraint) {
+ if (BKE_collection_has_object(rigidbody_world->constraints, ob_src)) {
+ BKE_collection_object_add(bmain, rigidbody_world->constraints, ob_dst);
+ need_constraints_update = true;
+ }
+ }
+
+ if ((flag & LIB_ID_CREATE_NO_DEG_TAG) == 0 &&
+ (need_objects_update || need_constraints_update)) {
+ BKE_rigidbody_cache_reset(rigidbody_world);
+
+ DEG_relations_tag_update(bmain);
+ if (need_objects_update) {
+ DEG_id_tag_update(&rigidbody_world->group->id, ID_RECALC_COPY_ON_WRITE);
+ }
+ if (need_constraints_update) {
+ DEG_id_tag_update(&rigidbody_world->constraints->id, ID_RECALC_COPY_ON_WRITE);
+ }
+ DEG_id_tag_update(&ob_dst->id, ID_RECALC_TRANSFORM);
+ }
+ }
+ }
+}
+
/* ************************************** */
/* Setup Utilities - Validate Sim Instances */
@@ -1983,13 +2032,8 @@ void BKE_rigidbody_do_simulation(Depsgraph *depsgraph, Scene *scene, float ctime
# pragma GCC diagnostic ignored "-Wunused-parameter"
# endif
-struct RigidBodyOb *BKE_rigidbody_copy_object(const Object *ob, const int flag)
-{
- return NULL;
-}
-struct RigidBodyCon *BKE_rigidbody_copy_constraint(const Object *ob, const int flag)
+void BKE_rigidbody_object_copy(Main *bmain, Object *ob_dst, const Object *ob_src, const int flag)
{
- return NULL;
}
void BKE_rigidbody_validate_sim_world(Scene *scene, RigidBodyWorld *rbw, bool rebuild)
{
diff --git a/source/blender/blenkernel/intern/scene.c b/source/blender/blenkernel/intern/scene.c
index d2d56569bff..a447b828bb1 100644
--- a/source/blender/blenkernel/intern/scene.c
+++ b/source/blender/blenkernel/intern/scene.c
@@ -2445,6 +2445,21 @@ void BKE_scene_cursor_from_mat4(View3DCursor *cursor, const float mat[4][4], boo
/* Dependency graph evaluation. */
+static void scene_sequencer_disable_sound_strips(Scene *scene)
+{
+ if (scene->sound_scene == NULL) {
+ return;
+ }
+ Sequence *seq;
+ SEQ_BEGIN (scene->ed, seq) {
+ if (seq->scene_sound != NULL) {
+ BKE_sound_remove_scene_sound(scene, seq->scene_sound);
+ seq->scene_sound = NULL;
+ }
+ }
+ SEQ_END;
+}
+
void BKE_scene_eval_sequencer_sequences(Depsgraph *depsgraph, Scene *scene)
{
DEG_debug_print_eval(depsgraph, __func__, scene->id.name, scene);
@@ -2474,6 +2489,9 @@ void BKE_scene_eval_sequencer_sequences(Depsgraph *depsgraph, Scene *scene)
* then it is no longer needed to do such manual forced updates. */
if (seq->type == SEQ_TYPE_SCENE && seq->scene != NULL) {
BKE_sound_set_scene_volume(seq->scene, seq->scene->audio.volume);
+ if ((seq->flag & SEQ_SCENE_STRIPS) == 0) {
+ scene_sequencer_disable_sound_strips(seq->scene);
+ }
}
if (seq->sound != NULL) {
if (scene->id.recalc & ID_RECALC_AUDIO || seq->sound->id.recalc & ID_RECALC_AUDIO) {
diff --git a/source/blender/blenkernel/intern/screen.c b/source/blender/blenkernel/intern/screen.c
index 86fec1ee754..619845c9ecb 100644
--- a/source/blender/blenkernel/intern/screen.c
+++ b/source/blender/blenkernel/intern/screen.c
@@ -738,6 +738,23 @@ ARegion *BKE_area_find_region_xy(ScrArea *sa, const int regiontype, int x, int y
}
/**
+ * \note This is only for screen level regions (typically menus/popups).
+ */
+ARegion *BKE_screen_find_region_xy(bScreen *sc, const int regiontype, int x, int y)
+{
+ ARegion *ar_found = NULL;
+ for (ARegion *ar = sc->regionbase.first; ar; ar = ar->next) {
+ if ((regiontype == RGN_TYPE_ANY) || (ar->regiontype == regiontype)) {
+ if (BLI_rcti_isect_pt(&ar->winrct, x, y)) {
+ ar_found = ar;
+ break;
+ }
+ }
+ }
+ return ar_found;
+}
+
+/**
* \note, ideally we can get the area from the context,
* there are a few places however where this isn't practical.
*/
diff --git a/source/blender/blenkernel/intern/sequencer.c b/source/blender/blenkernel/intern/sequencer.c
index 971ca77ff3d..c2d51b72b29 100644
--- a/source/blender/blenkernel/intern/sequencer.c
+++ b/source/blender/blenkernel/intern/sequencer.c
@@ -3740,9 +3740,6 @@ static ImBuf *do_render_strip_uncached(const SeqRenderData *context,
ibuf = seq_render_scene_strip(context, seq, nr, cfra);
}
- /* Scene strips update all animation, so we need to restore original state.*/
- BKE_animsys_evaluate_all_animation(context->bmain, context->depsgraph, context->scene, cfra);
-
break;
}
@@ -5203,6 +5200,8 @@ void BKE_sequencer_offset_animdata(Scene *scene, Sequence *seq, int ofs)
}
}
}
+
+ DEG_id_tag_update(&scene->adt->action->id, ID_RECALC_ANIMATION);
}
void BKE_sequencer_dupe_animdata(Scene *scene, const char *name_src, const char *name_dst)
@@ -5398,7 +5397,7 @@ static void seq_load_apply(Main *bmain, Scene *scene, Sequence *seq, SeqLoadInfo
if (seq_load->flag & SEQ_LOAD_SOUND_CACHE) {
if (seq->sound) {
- BKE_sound_cache(seq->sound);
+ seq->sound->flags |= SOUND_FLAGS_CACHING;
}
}
diff --git a/source/blender/blenkernel/intern/smoke.c b/source/blender/blenkernel/intern/smoke.c
index d6858e2d4d2..bb8fd18ea58 100644
--- a/source/blender/blenkernel/intern/smoke.c
+++ b/source/blender/blenkernel/intern/smoke.c
@@ -1402,9 +1402,9 @@ static void emit_from_particles(Object *flow_ob,
Scene *scene,
float dt)
{
+ /* Is particle system selected. */
if (sfs && sfs->psys && sfs->psys->part &&
- ELEM(sfs->psys->part->type, PART_EMITTER, PART_FLUID)) // is particle system selected
- {
+ ELEM(sfs->psys->part->type, PART_EMITTER, PART_FLUID)) {
ParticleSimulationData sim;
ParticleSystem *psys = sfs->psys;
float *particle_pos;
diff --git a/source/blender/blenkernel/intern/softbody.c b/source/blender/blenkernel/intern/softbody.c
index 5af3f22cad2..03fbdc24ce4 100644
--- a/source/blender/blenkernel/intern/softbody.c
+++ b/source/blender/blenkernel/intern/softbody.c
@@ -155,8 +155,8 @@ typedef struct SB_thread_context {
#define BFF_INTERSECT 1 /* collider edge intrudes face */
#define BFF_CLOSEVERT 2 /* collider vertex repulses face */
-static float SoftHeunTol =
- 1.0f; /* humm .. this should be calculated from sb parameters and sizes */
+/* humm .. this should be calculated from sb parameters and sizes. */
+static float SoftHeunTol = 1.0f;
/* local prototypes */
static void free_softbody_intern(SoftBody *sb);
@@ -251,7 +251,7 @@ static float _final_mass(Object *ob, BodyPoint *bp)
/*
* for each target object/face the axis aligned bounding box (AABB) is stored
* faces parallel to global axes
- * so only simple "value" in [min, max] ckecks are used
+ * so only simple "value" in [min, max] checks are used
* float operations still
*/
diff --git a/source/blender/blenkernel/intern/sound.c b/source/blender/blenkernel/intern/sound.c
index ad26314e877..6d782726e07 100644
--- a/source/blender/blenkernel/intern/sound.c
+++ b/source/blender/blenkernel/intern/sound.c
@@ -170,7 +170,7 @@ void BKE_sound_free(bSound *sound)
/* No animdata here. */
if (sound->packedfile) {
- freePackedFile(sound->packedfile);
+ BKE_packedfile_free(sound->packedfile);
sound->packedfile = NULL;
}
@@ -211,7 +211,7 @@ void BKE_sound_copy_data(Main *UNUSED(bmain),
sound_dst->newpackedfile = NULL;
if (sound_dst->packedfile) {
- sound_dst->packedfile = dupPackedFile(sound_dst->packedfile);
+ sound_dst->packedfile = BKE_packedfile_duplicate(sound_dst->packedfile);
}
BKE_sound_reset_runtime(sound_dst);
@@ -389,7 +389,6 @@ void BKE_sound_cache(bSound *sound)
{
sound_verify_evaluated_id(&sound->id);
- sound->flags |= SOUND_FLAGS_CACHING;
if (sound->cache) {
AUD_Sound_free(sound->cache);
}
@@ -405,7 +404,6 @@ void BKE_sound_cache(bSound *sound)
void BKE_sound_delete_cache(bSound *sound)
{
- sound->flags &= ~SOUND_FLAGS_CACHING;
if (sound->cache) {
AUD_Sound_free(sound->cache);
sound->cache = NULL;
diff --git a/source/blender/blenkernel/intern/subdiv_ccg.c b/source/blender/blenkernel/intern/subdiv_ccg.c
index 41ef2bd4b04..fac1e1dbe75 100644
--- a/source/blender/blenkernel/intern/subdiv_ccg.c
+++ b/source/blender/blenkernel/intern/subdiv_ccg.c
@@ -962,15 +962,31 @@ static void subdiv_ccg_average_inner_face_grids(SubdivCCG *subdiv_ccg,
const int num_face_grids = face->num_grids;
const int grid_size = subdiv_ccg->grid_size;
CCGElem *prev_grid = grids[face->start_grid_index + num_face_grids - 1];
+ /* Average boundary between neighbor grid. */
for (int corner = 0; corner < num_face_grids; corner++) {
CCGElem *grid = grids[face->start_grid_index + corner];
- for (int i = 0; i < grid_size; i++) {
+ for (int i = 1; i < grid_size; i++) {
CCGElem *prev_grid_element = CCG_grid_elem(key, prev_grid, i, 0);
CCGElem *grid_element = CCG_grid_elem(key, grid, 0, i);
average_grid_element(subdiv_ccg, key, prev_grid_element, grid_element);
}
prev_grid = grid;
}
+ /* Average all grids centers into a single accumulator, and share it.
+ * Guarantees corrent and smooth averaging in the center. */
+ GridElementAccumulator center_accumulator;
+ element_accumulator_init(&center_accumulator);
+ for (int corner = 0; corner < num_face_grids; corner++) {
+ CCGElem *grid = grids[face->start_grid_index + corner];
+ CCGElem *grid_center_element = CCG_grid_elem(key, grid, 0, 0);
+ element_accumulator_add(&center_accumulator, subdiv_ccg, key, grid_center_element);
+ }
+ element_accumulator_mul_fl(&center_accumulator, 1.0f / (float)num_face_grids);
+ for (int corner = 0; corner < num_face_grids; corner++) {
+ CCGElem *grid = grids[face->start_grid_index + corner];
+ CCGElem *grid_center_element = CCG_grid_elem(key, grid, 0, 0);
+ element_accumulator_copy(subdiv_ccg, key, grid_center_element, &center_accumulator);
+ }
}
static void subdiv_ccg_average_inner_grids_task(void *__restrict userdata_v,
diff --git a/source/blender/blenkernel/intern/subdiv_mesh.c b/source/blender/blenkernel/intern/subdiv_mesh.c
index 947f51b4ff9..75e05f8ffab 100644
--- a/source/blender/blenkernel/intern/subdiv_mesh.c
+++ b/source/blender/blenkernel/intern/subdiv_mesh.c
@@ -570,6 +570,8 @@ static void evaluate_vertex_and_apply_displacement_copy(const SubdivMeshContext
normalize_v3(N);
normal_float_to_short_v3(subdiv_vert->no, N);
}
+ /* Remove facedot flag. This can happen if there is more than one subsurf modifier. */
+ subdiv_vert->flag &= ~ME_VERT_FACEDOT;
}
static void evaluate_vertex_and_apply_displacement_interpolate(
@@ -719,6 +721,31 @@ static void subdiv_mesh_vertex_edge(const SubdivForeachContext *foreach_context,
ctx, ptex_face_index, u, v, &tls->vertex_interpolation, subdiv_vert);
}
+static bool subdiv_mesh_is_center_vertex(const MPoly *coarse_poly, const float u, const float v)
+{
+ if (coarse_poly->totloop == 4) {
+ if (u == 0.5f && v == 0.5f) {
+ return true;
+ }
+ }
+ else {
+ if (u == 1.0f && v == 1.0f) {
+ return true;
+ }
+ }
+ return false;
+}
+
+static void subdiv_mesh_tag_center_vertex(const MPoly *coarse_poly,
+ MVert *subdiv_vert,
+ const float u,
+ const float v)
+{
+ if (subdiv_mesh_is_center_vertex(coarse_poly, u, v)) {
+ subdiv_vert->flag |= ME_VERT_FACEDOT;
+ }
+}
+
static void subdiv_mesh_vertex_inner(const SubdivForeachContext *foreach_context,
void *tls_v,
const int ptex_face_index,
@@ -741,6 +768,7 @@ static void subdiv_mesh_vertex_inner(const SubdivForeachContext *foreach_context
subdiv_vertex_data_interpolate(ctx, subdiv_vert, &tls->vertex_interpolation, u, v);
eval_final_point_and_vertex_normal(
subdiv, ptex_face_index, u, v, subdiv_vert->co, subdiv_vert->no);
+ subdiv_mesh_tag_center_vertex(coarse_poly, subdiv_vert, u, v);
}
/* =============================================================================
@@ -1098,8 +1126,8 @@ static void setup_foreach_callbacks(const SubdivMeshContext *subdiv_context,
foreach_context->vertex_every_edge = subdiv_mesh_vertex_every_edge;
}
else {
- foreach_context->vertex_every_corner = NULL;
- foreach_context->vertex_every_edge = NULL;
+ foreach_context->vertex_every_corner = subdiv_mesh_vertex_every_corner;
+ foreach_context->vertex_every_edge = subdiv_mesh_vertex_every_edge;
}
foreach_context->vertex_corner = subdiv_mesh_vertex_corner;
foreach_context->vertex_edge = subdiv_mesh_vertex_edge;
diff --git a/source/blender/blenkernel/intern/text.c b/source/blender/blenkernel/intern/text.c
index 7d5862c1fb6..056229ceb1c 100644
--- a/source/blender/blenkernel/intern/text.c
+++ b/source/blender/blenkernel/intern/text.c
@@ -79,96 +79,24 @@
*
* Display
* --
+ *
* The st->top determines at what line the top of the text is displayed.
* If the user moves the cursor the st containing that cursor should
* be popped ... other st's retain their own top location.
- *
- * Undo
- * --
- * Undo/Redo works by storing
- * events in a queue, and a pointer
- * to the current position in the
- * queue...
- *
- * Events are stored using an
- * arbitrary op-code system
- * to keep track of
- * a) the two cursors (normal and selected)
- * b) input (visible and control (ie backspace))
- *
- * input data is stored as its
- * ASCII value, the opcodes are
- * then selected to not conflict.
- *
- * opcodes with data in between are
- * written at the beginning and end
- * of the data to allow undo and redo
- * to simply check the code at the current
- * undo position
*/
-/* Undo opcodes */
-
-enum {
- /* Complex editing */
- /* 1 - opcode is followed by 1 byte for ascii character and opcode (repeat)) */
- /* 2 - opcode is followed by 2 bytes for utf-8 character and opcode (repeat)) */
- /* 3 - opcode is followed by 3 bytes for utf-8 character and opcode (repeat)) */
- /* 4 - opcode is followed by 4 bytes for unicode character and opcode (repeat)) */
- UNDO_INSERT_1 = 013,
- UNDO_INSERT_2 = 014,
- UNDO_INSERT_3 = 015,
- UNDO_INSERT_4 = 016,
-
- UNDO_BS_1 = 017,
- UNDO_BS_2 = 020,
- UNDO_BS_3 = 021,
- UNDO_BS_4 = 022,
-
- UNDO_DEL_1 = 023,
- UNDO_DEL_2 = 024,
- UNDO_DEL_3 = 025,
- UNDO_DEL_4 = 026,
-
- /* Text block (opcode is followed
- * by 4 character length ID + the text
- * block itself + the 4 character length
- * ID (repeat) and opcode (repeat)) */
- UNDO_DBLOCK = 027, /* Delete block */
- UNDO_IBLOCK = 030, /* Insert block */
-
- /* Misc */
- UNDO_INDENT = 032,
- UNDO_UNINDENT = 033,
- UNDO_COMMENT = 034,
- UNDO_UNCOMMENT = 035,
-
- UNDO_MOVE_LINES_UP = 036,
- UNDO_MOVE_LINES_DOWN = 037,
-
- UNDO_DUPLICATE = 040,
-};
-
/***/
static void txt_pop_first(Text *text);
static void txt_pop_last(Text *text);
-static void txt_undo_add_blockop(Text *text, TextUndoBuf *utxt, int op, const char *buf);
static void txt_delete_line(Text *text, TextLine *line);
-static void txt_delete_sel(Text *text, TextUndoBuf *utxt);
+static void txt_delete_sel(Text *text);
static void txt_make_dirty(Text *text);
/***/
/**
- * Set to true when undoing (so we don't generate undo steps while undoing).
- *
- * Also use to disable undo entirely.
- */
-static bool undoing;
-
-/**
- * \note caller must handle `undo_buf` and `compiled` members.
+ * \note caller must handle `compiled` member.
*/
void BKE_text_free_lines(Text *text)
{
@@ -238,6 +166,8 @@ Text *BKE_text_add(Main *bmain, const char *name)
Text *ta;
ta = BKE_libblock_alloc(bmain, ID_TXT, name, 0);
+ /* Texts always have 'real' user (see also read code). */
+ id_us_ensure_real(&ta->id);
BKE_text_init(ta);
@@ -426,7 +356,8 @@ Text *BKE_text_load_ex(Main *bmain, const char *file, const char *relpath, const
}
ta = BKE_libblock_alloc(bmain, ID_TXT, BLI_path_basename(filepath_abs), 0);
- ta->id.us = 0;
+ /* Texts always have 'real' user (see also read code). */
+ id_us_ensure_real(&ta->id);
BLI_listbase_clear(&ta->lines);
ta->curl = ta->sell = NULL;
@@ -516,29 +447,17 @@ void BKE_text_make_local(Main *bmain, Text *text, const bool lib_local)
BKE_id_make_local_generic(bmain, &text->id, true, lib_local);
}
-void BKE_text_clear(Text *text, TextUndoBuf *utxt) /* called directly from rna */
+void BKE_text_clear(Text *text) /* called directly from rna */
{
- const bool undoing_orig = undoing;
- undoing = (utxt == NULL);
-
txt_sel_all(text);
- txt_delete_sel(text, utxt);
-
- undoing = undoing_orig;
-
+ txt_delete_sel(text);
txt_make_dirty(text);
}
-void BKE_text_write(Text *text, TextUndoBuf *utxt, const char *str) /* called directly from rna */
+void BKE_text_write(Text *text, const char *str) /* called directly from rna */
{
- const bool undoing_orig = undoing;
- undoing = (utxt == NULL);
-
- txt_insert_buf(text, utxt, str);
+ txt_insert_buf(text, str);
txt_move_eof(text, 0);
-
- undoing = undoing_orig;
-
txt_make_dirty(text);
}
@@ -1270,7 +1189,7 @@ bool txt_has_sel(Text *text)
return ((text->curl != text->sell) || (text->curc != text->selc));
}
-static void txt_delete_sel(Text *text, TextUndoBuf *utxt)
+static void txt_delete_sel(Text *text)
{
TextLine *tmpl;
char *buf;
@@ -1288,12 +1207,6 @@ static void txt_delete_sel(Text *text, TextUndoBuf *utxt)
txt_order_cursors(text, false);
- if (!undoing) {
- buf = txt_sel_to_buf(text);
- txt_undo_add_blockop(text, utxt, UNDO_DBLOCK, buf);
- MEM_freeN(buf);
- }
-
buf = MEM_mallocN(text->curc + (text->sell->len - text->selc) + 1, "textline_string");
strncpy(buf, text->curl->line, text->curc);
@@ -1349,17 +1262,121 @@ void txt_sel_line(Text *text)
text->selc = text->sell->len;
}
+/* -------------------------------------------------------------------- */
+/** \name Buffer Conversion for Undo/Redo
+ *
+ * Buffer conversion functions that rely on the buffer already being validated.
+ *
+ * The only requirement for these functions is that they're reverse-able,
+ * the undo logic doesn't inspect their content.
+ *
+ * Currently buffers:
+ * - Always ends with a new-line.
+ * - Are not null terminated.
+ * \{ */
+
+/**
+ * Create a buffer, the only requirement is #txt_from_buf_for_undo can decode it.
+ */
+char *txt_to_buf_for_undo(Text *text, int *r_buf_len)
+{
+ int buf_len = 0;
+ for (const TextLine *l = text->lines.first; l; l = l->next) {
+ buf_len += l->len + 1;
+ }
+ char *buf = MEM_mallocN(buf_len, __func__);
+ char *buf_step = buf;
+ for (const TextLine *l = text->lines.first; l; l = l->next) {
+ memcpy(buf_step, l->line, l->len);
+ buf_step += l->len;
+ *buf_step++ = '\n';
+ }
+ *r_buf_len = buf_len;
+ return buf;
+}
+
+/**
+ * Decode a buffer from #txt_to_buf_for_undo.
+ */
+void txt_from_buf_for_undo(Text *text, const char *buf, int buf_len)
+{
+ const char *buf_end = buf + buf_len;
+ const char *buf_step = buf;
+
+ /* First re-use existing lines.
+ * Good for undo since it means in practice many operations re-use all
+ * except for the modified line. */
+ TextLine *l_src = text->lines.first;
+ BLI_listbase_clear(&text->lines);
+ while (buf_step != buf_end && l_src) {
+ /* New lines are ensured by #txt_to_buf_for_undo. */
+ const char *buf_step_next = strchr(buf_step, '\n');
+ const int len = buf_step_next - buf_step;
+
+ TextLine *l = l_src;
+ l_src = l_src->next;
+ if (l->len != len) {
+ l->line = MEM_reallocN(l->line, len + 1);
+ l->len = len;
+ }
+ MEM_SAFE_FREE(l->format);
+
+ memcpy(l->line, buf_step, len);
+ l->line[len] = '\0';
+ BLI_addtail(&text->lines, l);
+ buf_step = buf_step_next + 1;
+ }
+
+ /* If we have extra lines. */
+ while (l_src != NULL) {
+ TextLine *l_src_next = l_src->next;
+ MEM_freeN(l_src->line);
+ if (l_src->format) {
+ MEM_freeN(l_src->format);
+ }
+ MEM_freeN(l_src);
+ l_src = l_src_next;
+ }
+
+ while (buf_step != buf_end) {
+ /* New lines are ensured by #txt_to_buf_for_undo. */
+ const char *buf_step_next = strchr(buf_step, '\n');
+ const int len = buf_step_next - buf_step;
+
+ TextLine *l = MEM_mallocN(sizeof(TextLine), "textline");
+ l->line = MEM_mallocN(len + 1, "textline_string");
+ l->len = len;
+ l->format = NULL;
+
+ memcpy(l->line, buf_step, len);
+ l->line[len] = '\0';
+ BLI_addtail(&text->lines, l);
+ buf_step = buf_step_next + 1;
+ }
+
+ text->curl = text->sell = text->lines.first;
+ text->curc = text->selc = 0;
+
+ txt_make_dirty(text);
+}
+
+/** \} */
+
/***************************/
/* Cut and paste functions */
/***************************/
-char *txt_to_buf(Text *text)
+char *txt_to_buf(Text *text, int *r_buf_strlen)
{
int length;
TextLine *tmp, *linef, *linel;
int charf, charl;
char *buf;
+ if (r_buf_strlen) {
+ *r_buf_strlen = 0;
+ }
+
if (!text->curl) {
return NULL;
}
@@ -1419,6 +1436,10 @@ char *txt_to_buf(Text *text)
buf[length] = 0;
}
+ if (r_buf_strlen) {
+ *r_buf_strlen = length;
+ }
+
return buf;
}
@@ -1475,13 +1496,17 @@ int txt_find_string(Text *text, const char *findstr, int wrap, int match_case)
}
}
-char *txt_sel_to_buf(Text *text)
+char *txt_sel_to_buf(Text *text, int *r_buf_strlen)
{
char *buf;
int length = 0;
TextLine *tmp, *linef, *linel;
int charf, charl;
+ if (r_buf_strlen) {
+ *r_buf_strlen = 0;
+ }
+
if (!text->curl) {
return NULL;
}
@@ -1556,12 +1581,15 @@ char *txt_sel_to_buf(Text *text)
buf[length] = 0;
}
+ if (r_buf_strlen) {
+ *r_buf_strlen = length;
+ }
+
return buf;
}
-void txt_insert_buf(Text *text, TextUndoBuf *utxt, const char *in_buffer)
+void txt_insert_buf(Text *text, const char *in_buffer)
{
- const bool undoing_orig = undoing;
int l = 0, len;
size_t i = 0, j;
TextLine *add;
@@ -1571,24 +1599,19 @@ void txt_insert_buf(Text *text, TextUndoBuf *utxt, const char *in_buffer)
return;
}
- txt_delete_sel(text, utxt);
+ txt_delete_sel(text);
len = strlen(in_buffer);
buffer = BLI_strdupn(in_buffer, len);
len += txt_extended_ascii_as_utf8(&buffer);
- if (!undoing) {
- txt_undo_add_blockop(text, utxt, UNDO_IBLOCK, buffer);
- }
- undoing = true;
-
/* Read the first line (or as close as possible */
while (buffer[i] && buffer[i] != '\n') {
- txt_add_raw_char(text, utxt, BLI_str_utf8_as_unicode_step(buffer, &i));
+ txt_add_raw_char(text, BLI_str_utf8_as_unicode_step(buffer, &i));
}
if (buffer[i] == '\n') {
- txt_split_curline(text, utxt);
+ txt_split_curline(text);
i++;
while (i < len) {
@@ -1606,7 +1629,7 @@ void txt_insert_buf(Text *text, TextUndoBuf *utxt, const char *in_buffer)
}
else {
for (j = i - l; j < i && j < len;) {
- txt_add_raw_char(text, utxt, BLI_str_utf8_as_unicode_step(buffer, &j));
+ txt_add_raw_char(text, BLI_str_utf8_as_unicode_step(buffer, &j));
}
break;
}
@@ -1614,1046 +1637,13 @@ void txt_insert_buf(Text *text, TextUndoBuf *utxt, const char *in_buffer)
}
MEM_freeN(buffer);
- undoing = undoing_orig;
-}
-
-/******************/
-/* Undo functions */
-/******************/
-
-static bool max_undo_test(TextUndoBuf *utxt, int x)
-{
- /* Normally over-allocating is preferred,
- * however in this case the buffer is small enough and re-allocation
- * fast enough for each undo step that it's not a problem to allocate each time.
- * This also saves on some memory when we have many text buffers
- * that would have an empty undo memory allocated.
- */
-
- /* Add one for the null terminator. */
- utxt->len = utxt->pos + x + 1;
- if (utxt->len > TXT_MAX_UNDO) {
- /* XXX error("Undo limit reached, buffer cleared\n"); */
- MEM_freeN(utxt->buf);
- return false;
- }
- else {
- /* Small reallocations on each undo step is fine. */
- utxt->buf = MEM_recallocN(utxt->buf, utxt->len);
- }
- return true;
-}
-
-static void txt_undo_end(Text *UNUSED(text), TextUndoBuf *utxt)
-{
- int undo_pos_end = utxt->pos + 1;
- BLI_assert(undo_pos_end + 1 == utxt->len);
- utxt->buf[undo_pos_end] = '\0';
-}
-
-/* Call once undo is done. */
-#ifndef NDEBUG
-
-#endif
-
-#if 0 /* UNUSED */
-static void dump_buffer(TextUndoBuf *utxt)
-{
- int i = 0;
-
- while (i++ < utxt->undo_pos)
- printf("%d: %d %c\n", i, utxt->buf[i], utxt->buf[i]);
-}
-
-/* Note: this function is outdated and must be updated if needed for future use */
-void txt_print_undo(Text *text)
-{
- int i = 0;
- int op;
- const char *ops;
- int linep, charp;
-
- dump_buffer(text);
-
- printf("---< Undo Buffer >---\n");
-
- printf("UndoPosition is %d\n", utxt->pos);
-
- while (i <= utxt->pos) {
- op = utxt->buf[i];
-
- if (op == UNDO_INSERT_1) {
- ops = "Insert ascii ";
- }
- else if (op == UNDO_INSERT_2) {
- ops = "Insert 2 bytes ";
- }
- else if (op == UNDO_INSERT_3) {
- ops = "Insert 3 bytes ";
- }
- else if (op == UNDO_INSERT_4) {
- ops = "Insert unicode ";
- }
- else if (op == UNDO_BS_1) {
- ops = "Backspace for ascii ";
- }
- else if (op == UNDO_BS_2) {
- ops = "Backspace for 2 bytes ";
- }
- else if (op == UNDO_BS_3) {
- ops = "Backspace for 3 bytes ";
- }
- else if (op == UNDO_BS_4) {
- ops = "Backspace for unicode ";
- }
- else if (op == UNDO_DEL_1) {
- ops = "Delete ascii ";
- }
- else if (op == UNDO_DEL_2) {
- ops = "Delete 2 bytes ";
- }
- else if (op == UNDO_DEL_3) {
- ops = "Delete 3 bytes ";
- }
- else if (op == UNDO_DEL_4) {
- ops = "Delete unicode ";
- }
- else if (op == UNDO_DBLOCK) {
- ops = "Delete text block";
- }
- else if (op == UNDO_IBLOCK) {
- ops = "Insert text block";
- }
- else if (op == UNDO_INDENT) {
- ops = "Indent ";
- }
- else if (op == UNDO_UNINDENT) {
- ops = "Unindent ";
- }
- else if (op == UNDO_COMMENT) {
- ops = "Comment ";
- }
- else if (op == UNDO_UNCOMMENT) {
- ops = "Uncomment ";
- }
- else {
- ops = "Unknown";
- }
-
- printf("Op (%o) at %d = %s", op, i, ops);
- if (op >= UNDO_INSERT_1 && op <= UNDO_DEL_4) {
- i++;
- printf(" - Char is ");
- switch (op) {
- case UNDO_INSERT_1:
- case UNDO_BS_1:
- case UNDO_DEL_1:
- printf("%c", utxt->buf[i]);
- i++;
- break;
- case UNDO_INSERT_2:
- case UNDO_BS_2:
- case UNDO_DEL_2:
- printf("%c%c", utxt->buf[i], utxt->buf[i + 1]);
- i += 2;
- break;
- case UNDO_INSERT_3:
- case UNDO_BS_3:
- case UNDO_DEL_3:
- printf("%c%c%c", utxt->buf[i], utxt->buf[i + 1], utxt->buf[i + 2]);
- i += 3;
- break;
- case UNDO_INSERT_4:
- case UNDO_BS_4:
- case UNDO_DEL_4: {
- unsigned int uc;
- char c[BLI_UTF8_MAX + 1];
- size_t c_len;
- uc = utxt->buf[i];
- i++;
- uc = uc + (utxt->buf[i] << 8);
- i++;
- uc = uc + (utxt->buf[i] << 16);
- i++;
- uc = uc + (utxt->buf[i] << 24);
- i++;
- c_len = BLI_str_utf8_from_unicode(uc, c);
- c[c_len] = '\0';
- puts(c);
- break;
- }
- }
- }
- else if (op == UNDO_DBLOCK || op == UNDO_IBLOCK) {
- i++;
-
- linep = utxt->buf[i];
- i++;
- linep = linep + (utxt->buf[i] << 8);
- i++;
- linep = linep + (utxt->buf[i] << 16);
- i++;
- linep = linep + (utxt->buf[i] << 24);
- i++;
-
- printf(" (length %d) <", linep);
-
- while (linep > 0) {
- putchar(utxt->buf[i]);
- linep--;
- i++;
- }
-
- linep = utxt->buf[i];
- i++;
- linep = linep + (utxt->buf[i] << 8);
- i++;
- linep = linep + (utxt->buf[i] << 16);
- i++;
- linep = linep + (utxt->buf[i] << 24);
- i++;
- printf("> (%d)", linep);
- }
- else if (op == UNDO_INDENT || op == UNDO_UNINDENT) {
- i++;
-
- charp = utxt->buf[i];
- i++;
- charp = charp + (utxt->buf[i] << 8);
- i++;
-
- linep = utxt->buf[i];
- i++;
- linep = linep + (utxt->buf[i] << 8);
- i++;
- linep = linep + (utxt->buf[i] << 16);
- i++;
- linep = linep + (utxt->buf[i] << 24);
- i++;
-
- printf("to <%d, %d> ", linep, charp);
-
- charp = utxt->buf[i];
- i++;
- charp = charp + (utxt->buf[i] << 8);
- i++;
-
- linep = utxt->buf[i];
- i++;
- linep = linep + (utxt->buf[i] << 8);
- i++;
- linep = linep + (utxt->buf[i] << 16);
- i++;
- linep = linep + (utxt->buf[i] << 24);
- i++;
-
- printf("from <%d, %d>", linep, charp);
- }
-
- printf(" %d\n", i);
- i++;
- }
-}
-#endif
-
-static void txt_undo_store_uint16(char *undo_buf, int *undo_pos, unsigned short value)
-{
- undo_buf[*undo_pos] = (value)&0xff;
- (*undo_pos)++;
- undo_buf[*undo_pos] = (value >> 8) & 0xff;
- (*undo_pos)++;
-}
-
-static void txt_undo_store_uint32(char *undo_buf, int *undo_pos, unsigned int value)
-{
- undo_buf[*undo_pos] = (value)&0xff;
- (*undo_pos)++;
- undo_buf[*undo_pos] = (value >> 8) & 0xff;
- (*undo_pos)++;
- undo_buf[*undo_pos] = (value >> 16) & 0xff;
- (*undo_pos)++;
- undo_buf[*undo_pos] = (value >> 24) & 0xff;
- (*undo_pos)++;
-}
-
-/* store the cur cursor to the undo buffer (6 bytes)*/
-static void txt_undo_store_cur(Text *text, TextUndoBuf *utxt)
-{
- txt_undo_store_uint16(utxt->buf, &utxt->pos, text->curc);
- txt_undo_store_uint32(utxt->buf, &utxt->pos, txt_get_span(text->lines.first, text->curl));
-}
-
-/* store the sel cursor to the undo buffer (6 bytes) */
-static void txt_undo_store_sel(Text *text, TextUndoBuf *utxt)
-{
- txt_undo_store_uint16(utxt->buf, &utxt->pos, text->selc);
- txt_undo_store_uint32(utxt->buf, &utxt->pos, txt_get_span(text->lines.first, text->sell));
-}
-
-/* store both cursors to the undo buffer (12 bytes) */
-static void txt_undo_store_cursors(Text *text, TextUndoBuf *utxt)
-{
- txt_undo_store_cur(text, utxt);
- txt_undo_store_sel(text, utxt);
-}
-
-/* store an operator along with a block of data */
-static void txt_undo_add_blockop(Text *text, TextUndoBuf *utxt, int op, const char *buf)
-{
- unsigned int length = strlen(buf);
-
- if (!max_undo_test(utxt, 2 + 12 + 4 + length + 4 + 1)) {
- return;
- }
- /* 2 bytes */
- utxt->pos++;
- utxt->buf[utxt->pos] = op;
- utxt->pos++;
- /* 12 bytes */
- txt_undo_store_cursors(text, utxt);
- /* 4 bytes */
- txt_undo_store_uint32(utxt->buf, &utxt->pos, length);
- /* 'length' bytes */
- memcpy(utxt->buf + utxt->pos, buf, length);
- utxt->pos += length;
- /* 4 bytes */
- txt_undo_store_uint32(utxt->buf, &utxt->pos, length);
- /* 1 byte */
- utxt->buf[utxt->pos] = op;
-
- txt_undo_end(text, utxt);
-}
-
-/* store a regular operator */
-void txt_undo_add_op(Text *text, TextUndoBuf *utxt, int op)
-{
- if (!max_undo_test(utxt, 2 + 12 + 1)) {
- return;
- }
-
- /* 2 bytes */
- utxt->pos++;
- utxt->buf[utxt->pos] = op;
- utxt->pos++;
- /* 12 bytes */
- txt_undo_store_cursors(text, utxt);
- /* 1 byte */
- utxt->buf[utxt->pos] = op;
-
- txt_undo_end(text, utxt);
-}
-
-/* store an operator for a single character */
-static void txt_undo_add_charop(Text *text, TextUndoBuf *utxt, int op_start, unsigned int c)
-{
- char utf8[BLI_UTF8_MAX];
- size_t i, utf8_size = BLI_str_utf8_from_unicode(c, utf8);
-
- if (utf8_size < 4 && 0) {
- if (!max_undo_test(utxt, 2 + 6 + utf8_size + 1)) {
- return;
- }
- /* 2 bytes */
- utxt->pos++;
- utxt->buf[utxt->pos] = op_start + utf8_size - 1;
- utxt->pos++;
- /* 6 bytes */
- txt_undo_store_cur(text, utxt);
- /* 'utf8_size' bytes */
- for (i = 0; i < utf8_size; i++) {
- utxt->buf[utxt->pos] = utf8[i];
- utxt->pos++;
- }
- /* 1 byte */
- utxt->buf[utxt->pos] = op_start + utf8_size - 1;
- }
- else {
- if (!max_undo_test(utxt, 2 + 6 + 4 + 1)) {
- return;
- }
- /* 2 bytes */
- utxt->pos++;
- utxt->buf[utxt->pos] = op_start + 3;
- utxt->pos++;
- /* 6 bytes */
- txt_undo_store_cur(text, utxt);
- /* 4 bytes */
- txt_undo_store_uint32(utxt->buf, &utxt->pos, c);
- /* 1 byte */
- utxt->buf[utxt->pos] = op_start + 3;
- }
-
- txt_undo_end(text, utxt);
-}
-
-/* extends Link */
-struct LinkInt {
- struct LinkInt *next, *prev;
- int value;
-};
-
-/**
- * UnindentLines points to a #ListBase composed of #LinkInt elements, listing the numbers
- * of the lines that should not be indented back.
- */
-static void txt_undo_add_unprefix_op(Text *text,
- TextUndoBuf *utxt,
- char undo_op,
- const ListBase *line_index_mask,
- const int line_index_mask_len)
-{
- struct LinkInt *idata;
-
- BLI_assert(BLI_listbase_count(line_index_mask) == line_index_mask_len);
-
- /* OP byte + u32 count + counted u32 line numbers + u32 count + 12-bytes selection + OP byte. */
- if (!max_undo_test(utxt, 2 + 4 + (line_index_mask_len * 4) + 4 + 12 + 1)) {
- return;
- }
-
- /* 2 bytes */
- utxt->pos++;
- utxt->buf[utxt->pos] = undo_op;
- utxt->pos++;
- /* Adding number of line numbers to read
- * 4 bytes */
- txt_undo_store_uint32(utxt->buf, &utxt->pos, line_index_mask_len);
-
- /* Adding line-numbers of lines that shall not be indented if undoing.
- * 'line_index_mask_len * 4' bytes */
- for (idata = line_index_mask->first; idata; idata = idata->next) {
- txt_undo_store_uint32(utxt->buf, &utxt->pos, idata->value);
- }
-
- /* Adding number of line numbers to read again.
- * 4 bytes */
- txt_undo_store_uint32(utxt->buf, &utxt->pos, line_index_mask_len);
- /* Adding current selection.
- * 12 bytes */
- txt_undo_store_cursors(text, utxt);
- /* Closing with OP (same as above).
- * 1 byte */
- utxt->buf[utxt->pos] = undo_op;
- /* Marking as last undo operation */
- txt_undo_end(text, utxt);
-}
-
-static unsigned short txt_undo_read_uint16(const char *undo_buf, int *undo_pos)
-{
- unsigned short val;
- val = undo_buf[*undo_pos];
- (*undo_pos)--;
- val = (val << 8) + undo_buf[*undo_pos];
- (*undo_pos)--;
- return val;
-}
-
-static unsigned int txt_undo_read_uint32(const char *undo_buf, int *undo_pos)
-{
- unsigned int val;
- val = undo_buf[*undo_pos];
- (*undo_pos)--;
- val = (val << 8) + undo_buf[*undo_pos];
- (*undo_pos)--;
- val = (val << 8) + undo_buf[*undo_pos];
- (*undo_pos)--;
- val = (val << 8) + undo_buf[*undo_pos];
- (*undo_pos)--;
- return val;
-}
-
-/* read the cur cursor from the undo buffer */
-static void txt_undo_read_cur(const char *undo_buf,
- int *undo_pos,
- unsigned int *curln,
- unsigned short *curc)
-{
- *curln = txt_undo_read_uint32(undo_buf, undo_pos);
- *curc = txt_undo_read_uint16(undo_buf, undo_pos);
-}
-
-/* read the sel cursor from the undo buffer */
-static void txt_undo_read_sel(const char *undo_buf,
- int *undo_pos,
- unsigned int *selln,
- unsigned short *selc)
-{
- *selln = txt_undo_read_uint32(undo_buf, undo_pos);
- *selc = txt_undo_read_uint16(undo_buf, undo_pos);
-}
-
-/* read both cursors from the undo buffer */
-static void txt_undo_read_cursors(const char *undo_buf,
- int *undo_pos,
- unsigned int *curln,
- unsigned short *curc,
- unsigned int *selln,
- unsigned short *selc)
-{
- txt_undo_read_sel(undo_buf, undo_pos, selln, selc);
- txt_undo_read_cur(undo_buf, undo_pos, curln, curc);
-}
-
-static unsigned int txt_undo_read_unicode(const char *undo_buf, int *undo_pos, short bytes)
-{
- unsigned int unicode;
- char utf8[BLI_UTF8_MAX + 1];
-
- switch (bytes) {
- case 1: /* ascii */
- unicode = undo_buf[*undo_pos];
- (*undo_pos)--;
- break;
- case 2: /* 2-byte symbol */
- utf8[2] = '\0';
- utf8[1] = undo_buf[*undo_pos];
- (*undo_pos)--;
- utf8[0] = undo_buf[*undo_pos];
- (*undo_pos)--;
- unicode = BLI_str_utf8_as_unicode(utf8);
- break;
- case 3: /* 3-byte symbol */
- utf8[3] = '\0';
- utf8[2] = undo_buf[*undo_pos];
- (*undo_pos)--;
- utf8[1] = undo_buf[*undo_pos];
- (*undo_pos)--;
- utf8[0] = undo_buf[*undo_pos];
- (*undo_pos)--;
- unicode = BLI_str_utf8_as_unicode(utf8);
- break;
- case 4: /* 32-bit unicode symbol */
- unicode = txt_undo_read_uint32(undo_buf, undo_pos);
- break;
- default:
- /* should never happen */
- BLI_assert(0);
- unicode = 0;
- break;
- }
-
- return unicode;
-}
-
-static unsigned short txt_redo_read_uint16(const char *undo_buf, int *undo_pos)
-{
- unsigned short val;
- val = undo_buf[*undo_pos];
- (*undo_pos)++;
- val = val + (undo_buf[*undo_pos] << 8);
- (*undo_pos)++;
- return val;
-}
-
-static unsigned int txt_redo_read_uint32(const char *undo_buf, int *undo_pos)
-{
- unsigned int val;
- val = undo_buf[*undo_pos];
- (*undo_pos)++;
- val = val + (undo_buf[*undo_pos] << 8);
- (*undo_pos)++;
- val = val + (undo_buf[*undo_pos] << 16);
- (*undo_pos)++;
- val = val + (undo_buf[*undo_pos] << 24);
- (*undo_pos)++;
- return val;
-}
-
-/* redo read cur cursor from the undo buffer */
-static void txt_redo_read_cur(const char *undo_buf,
- int *undo_pos,
- unsigned int *curln,
- unsigned short *curc)
-{
- *curc = txt_redo_read_uint16(undo_buf, undo_pos);
- *curln = txt_redo_read_uint32(undo_buf, undo_pos);
-}
-
-/* redo read sel cursor from the undo buffer */
-static void txt_redo_read_sel(const char *undo_buf,
- int *undo_pos,
- unsigned int *selln,
- unsigned short *selc)
-{
- *selc = txt_redo_read_uint16(undo_buf, undo_pos);
- *selln = txt_redo_read_uint32(undo_buf, undo_pos);
-}
-
-/* redo read both cursors from the undo buffer */
-static void txt_redo_read_cursors(const char *undo_buf,
- int *undo_pos,
- unsigned int *curln,
- unsigned short *curc,
- unsigned int *selln,
- unsigned short *selc)
-{
- txt_redo_read_cur(undo_buf, undo_pos, curln, curc);
- txt_redo_read_sel(undo_buf, undo_pos, selln, selc);
-}
-
-static unsigned int txt_redo_read_unicode(const char *undo_buf, int *undo_pos, short bytes)
-{
- unsigned int unicode;
- char utf8[BLI_UTF8_MAX + 1];
-
- switch (bytes) {
- case 1: /* ascii */
- unicode = undo_buf[*undo_pos];
- (*undo_pos)++;
- break;
- case 2: /* 2-byte symbol */
- utf8[0] = undo_buf[*undo_pos];
- (*undo_pos)++;
- utf8[1] = undo_buf[*undo_pos];
- (*undo_pos)++;
- utf8[2] = '\0';
- unicode = BLI_str_utf8_as_unicode(utf8);
- break;
- case 3: /* 3-byte symbol */
- utf8[0] = undo_buf[*undo_pos];
- (*undo_pos)++;
- utf8[1] = undo_buf[*undo_pos];
- (*undo_pos)++;
- utf8[2] = undo_buf[*undo_pos];
- (*undo_pos)++;
- utf8[3] = '\0';
- unicode = BLI_str_utf8_as_unicode(utf8);
- break;
- case 4: /* 32-bit unicode symbol */
- unicode = txt_redo_read_uint32(undo_buf, undo_pos);
- break;
- default:
- /* should never happen */
- BLI_assert(0);
- unicode = 0;
- break;
- }
-
- return unicode;
-}
-
-void txt_do_undo(Text *text, TextUndoBuf *utxt)
-{
- int op = utxt->buf[utxt->pos];
- int prev_flags;
- unsigned int linep;
- unsigned int uni_char;
- unsigned int curln, selln;
- unsigned short curc, selc;
- unsigned short charp;
- char *buf;
-
- if (utxt->pos < 0) {
- return;
- }
-
- utxt->pos--;
-
- undoing = 1;
-
- switch (op) {
- case UNDO_INSERT_1:
- case UNDO_INSERT_2:
- case UNDO_INSERT_3:
- case UNDO_INSERT_4:
- utxt->pos -= op - UNDO_INSERT_1 + 1;
-
- /* get and restore the cursors */
- txt_undo_read_cur(utxt->buf, &utxt->pos, &curln, &curc);
- txt_move_to(text, curln, curc, 0);
- txt_move_to(text, curln, curc, 1);
-
- txt_delete_char(text, utxt);
-
- utxt->pos--;
- break;
-
- case UNDO_BS_1:
- case UNDO_BS_2:
- case UNDO_BS_3:
- case UNDO_BS_4:
- charp = op - UNDO_BS_1 + 1;
- uni_char = txt_undo_read_unicode(utxt->buf, &utxt->pos, charp);
-
- /* get and restore the cursors */
- txt_undo_read_cur(utxt->buf, &utxt->pos, &curln, &curc);
- txt_move_to(text, curln, curc, 0);
- txt_move_to(text, curln, curc, 1);
-
- txt_add_char(text, utxt, uni_char);
-
- utxt->pos--;
- break;
-
- case UNDO_DEL_1:
- case UNDO_DEL_2:
- case UNDO_DEL_3:
- case UNDO_DEL_4:
- charp = op - UNDO_DEL_1 + 1;
- uni_char = txt_undo_read_unicode(utxt->buf, &utxt->pos, charp);
-
- /* get and restore the cursors */
- txt_undo_read_cur(utxt->buf, &utxt->pos, &curln, &curc);
- txt_move_to(text, curln, curc, 0);
- txt_move_to(text, curln, curc, 1);
-
- txt_add_char(text, utxt, uni_char);
-
- txt_move_left(text, 0);
-
- utxt->pos--;
- break;
-
- case UNDO_DBLOCK: {
- int i;
- /* length of the string in the buffer */
- linep = txt_undo_read_uint32(utxt->buf, &utxt->pos);
-
- buf = MEM_mallocN(linep + 1, "dblock buffer");
- for (i = 0; i < linep; i++) {
- buf[(linep - 1) - i] = utxt->buf[utxt->pos];
- utxt->pos--;
- }
- buf[i] = 0;
-
- /* skip over the length that was stored again */
- utxt->pos -= 4;
-
- /* Get the cursor positions */
- txt_undo_read_cursors(utxt->buf, &utxt->pos, &curln, &curc, &selln, &selc);
-
- /* move cur to location that needs buff inserted */
- txt_move_to(text, curln, curc, 0);
-
- txt_insert_buf(text, utxt, buf);
- MEM_freeN(buf);
-
- /* restore the cursors */
- txt_move_to(text, curln, curc, 0);
- txt_move_to(text, selln, selc, 1);
-
- utxt->pos--;
-
- break;
- }
- case UNDO_IBLOCK: {
- int i;
- /* length of the string in the buffer */
- linep = txt_undo_read_uint32(utxt->buf, &utxt->pos);
-
- /* txt_backspace_char removes utf8-characters, not bytes */
- buf = MEM_mallocN(linep + 1, "iblock buffer");
- for (i = 0; i < linep; i++) {
- buf[(linep - 1) - i] = utxt->buf[utxt->pos];
- utxt->pos--;
- }
- buf[i] = 0;
- linep = BLI_strlen_utf8(buf);
- MEM_freeN(buf);
-
- /* skip over the length that was stored again */
- utxt->pos -= 4;
-
- /* get and restore the cursors */
- txt_undo_read_cursors(utxt->buf, &utxt->pos, &curln, &curc, &selln, &selc);
-
- txt_move_to(text, curln, curc, 0);
- txt_move_to(text, selln, selc, 1);
-
- if ((curln == selln) && (curc == selc)) {
- /* disable tabs to spaces since moving right may involve skipping multiple spaces */
- prev_flags = text->flags;
- text->flags &= ~TXT_TABSTOSPACES;
-
- for (i = 0; i < linep; i++) {
- txt_move_right(text, 1);
- }
-
- text->flags = prev_flags;
- }
-
- txt_delete_selected(text, utxt);
-
- utxt->pos--;
- break;
- }
- case UNDO_INDENT:
- case UNDO_COMMENT:
- case UNDO_DUPLICATE:
- case UNDO_MOVE_LINES_UP:
- case UNDO_MOVE_LINES_DOWN:
- /* get and restore the cursors */
- txt_undo_read_cursors(utxt->buf, &utxt->pos, &curln, &curc, &selln, &selc);
- txt_move_to(text, curln, curc, 0);
- txt_move_to(text, selln, selc, 1);
-
- if (op == UNDO_INDENT) {
- txt_unindent(text, utxt);
- }
- else if (op == UNDO_COMMENT) {
- txt_uncomment(text, utxt);
- }
- else if (op == UNDO_DUPLICATE) {
- txt_delete_line(text, text->curl->next);
- }
- else if (op == UNDO_MOVE_LINES_UP) {
- txt_move_lines(text, utxt, TXT_MOVE_LINE_DOWN);
- }
- else if (op == UNDO_MOVE_LINES_DOWN) {
- txt_move_lines(text, utxt, TXT_MOVE_LINE_UP);
- }
-
- utxt->pos--;
- break;
- case UNDO_UNINDENT:
- case UNDO_UNCOMMENT: {
- void (*txt_prefix_fn)(Text *, TextUndoBuf *);
- void (*txt_unprefix_fn)(Text *, TextUndoBuf *);
- int count;
- int i;
- /* Get and restore the cursors */
- txt_undo_read_cursors(utxt->buf, &utxt->pos, &curln, &curc, &selln, &selc);
- txt_move_to(text, curln, curc, 0);
- txt_move_to(text, selln, selc, 1);
-
- /* Un-unindent */
- if (op == UNDO_UNINDENT) {
- txt_prefix_fn = txt_indent;
- txt_unprefix_fn = txt_unindent;
- }
- else {
- txt_prefix_fn = txt_comment;
- txt_unprefix_fn = txt_uncomment;
- }
-
- txt_prefix_fn(text, utxt);
-
- /* Get the count */
- count = txt_undo_read_uint32(utxt->buf, &utxt->pos);
- /* Iterate! */
- txt_pop_sel(text);
-
- for (i = 0; i < count; i++) {
- txt_move_to(text, txt_undo_read_uint32(utxt->buf, &utxt->pos), 0, 0);
- /* Un-un-unindent/comment */
- txt_unprefix_fn(text, utxt);
- }
- /* Restore selection */
- txt_move_to(text, curln, curc, 0);
- txt_move_to(text, selln, selc, 1);
- /* Jumo over count */
- txt_undo_read_uint32(utxt->buf, &utxt->pos);
- /* Jump over closing OP byte */
- utxt->pos--;
- break;
- }
- default:
- // XXX error("Undo buffer error - resetting");
- utxt->pos = -1;
-
- break;
- }
-
- undoing = 0;
-}
-
-void txt_do_redo(Text *text, TextUndoBuf *utxt)
-{
- char op;
- char *buf;
- unsigned int linep;
- unsigned short charp;
- unsigned int uni_uchar;
- unsigned int curln, selln;
- unsigned short curc, selc;
-
- utxt->pos++;
- op = utxt->buf[utxt->pos];
-
- if (!op) {
- utxt->pos--;
- return;
- }
-
- undoing = 1;
-
- switch (op) {
- case UNDO_INSERT_1:
- case UNDO_INSERT_2:
- case UNDO_INSERT_3:
- case UNDO_INSERT_4:
- utxt->pos++;
-
- /* get and restore the cursors */
- txt_redo_read_cur(utxt->buf, &utxt->pos, &curln, &curc);
- txt_move_to(text, curln, curc, 0);
- txt_move_to(text, curln, curc, 1);
-
- charp = op - UNDO_INSERT_1 + 1;
- uni_uchar = txt_redo_read_unicode(utxt->buf, &utxt->pos, charp);
-
- txt_add_char(text, utxt, uni_uchar);
- break;
-
- case UNDO_BS_1:
- case UNDO_BS_2:
- case UNDO_BS_3:
- case UNDO_BS_4:
- utxt->pos++;
-
- /* get and restore the cursors */
- txt_redo_read_cur(utxt->buf, &utxt->pos, &curln, &curc);
- txt_move_to(text, curln, curc, 0);
- txt_move_to(text, curln, curc, 1);
-
- utxt->pos += op - UNDO_BS_1 + 1;
-
- /* move right so we backspace the correct char */
- txt_move_right(text, 0);
- txt_backspace_char(text, utxt);
-
- break;
-
- case UNDO_DEL_1:
- case UNDO_DEL_2:
- case UNDO_DEL_3:
- case UNDO_DEL_4:
- utxt->pos++;
-
- /* get and restore the cursors */
- txt_redo_read_cur(utxt->buf, &utxt->pos, &curln, &curc);
- txt_move_to(text, curln, curc, 0);
- txt_move_to(text, curln, curc, 1);
-
- utxt->pos += op - UNDO_DEL_1 + 1;
-
- txt_delete_char(text, utxt);
-
- break;
-
- case UNDO_DBLOCK:
- utxt->pos++;
-
- /* get and restore the cursors */
- txt_redo_read_cursors(utxt->buf, &utxt->pos, &curln, &curc, &selln, &selc);
- txt_move_to(text, curln, curc, 0);
- txt_move_to(text, selln, selc, 1);
-
- /* length of the block */
- linep = txt_redo_read_uint32(utxt->buf, &utxt->pos);
-
- utxt->pos += linep;
-
- /* skip over the length that was stored again */
- utxt->pos += 4;
-
- txt_delete_sel(text, utxt);
-
- break;
-
- case UNDO_IBLOCK:
- utxt->pos++;
-
- /* get and restore the cursors */
- txt_redo_read_cursors(utxt->buf, &utxt->pos, &curln, &curc, &selln, &selc);
- txt_move_to(text, curln, curc, 0);
- txt_move_to(text, curln, curc, 1);
-
- /* length of the block */
- linep = txt_redo_read_uint32(utxt->buf, &utxt->pos);
-
- buf = MEM_mallocN(linep + 1, "iblock buffer");
- memcpy(buf, &utxt->buf[utxt->pos], linep);
- utxt->pos += linep;
- buf[linep] = 0;
-
- txt_insert_buf(text, utxt, buf);
- MEM_freeN(buf);
-
- /* skip over the length that was stored again */
- utxt->pos += 4;
-
- break;
-
- case UNDO_INDENT:
- case UNDO_COMMENT:
- case UNDO_UNCOMMENT:
- case UNDO_DUPLICATE:
- case UNDO_MOVE_LINES_UP:
- case UNDO_MOVE_LINES_DOWN:
- utxt->pos++;
-
- /* get and restore the cursors */
- txt_redo_read_cursors(utxt->buf, &utxt->pos, &curln, &curc, &selln, &selc);
- txt_move_to(text, curln, curc, 0);
- txt_move_to(text, selln, selc, 1);
-
- if (op == UNDO_INDENT) {
- txt_indent(text, utxt);
- }
- else if (op == UNDO_COMMENT) {
- txt_comment(text, utxt);
- }
- else if (op == UNDO_UNCOMMENT) {
- txt_uncomment(text, utxt);
- }
- else if (op == UNDO_DUPLICATE) {
- txt_duplicate_line(text, utxt);
- }
- else if (op == UNDO_MOVE_LINES_UP) {
- /* offset the cursor by + 1 */
- txt_move_to(text, curln + 1, curc, 0);
- txt_move_to(text, selln + 1, selc, 1);
-
- txt_move_lines(text, utxt, TXT_MOVE_LINE_UP);
- }
- else if (op == UNDO_MOVE_LINES_DOWN) {
- /* offset the cursor by - 1 */
- txt_move_to(text, curln - 1, curc, 0);
- txt_move_to(text, selln - 1, selc, 1);
-
- txt_move_lines(text, utxt, TXT_MOVE_LINE_DOWN);
- }
-
- /* re-restore the cursors since they got moved when redoing */
- txt_move_to(text, curln, curc, 0);
- txt_move_to(text, selln, selc, 1);
-
- break;
- case UNDO_UNINDENT: {
- int count;
- int i;
-
- utxt->pos++;
- /* Scan all the stuff described in txt_undo_add_unindent_op */
- count = txt_redo_read_uint32(utxt->buf, &utxt->pos);
- for (i = 0; i < count; i++) {
- txt_redo_read_uint32(utxt->buf, &utxt->pos);
- }
- /* Count again */
- txt_redo_read_uint32(utxt->buf, &utxt->pos);
- /* Get the selection and re-unindent */
- txt_redo_read_cursors(utxt->buf, &utxt->pos, &curln, &curc, &selln, &selc);
- txt_move_to(text, curln, curc, 0);
- txt_move_to(text, selln, selc, 1);
- txt_unindent(text, utxt);
- break;
- }
- default:
- // XXX error("Undo buffer error - resetting");
- utxt->pos = -1;
-
- break;
- }
-
- undoing = 0;
}
/**************************/
/* Line editing functions */
/**************************/
-void txt_split_curline(Text *text, TextUndoBuf *utxt)
+void txt_split_curline(Text *text)
{
TextLine *ins;
char *left, *right;
@@ -2662,11 +1652,7 @@ void txt_split_curline(Text *text, TextUndoBuf *utxt)
return;
}
- txt_delete_sel(text, utxt);
-
- if (!undoing) {
- txt_undo_add_charop(text, utxt, UNDO_INSERT_1, '\n');
- }
+ txt_delete_sel(text);
/* Make the two half strings */
@@ -2749,7 +1735,7 @@ static void txt_combine_lines(Text *text, TextLine *linea, TextLine *lineb)
txt_clean_text(text);
}
-void txt_duplicate_line(Text *text, TextUndoBuf *utxt)
+void txt_duplicate_line(Text *text)
{
TextLine *textline;
@@ -2763,14 +1749,10 @@ void txt_duplicate_line(Text *text, TextUndoBuf *utxt)
txt_make_dirty(text);
txt_clean_text(text);
-
- if (!undoing) {
- txt_undo_add_op(text, utxt, UNDO_DUPLICATE);
- }
}
}
-void txt_delete_char(Text *text, TextUndoBuf *utxt)
+void txt_delete_char(Text *text)
{
unsigned int c = '\n';
@@ -2779,7 +1761,7 @@ void txt_delete_char(Text *text, TextUndoBuf *utxt)
}
if (txt_has_sel(text)) { /* deleting a selection */
- txt_delete_sel(text, utxt);
+ txt_delete_sel(text);
txt_make_dirty(text);
return;
}
@@ -2795,6 +1777,7 @@ void txt_delete_char(Text *text, TextUndoBuf *utxt)
else { /* Just deleting a char */
size_t c_len = 0;
c = BLI_str_utf8_as_unicode_and_size(text->curl->line + text->curc, &c_len);
+ UNUSED_VARS(c);
memmove(text->curl->line + text->curc,
text->curl->line + text->curc + c_len,
@@ -2807,20 +1790,16 @@ void txt_delete_char(Text *text, TextUndoBuf *utxt)
txt_make_dirty(text);
txt_clean_text(text);
-
- if (!undoing) {
- txt_undo_add_charop(text, utxt, UNDO_DEL_1, c);
- }
}
-void txt_delete_word(Text *text, TextUndoBuf *utxt)
+void txt_delete_word(Text *text)
{
txt_jump_right(text, true, true);
- txt_delete_sel(text, utxt);
+ txt_delete_sel(text);
txt_make_dirty(text);
}
-void txt_backspace_char(Text *text, TextUndoBuf *utxt)
+void txt_backspace_char(Text *text)
{
unsigned int c = '\n';
@@ -2829,7 +1808,7 @@ void txt_backspace_char(Text *text, TextUndoBuf *utxt)
}
if (txt_has_sel(text)) { /* deleting a selection */
- txt_delete_sel(text, utxt);
+ txt_delete_sel(text);
txt_make_dirty(text);
return;
}
@@ -2848,6 +1827,7 @@ void txt_backspace_char(Text *text, TextUndoBuf *utxt)
size_t c_len = 0;
const char *prev = BLI_str_prev_char_utf8(text->curl->line + text->curc);
c = BLI_str_utf8_as_unicode_and_size(prev, &c_len);
+ UNUSED_VARS(c);
/* source and destination overlap, don't use memcpy() */
memmove(text->curl->line + text->curc - c_len,
@@ -2862,16 +1842,12 @@ void txt_backspace_char(Text *text, TextUndoBuf *utxt)
txt_make_dirty(text);
txt_clean_text(text);
-
- if (!undoing) {
- txt_undo_add_charop(text, utxt, UNDO_BS_1, c);
- }
}
-void txt_backspace_word(Text *text, TextUndoBuf *utxt)
+void txt_backspace_word(Text *text)
{
txt_jump_left(text, true, true);
- txt_delete_sel(text, utxt);
+ txt_delete_sel(text);
txt_make_dirty(text);
}
@@ -2880,17 +1856,17 @@ void txt_backspace_word(Text *text, TextUndoBuf *utxt)
* Remember to change this string according to max tab size */
static char tab_to_spaces[] = " ";
-static void txt_convert_tab_to_spaces(Text *text, TextUndoBuf *utxt)
+static void txt_convert_tab_to_spaces(Text *text)
{
/* sb aims to pad adjust the tab-width needed so that the right number of spaces
* is added so that the indention of the line is the right width (i.e. aligned
* to multiples of TXT_TABSIZE)
*/
const char *sb = &tab_to_spaces[text->curc % TXT_TABSIZE];
- txt_insert_buf(text, utxt, sb);
+ txt_insert_buf(text, sb);
}
-static bool txt_add_char_intern(Text *text, TextUndoBuf *utxt, unsigned int add, bool replace_tabs)
+static bool txt_add_char_intern(Text *text, unsigned int add, bool replace_tabs)
{
char *tmp, ch[BLI_UTF8_MAX];
size_t add_len;
@@ -2900,21 +1876,17 @@ static bool txt_add_char_intern(Text *text, TextUndoBuf *utxt, unsigned int add,
}
if (add == '\n') {
- txt_split_curline(text, utxt);
+ txt_split_curline(text);
return true;
}
/* insert spaces rather than tabs */
if (add == '\t' && replace_tabs) {
- txt_convert_tab_to_spaces(text, utxt);
+ txt_convert_tab_to_spaces(text);
return true;
}
- txt_delete_sel(text, utxt);
-
- if (!undoing) {
- txt_undo_add_charop(text, utxt, UNDO_INSERT_1, add);
- }
+ txt_delete_sel(text);
add_len = BLI_str_utf8_from_unicode(add, ch);
@@ -2937,23 +1909,23 @@ static bool txt_add_char_intern(Text *text, TextUndoBuf *utxt, unsigned int add,
return 1;
}
-bool txt_add_char(Text *text, TextUndoBuf *utxt, unsigned int add)
+bool txt_add_char(Text *text, unsigned int add)
{
- return txt_add_char_intern(text, utxt, add, (text->flags & TXT_TABSTOSPACES) != 0);
+ return txt_add_char_intern(text, add, (text->flags & TXT_TABSTOSPACES) != 0);
}
-bool txt_add_raw_char(Text *text, TextUndoBuf *utxt, unsigned int add)
+bool txt_add_raw_char(Text *text, unsigned int add)
{
- return txt_add_char_intern(text, utxt, add, 0);
+ return txt_add_char_intern(text, add, 0);
}
-void txt_delete_selected(Text *text, TextUndoBuf *utxt)
+void txt_delete_selected(Text *text)
{
- txt_delete_sel(text, utxt);
+ txt_delete_sel(text);
txt_make_dirty(text);
}
-bool txt_replace_char(Text *text, TextUndoBuf *utxt, unsigned int add)
+bool txt_replace_char(Text *text, unsigned int add)
{
unsigned int del;
size_t del_size = 0, add_size;
@@ -2965,10 +1937,11 @@ bool txt_replace_char(Text *text, TextUndoBuf *utxt, unsigned int add)
/* If text is selected or we're at the end of the line just use txt_add_char */
if (text->curc == text->curl->len || txt_has_sel(text) || add == '\n') {
- return txt_add_char(text, utxt, add);
+ return txt_add_char(text, add);
}
del = BLI_str_utf8_as_unicode_and_size(text->curl->line + text->curc, &del_size);
+ UNUSED_VARS(del);
add_size = BLI_str_utf8_from_unicode(add, ch);
if (add_size > del_size) {
@@ -2994,16 +1967,6 @@ bool txt_replace_char(Text *text, TextUndoBuf *utxt, unsigned int add)
txt_pop_sel(text);
txt_make_dirty(text);
txt_clean_text(text);
-
- /* Should probably create a new op for this */
- if (!undoing) {
- txt_undo_add_charop(text, utxt, UNDO_INSERT_1, add);
- text->curc -= add_size;
- txt_pop_sel(text);
- txt_undo_add_charop(text, utxt, UNDO_DEL_1, del);
- text->curc += add_size;
- txt_pop_sel(text);
- }
return true;
}
@@ -3082,26 +2045,14 @@ static void txt_select_prefix(Text *text, const char *add)
*
* \note caller must handle undo.
*/
-static void txt_select_unprefix(Text *text,
- const char *remove,
- ListBase *r_line_index_mask,
- int *r_line_index_mask_len)
+static void txt_select_unprefix(Text *text, const char *remove)
{
int num = 0;
const int indentlen = strlen(remove);
bool unindented_first = false;
- int curl_span_init = 0;
-
BLI_assert(!ELEM(NULL, text->curl, text->sell));
- BLI_listbase_clear(r_line_index_mask);
- *r_line_index_mask_len = 0;
-
- if (!undoing) {
- curl_span_init = txt_get_span(text->lines.first, text->curl);
- }
-
while (true) {
bool changed = false;
if (STREQLEN(text->curl->line, remove, indentlen)) {
@@ -3112,16 +2063,6 @@ static void txt_select_unprefix(Text *text,
memmove(text->curl->line, text->curl->line + indentlen, text->curl->len + 1);
changed = true;
}
- else {
- if (!undoing) {
- /* Create list element for 0 indent line */
- struct LinkInt *idata = MEM_mallocN(sizeof(struct LinkInt), __func__);
- idata->value = curl_span_init + num;
- BLI_assert(idata->value == txt_get_span(text->lines.first, text->curl));
- BLI_addtail(r_line_index_mask, idata);
- (*r_line_index_mask_len) += 1;
- }
- }
txt_make_dirty(text);
txt_clean_text(text);
@@ -3150,7 +2091,7 @@ static void txt_select_unprefix(Text *text,
/* caller must handle undo */
}
-void txt_comment(Text *text, TextUndoBuf *utxt)
+void txt_comment(Text *text)
{
const char *prefix = "#";
@@ -3159,32 +2100,20 @@ void txt_comment(Text *text, TextUndoBuf *utxt)
}
txt_select_prefix(text, prefix);
-
- if (!undoing) {
- txt_undo_add_op(text, utxt, UNDO_COMMENT);
- }
}
-void txt_uncomment(Text *text, TextUndoBuf *utxt)
+void txt_uncomment(Text *text)
{
const char *prefix = "#";
- ListBase line_index_mask;
- int line_index_mask_len;
if (ELEM(NULL, text->curl, text->sell)) {
return;
}
- txt_select_unprefix(text, prefix, &line_index_mask, &line_index_mask_len);
-
- if (!undoing) {
- txt_undo_add_unprefix_op(text, utxt, UNDO_UNCOMMENT, &line_index_mask, line_index_mask_len);
- }
-
- BLI_freelistN(&line_index_mask);
+ txt_select_unprefix(text, prefix);
}
-void txt_indent(Text *text, TextUndoBuf *utxt)
+void txt_indent(Text *text)
{
const char *prefix = (text->flags & TXT_TABSTOSPACES) ? tab_to_spaces : "\t";
@@ -3193,32 +2122,20 @@ void txt_indent(Text *text, TextUndoBuf *utxt)
}
txt_select_prefix(text, prefix);
-
- if (!undoing) {
- txt_undo_add_op(text, utxt, UNDO_INDENT);
- }
}
-void txt_unindent(Text *text, TextUndoBuf *utxt)
+void txt_unindent(Text *text)
{
const char *prefix = (text->flags & TXT_TABSTOSPACES) ? tab_to_spaces : "\t";
- ListBase line_index_mask;
- int line_index_mask_len;
if (ELEM(NULL, text->curl, text->sell)) {
return;
}
- txt_select_unprefix(text, prefix, &line_index_mask, &line_index_mask_len);
-
- if (!undoing) {
- txt_undo_add_unprefix_op(text, utxt, UNDO_UNINDENT, &line_index_mask, line_index_mask_len);
- }
-
- BLI_freelistN(&line_index_mask);
+ txt_select_unprefix(text, prefix);
}
-void txt_move_lines(struct Text *text, TextUndoBuf *utxt, const int direction)
+void txt_move_lines(struct Text *text, const int direction)
{
TextLine *line_other;
@@ -3247,11 +2164,6 @@ void txt_move_lines(struct Text *text, TextUndoBuf *utxt, const int direction)
txt_make_dirty(text);
txt_clean_text(text);
-
- if (!undoing) {
- txt_undo_add_op(
- text, utxt, (direction == TXT_MOVE_LINE_DOWN) ? UNDO_MOVE_LINES_DOWN : UNDO_MOVE_LINES_UP);
- }
}
int txt_setcurr_tab_spaces(Text *text, int space)
diff --git a/source/blender/blenkernel/intern/tracking_stabilize.c b/source/blender/blenkernel/intern/tracking_stabilize.c
index 88b81392189..b852e8a12cd 100644
--- a/source/blender/blenkernel/intern/tracking_stabilize.c
+++ b/source/blender/blenkernel/intern/tracking_stabilize.c
@@ -672,14 +672,14 @@ static void average_marker_positions(StabContext *ctx, int framenr, float r_ref_
}
else {
/* No usable tracking data on any track on this frame.
- * Use data from neighbouring frames to extrapolate...
+ * Use data from neighboring frames to extrapolate...
*/
int next_lower = MINAFRAME;
int next_higher = MAXFRAME;
use_values_from_fcurves(ctx, true);
for (track = tracking->tracks.first; track; track = track->next) {
/* Note: we deliberately do not care if this track
- * is already initialized for stabilisation */
+ * is already initialized for stabilization. */
if (track->flag & TRACK_USE_2D_STAB) {
int startpoint = search_closest_marker_index(track, framenr);
retrieve_next_higher_usable_frame(ctx, track, startpoint, framenr, &next_higher);
diff --git a/source/blender/blenkernel/intern/undo_system.c b/source/blender/blenkernel/intern/undo_system.c
index b33884e4f0e..8ea5b47de5f 100644
--- a/source/blender/blenkernel/intern/undo_system.c
+++ b/source/blender/blenkernel/intern/undo_system.c
@@ -50,7 +50,7 @@
/** Make sure all ID's created at the point we add an undo step that uses ID's. */
#define WITH_GLOBAL_UNDO_ENSURE_UPDATED
-/** Make sure we don't apply edits ontop of a newer memfile state, see: T56163.
+/** Make sure we don't apply edits on top of a newer memfile state, see: T56163.
* \note Keep an eye on this, could solve differently. */
#define WITH_GLOBAL_UNDO_CORRECT_ORDER
@@ -120,7 +120,7 @@ static const UndoType *BKE_undosys_type_from_context(bContext *C)
/* -------------------------------------------------------------------- */
/** \name Internal Callback Wrappers
*
- * #UndoRefID is simply a way to avoid inlining name copy and lookups,
+ * #UndoRefID is simply a way to avoid in-lining name copy and lookups,
* since it's easy to forget a single case when done inline (crashing in some cases).
*
* \{ */
@@ -173,7 +173,8 @@ static bool undosys_step_encode(bContext *C, Main *bmain, UndoStack *ustack, Und
return ok;
}
-static void undosys_step_decode(bContext *C, Main *bmain, UndoStack *ustack, UndoStep *us, int dir)
+static void undosys_step_decode(
+ bContext *C, Main *bmain, UndoStack *ustack, UndoStep *us, int dir, bool is_final)
{
CLOG_INFO(&LOG, 2, "addr=%p, name='%s', type='%s'", us, us->name, us->type->name);
@@ -188,7 +189,7 @@ static void undosys_step_decode(bContext *C, Main *bmain, UndoStack *ustack, Und
else {
/* Load the previous memfile state so any ID's referenced in this
* undo step will be correctly resolved, see: T56163. */
- undosys_step_decode(C, bmain, ustack, us_iter, dir);
+ undosys_step_decode(C, bmain, ustack, us_iter, dir, false);
/* May have been freed on memfile read. */
bmain = G.main;
}
@@ -203,7 +204,7 @@ static void undosys_step_decode(bContext *C, Main *bmain, UndoStack *ustack, Und
}
UNDO_NESTED_CHECK_BEGIN;
- us->type->step_decode(C, bmain, us, dir);
+ us->type->step_decode(C, bmain, us, dir, is_final);
UNDO_NESTED_CHECK_END;
#ifdef WITH_GLOBAL_UNDO_CORRECT_ORDER
@@ -310,13 +311,20 @@ static void undosys_stack_clear_all_last(UndoStack *ustack, UndoStep *us)
}
}
-static void undosys_stack_clear_all_first(UndoStack *ustack, UndoStep *us)
+static void undosys_stack_clear_all_first(UndoStack *ustack, UndoStep *us, UndoStep *us_exclude)
{
+ if (us && us == us_exclude) {
+ us = us->prev;
+ }
+
if (us) {
bool is_not_empty = true;
UndoStep *us_iter;
do {
us_iter = ustack->steps.first;
+ if (us_iter == us_exclude) {
+ us_iter = us_iter->next;
+ }
BLI_assert(us_iter != ustack->step_active);
undosys_step_free_and_unlink(ustack, us_iter);
undosys_stack_validate(ustack, is_not_empty);
@@ -394,9 +402,7 @@ void BKE_undosys_stack_limit_steps_and_memory(UndoStack *ustack, int steps, size
CLOG_INFO(&LOG, 1, "steps=%d, memory_limit=%zu", steps, memory_limit);
UndoStep *us;
-#ifdef WITH_GLOBAL_UNDO_KEEP_ONE
UndoStep *us_exclude = NULL;
-#endif
/* keep at least two (original + other) */
size_t data_size_all = 0;
size_t us_count = 0;
@@ -426,23 +432,14 @@ void BKE_undosys_stack_limit_steps_and_memory(UndoStack *ustack, int steps, size
/* Hack, we need to keep at least one BKE_UNDOSYS_TYPE_MEMFILE. */
if (us->type != BKE_UNDOSYS_TYPE_MEMFILE) {
us_exclude = us->prev;
- while (us_exclude && us->type != BKE_UNDOSYS_TYPE_MEMFILE) {
+ while (us_exclude && us_exclude->type != BKE_UNDOSYS_TYPE_MEMFILE) {
us_exclude = us_exclude->prev;
}
- if (us_exclude) {
- BLI_remlink(&ustack->steps, us_exclude);
- }
}
#endif
/* Free from first to last, free functions may update de-duplication info
* (see #MemFileUndoStep). */
- undosys_stack_clear_all_first(ustack, us->prev);
-
-#ifdef WITH_GLOBAL_UNDO_KEEP_ONE
- if (us_exclude) {
- BLI_addhead(&ustack->steps, us_exclude);
- }
-#endif
+ undosys_stack_clear_all_first(ustack, us->prev, us_exclude);
}
}
@@ -550,7 +547,7 @@ bool BKE_undosys_step_push_with_type(UndoStack *ustack,
BLI_strncpy(us->name, name, sizeof(us->name));
}
us->type = ut;
- /* initialized, not added yet. */
+ /* Initialized, not added yet. */
if (!undosys_step_encode(C, G_MAIN, ustack, us)) {
MEM_freeN(us);
@@ -678,22 +675,36 @@ bool BKE_undosys_step_undo_with_data_ex(UndoStack *ustack,
* - skip successive steps that store the same data, eg: memfile steps.
* - or steps that include another steps data, eg: a memfile step includes text undo data.
*/
- undosys_step_decode(C, G_MAIN, ustack, us_iter, -1);
+ undosys_step_decode(C, G_MAIN, ustack, us_iter, -1, false);
+
us_iter = us_iter->prev;
}
}
- undosys_step_decode(C, G_MAIN, ustack, us, -1);
-
- ustack->step_active = us_prev;
- undosys_stack_validate(ustack, true);
+ UndoStep *us_active = us_prev;
if (use_skip) {
- if (ustack->step_active && ustack->step_active->skip) {
- CLOG_INFO(
- &LOG, 2, "undo continue with skip %p '%s', type='%s'", us, us->name, us->type->name);
- BKE_undosys_step_undo_with_data(ustack, C, ustack->step_active);
+ while (us_active->skip && us_active->prev) {
+ us_active = us_active->prev;
}
}
+
+ {
+ UndoStep *us_iter = us_prev;
+ do {
+ const bool is_final = (us_iter == us_active);
+ if (is_final == false) {
+ CLOG_INFO(&LOG,
+ 2,
+ "undo continue with skip %p '%s', type='%s'",
+ us_iter,
+ us_iter->name,
+ us_iter->type->name);
+ }
+ undosys_step_decode(C, G_MAIN, ustack, us_iter, -1, is_final);
+ ustack->step_active = us_iter;
+ } while ((us_active != us_iter) && (us_iter = us_iter->prev));
+ }
+
return true;
}
return false;
@@ -732,20 +743,34 @@ bool BKE_undosys_step_redo_with_data_ex(UndoStack *ustack,
if (ustack->step_active && ustack->step_active->next) {
UndoStep *us_iter = ustack->step_active->next;
while (us_iter != us) {
- undosys_step_decode(C, G_MAIN, ustack, us_iter, 1);
+ undosys_step_decode(C, G_MAIN, ustack, us_iter, 1, false);
us_iter = us_iter->next;
}
}
- undosys_step_decode(C, G_MAIN, ustack, us, 1);
- ustack->step_active = us_next;
+ UndoStep *us_active = us_next;
if (use_skip) {
- if (ustack->step_active && ustack->step_active->skip) {
- CLOG_INFO(
- &LOG, 2, "redo continue with skip %p '%s', type='%s'", us, us->name, us->type->name);
- BKE_undosys_step_redo_with_data(ustack, C, ustack->step_active);
+ while (us_active->skip && us_active->prev) {
+ us_active = us_active->next;
}
}
+
+ {
+ UndoStep *us_iter = us_next;
+ do {
+ const bool is_final = (us_iter == us_active);
+ if (is_final == false) {
+ CLOG_INFO(&LOG,
+ 2,
+ "redo continue with skip %p '%s', type='%s'",
+ us_iter,
+ us_iter->name,
+ us_iter->type->name);
+ }
+ undosys_step_decode(C, G_MAIN, ustack, us_iter, 1, is_final);
+ ustack->step_active = us_iter;
+ } while ((us_active != us_iter) && (us_iter = us_iter->next));
+ }
return true;
}
return false;
diff --git a/source/blender/blenkernel/intern/writeffmpeg.c b/source/blender/blenkernel/intern/writeffmpeg.c
index 345d9ce1193..f3336adda30 100644
--- a/source/blender/blenkernel/intern/writeffmpeg.c
+++ b/source/blender/blenkernel/intern/writeffmpeg.c
@@ -601,7 +601,7 @@ static AVStream *alloc_video_stream(FFMpegContext *context,
/* This calculates a fraction (DENUM_MAX / num) which approximates the scene frame rate
* (frs_sec / frs_sec_base). It uses the maximum denominator allowed by FFmpeg.
*/
- const double DENUM_MAX = (codec_id == AV_CODEC_ID_MPEG4) ? (1L << 16) - 1 : (1L << 31) - 1;
+ const double DENUM_MAX = (codec_id == AV_CODEC_ID_MPEG4) ? (1UL << 16) - 1 : (1UL << 31) - 1;
const double num = (DENUM_MAX / (double)rd->frs_sec) * rd->frs_sec_base;
c->time_base.den = (int)DENUM_MAX;
@@ -696,9 +696,9 @@ static AVStream *alloc_video_stream(FFMpegContext *context,
}
if (codec_id == AV_CODEC_ID_QTRLE) {
- if (rd->im_format.planes == R_IMF_PLANES_RGBA) {
- c->pix_fmt = AV_PIX_FMT_ARGB;
- }
+ /* Always write to ARGB. The default pixel format of QTRLE is RGB24, which uses 3 bytes per
+ * pixels, which breaks the export. */
+ c->pix_fmt = AV_PIX_FMT_ARGB;
}
if (codec_id == AV_CODEC_ID_PNG) {
diff --git a/source/blender/blenlib/BLI_math_geom.h b/source/blender/blenlib/BLI_math_geom.h
index 484d5af194d..d5485765844 100644
--- a/source/blender/blenlib/BLI_math_geom.h
+++ b/source/blender/blenlib/BLI_math_geom.h
@@ -302,6 +302,13 @@ bool isect_line_line_strict_v3(const float v1[3],
float vi[3],
float *r_lambda);
+bool isect_ray_ray_v3(const float ray_origin_a[3],
+ const float ray_direction_a[3],
+ const float ray_origin_b[3],
+ const float ray_direction_b[3],
+ float *r_lambda_a,
+ float *r_lambda_b);
+
bool isect_ray_plane_v3(const float ray_origin[3],
const float ray_direction[3],
const float plane[4],
diff --git a/source/blender/blenlib/intern/BLI_heap.c b/source/blender/blenlib/intern/BLI_heap.c
index 836b11baa85..88b7f83385c 100644
--- a/source/blender/blenlib/intern/BLI_heap.c
+++ b/source/blender/blenlib/intern/BLI_heap.c
@@ -366,7 +366,7 @@ void BLI_heap_remove(Heap *heap, HeapNode *node)
/**
* Can be used to avoid #BLI_heap_remove, #BLI_heap_insert calls,
* balancing the tree still has a performance cost,
- * but is often much less than remove/insert, difference is most noticable with large heaps.
+ * but is often much less than remove/insert, difference is most noticeable with large heaps.
*/
void BLI_heap_node_value_update(Heap *heap, HeapNode *node, float value)
{
diff --git a/source/blender/blenlib/intern/math_geom.c b/source/blender/blenlib/intern/math_geom.c
index 5dbd2a52d07..8b715ebf87b 100644
--- a/source/blender/blenlib/intern/math_geom.c
+++ b/source/blender/blenlib/intern/math_geom.c
@@ -2798,6 +2798,46 @@ bool isect_line_line_strict_v3(const float v1[3],
}
}
+/**
+ * Check if two rays are not parallel and returns a factor that indicates
+ * the distance from \a ray_origin_b to the closest point on ray-a to ray-b.
+ *
+ * \note Neither directions need to be normalized.
+ */
+bool isect_ray_ray_v3(const float ray_origin_a[3],
+ const float ray_direction_a[3],
+ const float ray_origin_b[3],
+ const float ray_direction_b[3],
+ float *r_lambda_a,
+ float *r_lambda_b)
+{
+ BLI_assert(r_lambda_a || r_lambda_b);
+ float n[3];
+ cross_v3_v3v3(n, ray_direction_b, ray_direction_a);
+ const float nlen = len_squared_v3(n);
+
+ if (UNLIKELY(nlen == 0.0f)) {
+ /* The lines are parallel. */
+ return false;
+ }
+
+ float t[3], c[3], cray[3];
+ sub_v3_v3v3(t, ray_origin_b, ray_origin_a);
+ sub_v3_v3v3(c, n, t);
+
+ if (r_lambda_a != NULL) {
+ cross_v3_v3v3(cray, c, ray_direction_a);
+ *r_lambda_a = dot_v3v3(cray, n) / nlen;
+ }
+
+ if (r_lambda_b != NULL) {
+ cross_v3_v3v3(cray, c, ray_direction_b);
+ *r_lambda_b = dot_v3v3(cray, n) / nlen;
+ }
+
+ return true;
+}
+
bool isect_aabb_aabb_v3(const float min1[3],
const float max1[3],
const float min2[3],
diff --git a/source/blender/blenlib/intern/path_util.c b/source/blender/blenlib/intern/path_util.c
index 61b773f6016..111b530a527 100644
--- a/source/blender/blenlib/intern/path_util.c
+++ b/source/blender/blenlib/intern/path_util.c
@@ -1037,7 +1037,7 @@ bool BLI_path_abs(char *path, const char *basepath)
* in this case, there is no use in trying C:/ since it
* will never exist on a unix os.
*
- * Add a / prefix and lowercase the driveletter, remove the :
+ * Add a '/' prefix and lowercase the drive-letter, remove the ':'.
* C:\foo.JPG -> /c/foo.JPG */
if (isalpha(tmp[0]) && tmp[1] == ':' && (tmp[2] == '\\' || tmp[2] == '/')) {
@@ -1552,7 +1552,7 @@ bool BLI_path_extension_glob_validate(char *ext_fnmatch)
only_wildcards = true;
}
/* Only one group in the pattern, so even if its only made of wildcard(s),
- * it is assumed vaid. */
+ * it is assumed valid. */
return false;
}
diff --git a/source/blender/blenlib/intern/storage.c b/source/blender/blenlib/intern/storage.c
index b34a9c0a44e..39af73ac175 100644
--- a/source/blender/blenlib/intern/storage.c
+++ b/source/blender/blenlib/intern/storage.c
@@ -15,12 +15,12 @@
*
* The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
* All rights reserved.
- * Reorganised mar-01 nzc
- * Some really low-level file thingies.
*/
/** \file
* \ingroup bli
+ *
+ * Some really low-level file operations.
*/
#include <sys/types.h>
@@ -303,12 +303,24 @@ void *BLI_file_read_text_as_mem(const char *filepath, size_t pad_bytes, size_t *
void *mem = NULL;
if (fp) {
- fseek(fp, 0L, SEEK_END);
+ struct stat st;
+ if (fstat(fileno(fp), &st) == -1) {
+ goto finally;
+ }
+ if (S_ISDIR(st.st_mode)) {
+ goto finally;
+ }
+ if (fseek(fp, 0L, SEEK_END) == -1) {
+ goto finally;
+ }
+ /* Don't use the 'st_size' because it may be the symlink. */
const long int filelen = ftell(fp);
if (filelen == -1) {
goto finally;
}
- fseek(fp, 0L, SEEK_SET);
+ if (fseek(fp, 0L, SEEK_SET) == -1) {
+ goto finally;
+ }
mem = MEM_mallocN(filelen + pad_bytes, __func__);
if (mem == NULL) {
@@ -344,12 +356,24 @@ void *BLI_file_read_binary_as_mem(const char *filepath, size_t pad_bytes, size_t
void *mem = NULL;
if (fp) {
- fseek(fp, 0L, SEEK_END);
+ struct stat st;
+ if (fstat(fileno(fp), &st) == -1) {
+ goto finally;
+ }
+ if (S_ISDIR(st.st_mode)) {
+ goto finally;
+ }
+ if (fseek(fp, 0L, SEEK_END) == -1) {
+ goto finally;
+ }
+ /* Don't use the 'st_size' because it may be the symlink. */
const long int filelen = ftell(fp);
if (filelen == -1) {
goto finally;
}
- fseek(fp, 0L, SEEK_SET);
+ if (fseek(fp, 0L, SEEK_SET) == -1) {
+ goto finally;
+ }
mem = MEM_mallocN(filelen + pad_bytes, __func__);
if (mem == NULL) {
diff --git a/source/blender/blenloader/intern/readfile.c b/source/blender/blenloader/intern/readfile.c
index 3c57de0a9d8..44039ad59ee 100644
--- a/source/blender/blenloader/intern/readfile.c
+++ b/source/blender/blenloader/intern/readfile.c
@@ -1712,22 +1712,26 @@ BlendThumbnail *BLO_thumbnail_from_file(const char *filepath)
/** \name Old/New Pointer Map
* \{ */
-static void *newdataadr(FileData *fd, const void *adr) /* only direct databocks */
+/* only direct databocks */
+static void *newdataadr(FileData *fd, const void *adr)
{
return oldnewmap_lookup_and_inc(fd->datamap, adr, true);
}
-static void *newdataadr_no_us(FileData *fd, const void *adr) /* only direct databocks */
+/* only direct databocks */
+static void *newdataadr_no_us(FileData *fd, const void *adr)
{
return oldnewmap_lookup_and_inc(fd->datamap, adr, false);
}
-static void *newglobadr(FileData *fd, const void *adr) /* direct data-locks with global linking */
+/* direct datablocks with global linking */
+static void *newglobadr(FileData *fd, const void *adr)
{
return oldnewmap_lookup_and_inc(fd->globmap, adr, true);
}
-static void *newimaadr(FileData *fd, const void *adr) /* used to restore image data after undo */
+/* used to restore image data after undo */
+static void *newimaadr(FileData *fd, const void *adr)
{
if (fd->imamap && adr) {
return oldnewmap_lookup_and_inc(fd->imamap, adr, true);
@@ -1735,7 +1739,8 @@ static void *newimaadr(FileData *fd, const void *adr) /* used to restore image d
return NULL;
}
-static void *newsceadr(FileData *fd, const void *adr) /* used to restore scene data after undo */
+/* used to restore scene data after undo */
+static void *newsceadr(FileData *fd, const void *adr)
{
if (fd->scenemap && adr) {
return oldnewmap_lookup_and_inc(fd->scenemap, adr, true);
@@ -1743,8 +1748,8 @@ static void *newsceadr(FileData *fd, const void *adr) /* used to restore scene d
return NULL;
}
-static void *newmclipadr(FileData *fd,
- const void *adr) /* used to restore movie clip data after undo */
+/* used to restore movie clip data after undo */
+static void *newmclipadr(FileData *fd, const void *adr)
{
if (fd->movieclipmap && adr) {
return oldnewmap_lookup_and_inc(fd->movieclipmap, adr, true);
@@ -1752,7 +1757,8 @@ static void *newmclipadr(FileData *fd,
return NULL;
}
-static void *newsoundadr(FileData *fd, const void *adr) /* used to restore sound data after undo */
+/* used to restore sound data after undo */
+static void *newsoundadr(FileData *fd, const void *adr)
{
if (fd->soundmap && adr) {
return oldnewmap_lookup_and_inc(fd->soundmap, adr, true);
@@ -1760,8 +1766,8 @@ static void *newsoundadr(FileData *fd, const void *adr) /* used to restore sound
return NULL;
}
-static void *newpackedadr(FileData *fd,
- const void *adr) /* used to restore packed data after undo */
+/* used to restore packed data after undo */
+static void *newpackedadr(FileData *fd, const void *adr)
{
if (fd->packedmap && adr) {
return oldnewmap_lookup_and_inc(fd->packedmap, adr, true);
@@ -1770,19 +1776,20 @@ static void *newpackedadr(FileData *fd,
return oldnewmap_lookup_and_inc(fd->datamap, adr, true);
}
-static void *newlibadr(FileData *fd, const void *lib, const void *adr) /* only lib data */
+/* only lib data */
+static void *newlibadr(FileData *fd, const void *lib, const void *adr)
{
return oldnewmap_liblookup(fd->libmap, adr, lib);
}
-void *blo_do_versions_newlibadr(FileData *fd, const void *lib, const void *adr) /* only lib data */
+/* only lib data */
+void *blo_do_versions_newlibadr(FileData *fd, const void *lib, const void *adr)
{
return newlibadr(fd, lib, adr);
}
-static void *newlibadr_us(FileData *fd,
- const void *lib,
- const void *adr) /* increases user number */
+/* increases user number */
+static void *newlibadr_us(FileData *fd, const void *lib, const void *adr)
{
ID *id = newlibadr(fd, lib, adr);
@@ -1791,16 +1798,14 @@ static void *newlibadr_us(FileData *fd,
return id;
}
-void *blo_do_versions_newlibadr_us(FileData *fd,
- const void *lib,
- const void *adr) /* increases user number */
+/* increases user number */
+void *blo_do_versions_newlibadr_us(FileData *fd, const void *lib, const void *adr)
{
return newlibadr_us(fd, lib, adr);
}
-static void *newlibadr_real_us(FileData *fd,
- const void *lib,
- const void *adr) /* ensures real user */
+/* ensures real user */
+static void *newlibadr_real_us(FileData *fd, const void *lib, const void *adr)
{
ID *id = newlibadr(fd, lib, adr);
@@ -4507,8 +4512,9 @@ static void direct_link_pointcache_cb(FileData *fd, void *data)
/* the cache saves non-struct data without DNA */
if (pm->data[i] && ptcache_data_struct[i][0] == '\0' && (fd->flags & FD_FLAGS_SWITCH_ENDIAN)) {
- int tot = (BKE_ptcache_data_size(i) * pm->totpoint) /
- sizeof(int); /* data_size returns bytes */
+ /* data_size returns bytes. */
+ int tot = (BKE_ptcache_data_size(i) * pm->totpoint) / sizeof(int);
+
int *poin = pm->data[i];
BLI_endian_switch_int32_array(poin, tot);
@@ -4776,8 +4782,10 @@ static void direct_link_particlesystems(FileData *fd, ListBase *particles)
if (psys->particles && psys->particles->boid) {
pa = psys->particles;
pa->boid = newdataadr(fd, pa->boid);
- pa->boid->ground =
- NULL; /* This is purely runtime data, but still can be an issue if left dangling. */
+
+ /* This is purely runtime data, but still can be an issue if left dangling. */
+ pa->boid->ground = NULL;
+
for (a = 1, pa++; a < psys->totpart; a++, pa++) {
pa->boid = (pa - 1)->boid + 1;
pa->boid->ground = NULL;
@@ -7169,8 +7177,10 @@ static void direct_link_area(FileData *fd, ScrArea *area)
BLI_listbase_clear(&area->handlers);
area->type = NULL; /* spacetype callbacks */
- area->butspacetype =
- SPACE_EMPTY; /* Should always be unset so that rna_Area_type_get works correctly */
+
+ /* Should always be unset so that rna_Area_type_get works correctly. */
+ area->butspacetype = SPACE_EMPTY;
+
area->region_active_win = -1;
area->flag &= ~AREA_FLAG_ACTIVE_TOOL_UPDATE;
@@ -7180,8 +7190,9 @@ static void direct_link_area(FileData *fd, ScrArea *area)
/* if we do not have the spacetype registered we cannot
* free it, so don't allocate any new memory for such spacetypes. */
if (!BKE_spacetype_exists(area->spacetype)) {
- area->butspacetype =
- area->spacetype; /* Hint for versioning code to replace deprecated space types. */
+ /* Hint for versioning code to replace deprecated space types. */
+ area->butspacetype = area->spacetype;
+
area->spacetype = SPACE_EMPTY;
}
@@ -9498,7 +9509,7 @@ static void lib_link_all(FileData *fd, Main *main)
* re-read all library data-blocks.
* Unfortunately, that means that we do not clear Collections' parents lists, which then get
* improperly extended in some cases by lib_link_scene() and lib_link_collection() calls above
- * (when ome local collection is parent of linked ones).
+ * (when one local collection is parent of linked ones).
* I do not really see a way to address that issue, besides brute force call below which
* invalidates and re-creates all parenting relationships between collections. Yet another
* example of why it is such a bad idea to keep that kind of double-linked relationships info
diff --git a/source/blender/blenloader/intern/versioning_280.c b/source/blender/blenloader/intern/versioning_280.c
index 4b55364f0b1..cb2b64957f0 100644
--- a/source/blender/blenloader/intern/versioning_280.c
+++ b/source/blender/blenloader/intern/versioning_280.c
@@ -1180,12 +1180,11 @@ void blo_do_versions_280(FileData *fd, Library *UNUSED(lib), Main *bmain)
/* MTexPoly now removed. */
if (DNA_struct_find(fd->filesdna, "MTexPoly")) {
- const int cd_mtexpoly = 15; /* CD_MTEXPOLY, deprecated */
for (Mesh *me = bmain->meshes.first; me; me = me->id.next) {
/* If we have UV's, so this file will have MTexPoly layers too! */
if (me->mloopuv != NULL) {
CustomData_update_typemap(&me->pdata);
- CustomData_free_layers(&me->pdata, cd_mtexpoly, me->totpoly);
+ CustomData_free_layers(&me->pdata, CD_MTEXPOLY, me->totpoly);
BKE_mesh_update_customdata_pointers(me, false);
}
}
@@ -3496,19 +3495,45 @@ void blo_do_versions_280(FileData *fd, Library *UNUSED(lib), Main *bmain)
}
}
- {
- /* Versioning code until next subversion bump goes here. */
-
+ if (!MAIN_VERSION_ATLEAST(bmain, 280, 75)) {
for (Scene *scene = bmain->scenes.first; scene; scene = scene->id.next) {
if (scene->master_collection != NULL) {
scene->master_collection->flag &= ~(COLLECTION_RESTRICT_VIEWPORT |
COLLECTION_RESTRICT_SELECT |
COLLECTION_RESTRICT_RENDER);
}
+
+ UnitSettings *unit = &scene->unit;
+ if (unit->system == USER_UNIT_NONE) {
+ unit->length_unit = (char)USER_UNIT_ADAPTIVE;
+ unit->mass_unit = (char)USER_UNIT_ADAPTIVE;
+ }
+
+ RenderData *render_data = &scene->r;
+ switch (render_data->ffcodecdata.ffmpeg_preset) {
+ case FFM_PRESET_ULTRAFAST:
+ case FFM_PRESET_SUPERFAST:
+ render_data->ffcodecdata.ffmpeg_preset = FFM_PRESET_REALTIME;
+ break;
+ case FFM_PRESET_VERYFAST:
+ case FFM_PRESET_FASTER:
+ case FFM_PRESET_FAST:
+ case FFM_PRESET_MEDIUM:
+ render_data->ffcodecdata.ffmpeg_preset = FFM_PRESET_GOOD;
+ break;
+ case FFM_PRESET_SLOW:
+ case FFM_PRESET_SLOWER:
+ case FFM_PRESET_VERYSLOW:
+ render_data->ffcodecdata.ffmpeg_preset = FFM_PRESET_BEST;
+ }
}
LISTBASE_FOREACH (bArmature *, arm, &bmain->armatures) {
arm->flag &= ~(ARM_FLAG_UNUSED_6);
}
}
+
+ {
+ /* Versioning code until next subversion bump goes here. */
+ }
}
diff --git a/source/blender/blenloader/intern/writefile.c b/source/blender/blenloader/intern/writefile.c
index 115387a697b..5954ba9cf8e 100644
--- a/source/blender/blenloader/intern/writefile.c
+++ b/source/blender/blenloader/intern/writefile.c
@@ -553,10 +553,8 @@ static void writestruct_id(
writestruct_at_address_id(wd, filecode, structname, nr, adr, adr);
}
-static void writedata(WriteData *wd,
- int filecode,
- int len,
- const void *adr) /* do not use for structs */
+/* do not use for structs */
+static void writedata(WriteData *wd, int filecode, int len, const void *adr)
{
BHead bh;
diff --git a/source/blender/bmesh/intern/bmesh_mesh_conv.c b/source/blender/bmesh/intern/bmesh_mesh_conv.c
index 7a100167b48..2000689b496 100644
--- a/source/blender/bmesh/intern/bmesh_mesh_conv.c
+++ b/source/blender/bmesh/intern/bmesh_mesh_conv.c
@@ -984,7 +984,7 @@ void BM_mesh_bm_to_me(Main *bmain, BMesh *bm, Mesh *me, const struct BMeshToMesh
/**
* A version of #BM_mesh_bm_to_me intended for getting the mesh
* to pass to the modifier stack for evaluation,
- * instad of mode switching (where we make sure all data is kept
+ * instead of mode switching (where we make sure all data is kept
* and do expensive lookups to maintain shape keys).
*
* Key differences:
diff --git a/source/blender/bmesh/operators/bmo_inset.c b/source/blender/bmesh/operators/bmo_inset.c
index 12ec4617f0a..323bb5a7748 100644
--- a/source/blender/bmesh/operators/bmo_inset.c
+++ b/source/blender/bmesh/operators/bmo_inset.c
@@ -186,7 +186,7 @@ static void bm_loop_customdata_merge(BMesh *bm,
BM_ELEM_CD_GET_VOID_P(l_a_outer, offset),
BM_ELEM_CD_GET_VOID_P(l_b_outer, offset)) == true)
- /* epsilon for comparing UV's is too big, gives noticable problems */
+ /* Epsilon for comparing UV's is too big, gives noticeable problems. */
# if 0
&&
/* check if the data ends up diverged */
diff --git a/source/blender/bmesh/tools/bmesh_bevel.c b/source/blender/bmesh/tools/bmesh_bevel.c
index c8338081443..90df3cd225e 100644
--- a/source/blender/bmesh/tools/bmesh_bevel.c
+++ b/source/blender/bmesh/tools/bmesh_bevel.c
@@ -3201,7 +3201,7 @@ static BoundVert *pipe_test(BevVert *bv)
/* check face planes: all should have normals perpendicular to epipe */
for (e = &bv->edges[0]; e != &bv->edges[bv->edgecount]; e++) {
if (e->fnext) {
- if (dot_v3v3(dir1, e->fnext->no) > BEVEL_EPSILON_BIG) {
+ if (fabsf(dot_v3v3(dir1, e->fnext->no)) > BEVEL_EPSILON_BIG) {
return NULL;
}
}
diff --git a/source/blender/bmesh/tools/bmesh_intersect.c b/source/blender/bmesh/tools/bmesh_intersect.c
index 66845b6f33c..9a3cade85db 100644
--- a/source/blender/bmesh/tools/bmesh_intersect.c
+++ b/source/blender/bmesh/tools/bmesh_intersect.c
@@ -896,7 +896,7 @@ static int isect_bvhtree_point_v3(BVHTree *tree, const float **looptris, const f
float dir[3] = {1.0f, 0.0f, 0.0f};
/* Need to initialize hit even tho it's not used.
- * This is to make it so kdotree believes we didn't intersect anything and
+ * This is to make it so kd-tree believes we didn't intersect anything and
* keeps calling the intersect callback.
*/
hit.index = -1;
diff --git a/source/blender/collada/ArmatureImporter.cpp b/source/blender/collada/ArmatureImporter.cpp
index e79a97c890f..15c34226cf6 100644
--- a/source/blender/collada/ArmatureImporter.cpp
+++ b/source/blender/collada/ArmatureImporter.cpp
@@ -791,8 +791,8 @@ void ArmatureImporter::make_armatures(bContext *C, std::vector<Object *> &object
std::vector<Object *> ob_arms;
std::map<COLLADAFW::UniqueId, SkinInfo>::iterator it;
- leaf_bone_length =
- FLT_MAX; /*TODO: Make this work for more than one armature in the import file*/
+ /* TODO: Make this work for more than one armature in the import file. */
+ leaf_bone_length = FLT_MAX;
for (it = skin_by_data_uid.begin(); it != skin_by_data_uid.end(); it++) {
diff --git a/source/blender/collada/BCAnimationSampler.cpp b/source/blender/collada/BCAnimationSampler.cpp
index 2e89ea0af4d..49d87f92fda 100644
--- a/source/blender/collada/BCAnimationSampler.cpp
+++ b/source/blender/collada/BCAnimationSampler.cpp
@@ -334,15 +334,16 @@ bool BCAnimationSampler::get_object_samples(BCMatrixSampleMap &samples, Object *
#if 0
/**
- * Add sampled values to FCurve
- * If no FCurve exists, create a temporary FCurve;
- * Note: The temporary FCurve will later be removed when the
- * BCAnimationSampler is removed (by its destructor)
+ * Add sampled values to #FCurve
+ * If no #FCurve exists, create a temporary #FCurve;
+ * \note The temporary #FCurve will later be removed when the
+ * #BCAnimationSampler is removed (by its destructor).
*
- * curve: The curve to whioch the data is added
- * matrices: The set of matrix values from where the data is taken
- * animation_type BC_ANIMATION_EXPORT_SAMPLES: Use all matrix data
- * animation_type BC_ANIMATION_EXPORT_KEYS: Only take data from matrices for keyframes
+ * \param curve: The curve to which the data is added.
+ * \param matrices: The set of matrix values from where the data is taken.
+ * \param animation_type:
+ * - #BC_ANIMATION_EXPORT_SAMPLES: Use all matrix data.
+ * - #BC_ANIMATION_EXPORT_KEYS: Only take data from matrices for keyframes.
*/
void BCAnimationSampler::add_value_set(BCAnimationCurve &curve,
BCFrameSampleMap &samples,
diff --git a/source/blender/collada/DocumentImporter.cpp b/source/blender/collada/DocumentImporter.cpp
index 06f6682f401..eabd9469582 100644
--- a/source/blender/collada/DocumentImporter.cpp
+++ b/source/blender/collada/DocumentImporter.cpp
@@ -804,7 +804,10 @@ void DocumentImporter::write_profile_COMMON(COLLADAFW::EffectCommon *ef, Materia
matNode.set_alpha(ef->getOpaqueMode(), ef->getTransparent(), ef->getTransparency());
/* following mapping still needs to be verified */
+#if 0
+ // needs rework to be done for 2.81
matNode.set_shininess(ef->getShininess());
+#endif
matNode.set_reflectivity(ef->getReflectivity());
/* not supported by principled BSDF */
diff --git a/source/blender/collada/EffectExporter.cpp b/source/blender/collada/EffectExporter.cpp
index 394c79bb988..80f84738f6e 100644
--- a/source/blender/collada/EffectExporter.cpp
+++ b/source/blender/collada/EffectExporter.cpp
@@ -102,7 +102,12 @@ void EffectsExporter::set_shader_type(COLLADASW::EffectProfile &ep, Material *ma
void EffectsExporter::set_transparency(COLLADASW::EffectProfile &ep, Material *ma)
{
double alpha = bc_get_alpha(ma);
- ep.setTransparency(alpha, false, "alpha");
+ if (alpha < 1) {
+ // workaround use <transparent> to avoid wrong handling of <transparency> by other tools
+ COLLADASW::ColorOrTexture cot = bc_get_cot(0, 0, 0, alpha);
+ ep.setTransparent(cot, false, "alpha");
+ ep.setOpaque(COLLADASW::EffectProfile::A_ONE);
+ }
}
void EffectsExporter::set_diffuse_color(COLLADASW::EffectProfile &ep, Material *ma)
@@ -134,7 +139,9 @@ void EffectsExporter::set_reflective(COLLADASW::EffectProfile &ep, Material *ma)
void EffectsExporter::set_reflectivity(COLLADASW::EffectProfile &ep, Material *ma)
{
double reflectivity = bc_get_reflectivity(ma);
- ep.setReflectivity(reflectivity, false, "specular");
+ if (reflectivity > 0.0) {
+ ep.setReflectivity(reflectivity, false, "specular");
+ }
}
void EffectsExporter::set_emission(COLLADASW::EffectProfile &ep, Material *ma)
@@ -208,21 +215,20 @@ void EffectsExporter::operator()(Material *ma, Object *ob)
COLLADASW::EffectProfile ep(mSW);
ep.setProfileType(COLLADASW::EffectProfile::COMMON);
ep.openProfile();
- set_shader_type(ep, ma);
+ set_shader_type(ep, ma); // creates a Lambert Shader for now
COLLADASW::ColorOrTexture cot;
set_diffuse_color(ep, ma);
set_emission(ep, ma);
set_ior(ep, ma);
- set_shininess(ep, ma);
set_reflectivity(ep, ma);
set_transparency(ep, ma);
- /* TODO: from where to get ambient, specular and reflective? */
+ /* TODO: */
+ // set_shininess(ep, ma); shininess not supported for lambert
// set_ambient(ep, ma);
// set_specular(ep, ma);
- // set_reflective(ep, ma);
get_images(ma, material_image_map);
std::string active_uv(getActiveUVLayerName(ob));
diff --git a/source/blender/collada/Materials.cpp b/source/blender/collada/Materials.cpp
index aa35b71b9db..e1d5b2e9d5c 100644
--- a/source/blender/collada/Materials.cpp
+++ b/source/blender/collada/Materials.cpp
@@ -131,18 +131,24 @@ void MaterialNode::add_link(bNode *from_node, int from_index, bNode *to_node, in
void MaterialNode::set_reflectivity(COLLADAFW::FloatOrParam &val)
{
float reflectivity = val.getFloatValue();
- bNodeSocket *socket = nodeFindSocket(shader_node, SOCK_IN, "Metallic");
- ((bNodeSocketValueFloat *)socket->default_value)->value = reflectivity;
-
- material->metallic = reflectivity;
+ if (reflectivity >= 0) {
+ bNodeSocket *socket = nodeFindSocket(shader_node, SOCK_IN, "Metallic");
+ ((bNodeSocketValueFloat *)socket->default_value)->value = reflectivity;
+ material->metallic = reflectivity;
+ }
}
+#if 0
+// needs rework to be done for 2.81
void MaterialNode::set_shininess(COLLADAFW::FloatOrParam &val)
{
float roughness = val.getFloatValue();
- bNodeSocket *socket = nodeFindSocket(shader_node, SOCK_IN, "Roughness");
- ((bNodeSocketValueFloat *)socket->default_value)->value = roughness;
+ if (roughness >= 0) {
+ bNodeSocket *socket = nodeFindSocket(shader_node, SOCK_IN, "Roughness");
+ ((bNodeSocketValueFloat *)socket->default_value)->value = roughness;
+ }
}
+#endif
void MaterialNode::set_ior(COLLADAFW::FloatOrParam &val)
{
@@ -162,13 +168,37 @@ void MaterialNode::set_alpha(COLLADAFW::EffectCommon::OpaqueMode mode,
COLLADAFW::ColorOrTexture &cot,
COLLADAFW::FloatOrParam &val)
{
+ /* Handling the alpha value according to the Collada 1.4 reference guide
+ * see page 7-5 Determining Transparency (Opacity)
+ */
+
if (effect == nullptr) {
return;
}
if (cot.isColor() || !cot.isValid()) {
- COLLADAFW::Color col = (cot.isValid()) ? cot.getColor() : COLLADAFW::Color(1, 1, 1, 1);
- float alpha = val.getFloatValue() * col.getAlpha(); // Assuming A_ONE opaque mode
+ // transparent_cot is either a color or not defined
+
+ float transparent_alpha;
+ if (cot.isValid()) {
+ COLLADAFW::Color col = cot.getColor();
+ transparent_alpha = col.getAlpha();
+ }
+ else {
+ // no transparent color defined
+ transparent_alpha = 1;
+ }
+
+ float transparency_alpha = val.getFloatValue();
+ if (transparency_alpha < 0) {
+ // transparency is not defined
+ transparency_alpha = 1; // set to opaque
+ }
+
+ float alpha = transparent_alpha * transparency_alpha;
+ if (mode == COLLADASW::EffectProfile::RGB_ZERO) {
+ alpha = 1 - alpha;
+ }
bNodeSocket *socket = nodeFindSocket(shader_node, SOCK_IN, "Alpha");
((bNodeSocketValueFloat *)socket->default_value)->value = alpha;
@@ -176,7 +206,6 @@ void MaterialNode::set_alpha(COLLADAFW::EffectCommon::OpaqueMode mode,
else if (cot.isTexture()) {
int locy = -300 * (node_map.size() - 2);
add_texture_node(cot, -300, locy, "Alpha");
- // TODO: Connect node
}
}
diff --git a/source/blender/depsgraph/DEG_depsgraph_build.h b/source/blender/depsgraph/DEG_depsgraph_build.h
index ee2d4b7be54..18e06410adf 100644
--- a/source/blender/depsgraph/DEG_depsgraph_build.h
+++ b/source/blender/depsgraph/DEG_depsgraph_build.h
@@ -110,6 +110,9 @@ typedef enum eDepsSceneComponentType {
} eDepsSceneComponentType;
typedef enum eDepsObjectComponentType {
+ /* Used in query API, to denote which component caller is interested in. */
+ DEG_OB_COMP_ANY,
+
/* Parameters Component - Default when nothing else fits
* (i.e. just SDNA property setting). */
DEG_OB_COMP_PARAMETERS,
diff --git a/source/blender/depsgraph/DEG_depsgraph_query.h b/source/blender/depsgraph/DEG_depsgraph_query.h
index 4148529d3f8..e3381e79e9c 100644
--- a/source/blender/depsgraph/DEG_depsgraph_query.h
+++ b/source/blender/depsgraph/DEG_depsgraph_query.h
@@ -219,6 +219,9 @@ void DEG_iterator_ids_end(struct BLI_Iterator *iter);
/* ************************ DEG traversal ********************* */
typedef void (*DEGForeachIDCallback)(ID *id, void *user_data);
+typedef void (*DEGForeachIDComponentCallback)(ID *id,
+ eDepsObjectComponentType component,
+ void *user_data);
/* NOTE: Modifies runtime flags in depsgraph nodes, so can not be used in
* parallel. Keep an eye on that!
@@ -232,6 +235,14 @@ void DEG_foreach_dependent_ID(const Depsgraph *depsgraph,
DEGForeachIDCallback callback,
void *user_data);
+/* Starts traversal from given component of the given ID, invokes callback for every other
+ * component which is directly on indirectly dependent on the source one. */
+void DEG_foreach_dependent_ID_component(const Depsgraph *depsgraph,
+ const ID *id,
+ eDepsObjectComponentType source_component_type,
+ DEGForeachIDComponentCallback callback,
+ void *user_data);
+
void DEG_foreach_ID(const Depsgraph *depsgraph, DEGForeachIDCallback callback, void *user_data);
#ifdef __cplusplus
diff --git a/source/blender/depsgraph/intern/builder/deg_builder_nodes.cc b/source/blender/depsgraph/intern/builder/deg_builder_nodes.cc
index e65dd3b4560..fa6d7bc6028 100644
--- a/source/blender/depsgraph/intern/builder/deg_builder_nodes.cc
+++ b/source/blender/depsgraph/intern/builder/deg_builder_nodes.cc
@@ -595,7 +595,7 @@ void DepsgraphNodeBuilder::build_object(int base_index,
}
/* Object data. */
build_object_data(object, is_visible);
- /* Paramaters, used by both drivers/animation and also to inform dependency
+ /* Parameters, used by both drivers/animation and also to inform dependency
* from object's data. */
build_parameters(&object->id);
/* Build animation data,
@@ -697,6 +697,12 @@ void DepsgraphNodeBuilder::build_object_data(Object *object, bool is_object_visi
break;
}
}
+ /* Materials. */
+ Material ***materials_ptr = give_matarar(object);
+ if (materials_ptr != NULL) {
+ short *num_materials_ptr = give_totcolp(object);
+ build_materials(*materials_ptr, *num_materials_ptr);
+ }
}
void DepsgraphNodeBuilder::build_object_data_camera(Object *object)
@@ -753,7 +759,7 @@ void DepsgraphNodeBuilder::build_object_transform(Object *object)
NodeType::TRANSFORM,
OperationCode::TRANSFORM_EVAL,
function_bind(BKE_object_eval_uber_transform, _1, ob_cow));
- /* Operation to take of rigid body simulation. soft bodies and other firends
+ /* Operation to take of rigid body simulation. soft bodies and other friends
* in the context of point cache invalidation. */
add_operation_node(&object->id, NodeType::TRANSFORM, OperationCode::TRANSFORM_SIMULATION_INIT);
/* Object transform is done. */
@@ -1195,18 +1201,16 @@ void DepsgraphNodeBuilder::build_object_data_geometry(Object *object, bool is_ob
function_bind(BKE_object_eval_uber_data, _1, scene_cow, object_cow));
op_node->set_as_exit();
/* Materials. */
- if (object->totcol != 0) {
- for (int a = 1; a <= object->totcol; a++) {
- Material *ma = give_current_material(object, a);
- if (ma != NULL) {
- build_material(ma);
- }
- }
- }
+ build_materials(object->mat, object->totcol);
/* Point caches. */
build_object_pointcache(object);
/* Geometry. */
build_object_data_geometry_datablock((ID *)object->data, is_object_visible);
+ /* Batch cache. */
+ add_operation_node(&object->id,
+ NodeType::BATCH_CACHE,
+ OperationCode::GEOMETRY_SELECT_UPDATE,
+ function_bind(BKE_object_select_update, _1, object_cow));
}
void DepsgraphNodeBuilder::build_object_data_geometry_datablock(ID *obdata, bool is_object_visible)
@@ -1429,6 +1433,16 @@ void DepsgraphNodeBuilder::build_material(Material *material)
build_nodetree(material->nodetree);
}
+void DepsgraphNodeBuilder::build_materials(Material **materials, int num_materials)
+{
+ for (int i = 0; i < num_materials; ++i) {
+ if (materials[i] == NULL) {
+ continue;
+ }
+ build_material(materials[i]);
+ }
+}
+
/* Recursively build graph for texture */
void DepsgraphNodeBuilder::build_texture(Tex *texture)
{
@@ -1514,6 +1528,19 @@ void DepsgraphNodeBuilder::build_mask(Mask *mask)
NodeType::PARAMETERS,
OperationCode::MASK_EVAL,
function_bind(BKE_mask_eval_update, _1, mask_cow));
+ /* Build parents. */
+ LISTBASE_FOREACH (MaskLayer *, mask_layer, &mask->masklayers) {
+ LISTBASE_FOREACH (MaskSpline *, spline, &mask_layer->splines) {
+ for (int i = 0; i < spline->tot_point; i++) {
+ MaskSplinePoint *point = &spline->points[i];
+ MaskParent *parent = &point->parent;
+ if (parent == NULL || parent->id == NULL) {
+ continue;
+ }
+ build_id(parent->id);
+ }
+ }
+ }
}
void DepsgraphNodeBuilder::build_movieclip(MovieClip *clip)
diff --git a/source/blender/depsgraph/intern/builder/deg_builder_nodes.h b/source/blender/depsgraph/intern/builder/deg_builder_nodes.h
index 9983b346355..de9f0e4d6cd 100644
--- a/source/blender/depsgraph/intern/builder/deg_builder_nodes.h
+++ b/source/blender/depsgraph/intern/builder/deg_builder_nodes.h
@@ -202,6 +202,7 @@ class DepsgraphNodeBuilder : public DepsgraphBuilder {
void build_light(Light *lamp);
void build_nodetree(bNodeTree *ntree);
void build_material(Material *ma);
+ void build_materials(Material **materials, int num_materials);
void build_texture(Tex *tex);
void build_image(Image *image);
void build_world(World *world);
diff --git a/source/blender/depsgraph/intern/builder/deg_builder_nodes_scene.cc b/source/blender/depsgraph/intern/builder/deg_builder_nodes_scene.cc
index 3486d2c92ae..777512acf89 100644
--- a/source/blender/depsgraph/intern/builder/deg_builder_nodes_scene.cc
+++ b/source/blender/depsgraph/intern/builder/deg_builder_nodes_scene.cc
@@ -56,8 +56,8 @@ void DepsgraphNodeBuilder::build_scene_parameters(Scene *scene)
if (built_map_.checkIsBuiltAndTag(scene, BuilderMap::TAG_PARAMETERS)) {
return;
}
+ build_parameters(&scene->id);
add_operation_node(&scene->id, NodeType::PARAMETERS, OperationCode::SCENE_EVAL);
- add_operation_node(&scene->id, NodeType::PARAMETERS, OperationCode::PARAMETERS_EVAL);
/* NOTE: This is a bit overkill and can potentially pull a bit too much into the graph, but:
*
* - We definitely need an ID node for the scene's compositor, otherwise re-mapping will no
diff --git a/source/blender/depsgraph/intern/builder/deg_builder_relations.cc b/source/blender/depsgraph/intern/builder/deg_builder_relations.cc
index c7f6116e81d..86cbb330170 100644
--- a/source/blender/depsgraph/intern/builder/deg_builder_relations.cc
+++ b/source/blender/depsgraph/intern/builder/deg_builder_relations.cc
@@ -200,6 +200,11 @@ static OperationCode bone_target_opcode(ID *target,
return OperationCode::BONE_DONE;
}
+static bool object_have_geometry_component(const Object *object)
+{
+ return ELEM(object->type, OB_MESH, OB_CURVE, OB_FONT, OB_SURF, OB_MBALL, OB_LATTICE, OB_GPENCIL);
+}
+
/* **** General purpose functions **** */
DepsgraphRelationBuilder::DepsgraphRelationBuilder(Main *bmain,
@@ -374,6 +379,14 @@ void DepsgraphRelationBuilder::add_particle_forcefield_relations(const Operation
{
ListBase *relations = build_effector_relations(graph_, eff->group);
+ /* Make sure physics effects like wind are properly re-evaluating the modifier stack. */
+ if (!BLI_listbase_is_empty(relations)) {
+ TimeSourceKey time_src_key;
+ ComponentKey geometry_key(&object->id, NodeType::GEOMETRY);
+ add_relation(
+ time_src_key, geometry_key, "Effector Time -> Particle", RELATION_CHECK_BEFORE_ADD);
+ }
+
LISTBASE_FOREACH (EffectorRelation *, relation, relations) {
if (relation->ob != object) {
/* Relation to forcefield object, optionally including geometry. */
@@ -746,6 +759,12 @@ void DepsgraphRelationBuilder::build_object_data(Object *object)
add_relation(key_key, geometry_key, "Shapekeys");
build_nested_shapekey(&object->id, key);
}
+ /* Materials. */
+ Material ***materials_ptr = give_matarar(object);
+ if (materials_ptr != NULL) {
+ short *num_materials_ptr = give_totcolp(object);
+ build_materials(*materials_ptr, *num_materials_ptr);
+ }
}
void DepsgraphRelationBuilder::build_object_data_camera(Object *object)
@@ -1929,14 +1948,7 @@ void DepsgraphRelationBuilder::build_object_data_geometry(Object *object)
}
}
/* Materials. */
- if (object->totcol) {
- for (int a = 1; a <= object->totcol; a++) {
- Material *ma = give_current_material(object, a);
- if (ma != NULL) {
- build_material(ma);
- }
- }
- }
+ build_materials(object->mat, object->totcol);
/* Geometry collision. */
if (ELEM(object->type, OB_MESH, OB_CURVE, OB_LATTICE)) {
// add geometry collider relations
@@ -1988,10 +2000,18 @@ void DepsgraphRelationBuilder::build_object_data_geometry(Object *object)
}
}
/* Syncronization back to original object. */
- ComponentKey final_geometry_jey(&object->id, NodeType::GEOMETRY);
+ ComponentKey final_geometry_key(&object->id, NodeType::GEOMETRY);
OperationKey synchronize_key(
&object->id, NodeType::SYNCHRONIZATION, OperationCode::SYNCHRONIZE_TO_ORIGINAL);
- add_relation(final_geometry_jey, synchronize_key, "Synchronize to Original");
+ add_relation(final_geometry_key, synchronize_key, "Synchronize to Original");
+ /* Batch cache. */
+ OperationKey object_data_select_key(
+ obdata, NodeType::BATCH_CACHE, OperationCode::GEOMETRY_SELECT_UPDATE);
+ OperationKey object_select_key(
+ &object->id, NodeType::BATCH_CACHE, OperationCode::GEOMETRY_SELECT_UPDATE);
+ add_relation(object_data_select_key, object_select_key, "Data Selection -> Object Selection");
+ add_relation(
+ geom_key, object_select_key, "Object Geometry -> Select Update", RELATION_FLAG_NO_FLUSH);
}
void DepsgraphRelationBuilder::build_object_data_geometry_datablock(ID *obdata)
@@ -2149,9 +2169,11 @@ void DepsgraphRelationBuilder::build_nodetree(bNodeTree *ntree)
else if (id_type == ID_OB) {
build_object(NULL, (Object *)id);
ComponentKey object_transform_key(id, NodeType::TRANSFORM);
- ComponentKey object_geometry_key(id, NodeType::GEOMETRY);
add_relation(object_transform_key, shading_key, "Object Transform -> Node");
- add_relation(object_geometry_key, shading_key, "Object Geometry -> Node");
+ if (object_have_geometry_component(reinterpret_cast<Object *>(id))) {
+ ComponentKey object_geometry_key(id, NodeType::GEOMETRY);
+ add_relation(object_geometry_key, shading_key, "Object Geometry -> Node");
+ }
}
else if (id_type == ID_SCE) {
Scene *node_scene = (Scene *)id;
@@ -2221,6 +2243,16 @@ void DepsgraphRelationBuilder::build_material(Material *material)
}
}
+void DepsgraphRelationBuilder::build_materials(Material **materials, int num_materials)
+{
+ for (int i = 0; i < num_materials; ++i) {
+ if (materials[i] == NULL) {
+ continue;
+ }
+ build_material(materials[i]);
+ }
+}
+
/* Recursively build graph for texture */
void DepsgraphRelationBuilder::build_texture(Tex *texture)
{
@@ -2305,6 +2337,24 @@ void DepsgraphRelationBuilder::build_mask(Mask *mask)
/* Final mask evaluation. */
OperationKey mask_eval_key(mask_id, NodeType::PARAMETERS, OperationCode::MASK_EVAL);
add_relation(mask_animation_key, mask_eval_key, "Mask Animation -> Mask Eval");
+ /* Build parents. */
+ LISTBASE_FOREACH (MaskLayer *, mask_layer, &mask->masklayers) {
+ LISTBASE_FOREACH (MaskSpline *, spline, &mask_layer->splines) {
+ for (int i = 0; i < spline->tot_point; i++) {
+ MaskSplinePoint *point = &spline->points[i];
+ MaskParent *parent = &point->parent;
+ if (parent == NULL || parent->id == NULL) {
+ continue;
+ }
+ build_id(parent->id);
+ if (parent->id_type == ID_MC) {
+ OperationKey movieclip_eval_key(
+ parent->id, NodeType::PARAMETERS, OperationCode::MOVIECLIP_EVAL);
+ add_relation(movieclip_eval_key, mask_eval_key, "Movie Clip -> Mask Eval");
+ }
+ }
+ }
+ }
}
void DepsgraphRelationBuilder::build_movieclip(MovieClip *clip)
diff --git a/source/blender/depsgraph/intern/builder/deg_builder_relations.h b/source/blender/depsgraph/intern/builder/deg_builder_relations.h
index cfed5a73a49..0e15818622f 100644
--- a/source/blender/depsgraph/intern/builder/deg_builder_relations.h
+++ b/source/blender/depsgraph/intern/builder/deg_builder_relations.h
@@ -186,7 +186,7 @@ class DepsgraphRelationBuilder : public DepsgraphBuilder {
const char *description,
int flags = 0);
- /* Adds relation from proper transformation opertation to the modifier.
+ /* Adds relation from proper transformation operation to the modifier.
* Takes care of checking for possible physics solvers modifying position
* of this object. */
void add_modifier_to_transform_relation(const DepsNodeHandle *handle, const char *description);
@@ -264,6 +264,7 @@ class DepsgraphRelationBuilder : public DepsgraphBuilder {
void build_light(Light *lamp);
void build_nodetree(bNodeTree *ntree);
void build_material(Material *ma);
+ void build_materials(Material **materials, int num_materials);
void build_texture(Tex *tex);
void build_image(Image *image);
void build_gpencil(bGPdata *gpd);
diff --git a/source/blender/depsgraph/intern/builder/deg_builder_relations_scene.cc b/source/blender/depsgraph/intern/builder/deg_builder_relations_scene.cc
index daaf90011c5..4e0c2cbba0c 100644
--- a/source/blender/depsgraph/intern/builder/deg_builder_relations_scene.cc
+++ b/source/blender/depsgraph/intern/builder/deg_builder_relations_scene.cc
@@ -52,8 +52,9 @@ void DepsgraphRelationBuilder::build_scene_parameters(Scene *scene)
if (built_map_.checkIsBuiltAndTag(scene, BuilderMap::TAG_PARAMETERS)) {
return;
}
+ build_parameters(&scene->id);
OperationKey parameters_eval_key(
- &scene->id, NodeType::PARAMETERS, OperationCode::PARAMETERS_EVAL);
+ &scene->id, NodeType::PARAMETERS, OperationCode::PARAMETERS_EXIT);
OperationKey scene_eval_key(&scene->id, NodeType::PARAMETERS, OperationCode::SCENE_EVAL);
add_relation(parameters_eval_key, scene_eval_key, "Parameters -> Scene Eval");
}
diff --git a/source/blender/depsgraph/intern/builder/deg_builder_rna.cc b/source/blender/depsgraph/intern/builder/deg_builder_rna.cc
index a8d357cd5bd..5bb3ebf40c4 100644
--- a/source/blender/depsgraph/intern/builder/deg_builder_rna.cc
+++ b/source/blender/depsgraph/intern/builder/deg_builder_rna.cc
@@ -314,6 +314,10 @@ RNANodeIdentifier RNANodeQuery::construct_node_identifier(const PointerRNA *ptr,
node_identifier.type = NodeType::OBJECT_FROM_LAYER;
return node_identifier;
}
+ else if (STREQ(prop_identifier, "dimensions")) {
+ node_identifier.type = NodeType::GEOMETRY;
+ return node_identifier;
+ }
}
}
else if (ptr->type == &RNA_ShapeKey) {
diff --git a/source/blender/depsgraph/intern/builder/deg_builder_rna.h b/source/blender/depsgraph/intern/builder/deg_builder_rna.h
index 26d7963e0a8..8a79d9abef9 100644
--- a/source/blender/depsgraph/intern/builder/deg_builder_rna.h
+++ b/source/blender/depsgraph/intern/builder/deg_builder_rna.h
@@ -85,7 +85,7 @@ class RNANodeQuery {
/* Indexed by an ID, returns RNANodeQueryIDData associated with that ID. */
GHash *id_data_map_;
- /* Construct identifier of the node which correspods given configuration
+ /* Construct identifier of the node which corresponds given configuration
* of RNA property. */
RNANodeIdentifier construct_node_identifier(const PointerRNA *ptr,
const PropertyRNA *prop,
diff --git a/source/blender/depsgraph/intern/depsgraph_build.cc b/source/blender/depsgraph/intern/depsgraph_build.cc
index 279c5e7839a..dd2d7f70ed5 100644
--- a/source/blender/depsgraph/intern/depsgraph_build.cc
+++ b/source/blender/depsgraph/intern/depsgraph_build.cc
@@ -77,31 +77,6 @@ static DEG::NodeType deg_build_scene_component_type(eDepsSceneComponentType comp
return DEG::NodeType::UNDEFINED;
}
-static DEG::NodeType deg_build_object_component_type(eDepsObjectComponentType component)
-{
- switch (component) {
- case DEG_OB_COMP_PARAMETERS:
- return DEG::NodeType::PARAMETERS;
- case DEG_OB_COMP_PROXY:
- return DEG::NodeType::PROXY;
- case DEG_OB_COMP_ANIMATION:
- return DEG::NodeType::ANIMATION;
- case DEG_OB_COMP_TRANSFORM:
- return DEG::NodeType::TRANSFORM;
- case DEG_OB_COMP_GEOMETRY:
- return DEG::NodeType::GEOMETRY;
- case DEG_OB_COMP_EVAL_POSE:
- return DEG::NodeType::EVAL_POSE;
- case DEG_OB_COMP_BONE:
- return DEG::NodeType::BONE;
- case DEG_OB_COMP_SHADING:
- return DEG::NodeType::SHADING;
- case DEG_OB_COMP_CACHE:
- return DEG::NodeType::CACHE;
- }
- return DEG::NodeType::UNDEFINED;
-}
-
static DEG::DepsNodeHandle *get_node_handle(DepsNodeHandle *node_handle)
{
return reinterpret_cast<DEG::DepsNodeHandle *>(node_handle);
@@ -123,7 +98,7 @@ void DEG_add_object_relation(DepsNodeHandle *node_handle,
eDepsObjectComponentType component,
const char *description)
{
- DEG::NodeType type = deg_build_object_component_type(component);
+ DEG::NodeType type = DEG::nodeTypeFromObjectComponent(component);
DEG::ComponentKey comp_key(&object->id, type);
DEG::DepsNodeHandle *deg_node_handle = get_node_handle(node_handle);
deg_node_handle->builder->add_node_handle_relation(comp_key, deg_node_handle, description);
@@ -134,7 +109,7 @@ void DEG_add_object_cache_relation(DepsNodeHandle *node_handle,
eDepsObjectComponentType component,
const char *description)
{
- DEG::NodeType type = deg_build_object_component_type(component);
+ DEG::NodeType type = DEG::nodeTypeFromObjectComponent(component);
DEG::ComponentKey comp_key(&cache_file->id, type);
DEG::DepsNodeHandle *deg_node_handle = get_node_handle(node_handle);
deg_node_handle->builder->add_node_handle_relation(comp_key, deg_node_handle, description);
@@ -146,7 +121,7 @@ void DEG_add_bone_relation(DepsNodeHandle *node_handle,
eDepsObjectComponentType component,
const char *description)
{
- DEG::NodeType type = deg_build_object_component_type(component);
+ DEG::NodeType type = DEG::nodeTypeFromObjectComponent(component);
DEG::ComponentKey comp_key(&object->id, type, bone_name);
DEG::DepsNodeHandle *deg_node_handle = get_node_handle(node_handle);
deg_node_handle->builder->add_node_handle_relation(comp_key, deg_node_handle, description);
@@ -157,7 +132,7 @@ void DEG_add_object_pointcache_relation(struct DepsNodeHandle *node_handle,
eDepsObjectComponentType component,
const char *description)
{
- DEG::NodeType type = deg_build_object_component_type(component);
+ DEG::NodeType type = DEG::nodeTypeFromObjectComponent(component);
DEG::ComponentKey comp_key(&object->id, type);
DEG::DepsNodeHandle *deg_node_handle = get_node_handle(node_handle);
DEG::DepsgraphRelationBuilder *relation_builder = deg_node_handle->builder;
diff --git a/source/blender/depsgraph/intern/depsgraph_query.cc b/source/blender/depsgraph/intern/depsgraph_query.cc
index f821af8cdc7..23f2bf4194f 100644
--- a/source/blender/depsgraph/intern/depsgraph_query.cc
+++ b/source/blender/depsgraph/intern/depsgraph_query.cc
@@ -289,7 +289,7 @@ bool DEG_is_original_id(ID *id)
* Localization is usually happening from evaluated data-block, 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. */
+ * NOTE: We consider 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;
diff --git a/source/blender/depsgraph/intern/depsgraph_query_foreach.cc b/source/blender/depsgraph/intern/depsgraph_query_foreach.cc
index 717793d60f1..33cb1ba7416 100644
--- a/source/blender/depsgraph/intern/depsgraph_query_foreach.cc
+++ b/source/blender/depsgraph/intern/depsgraph_query_foreach.cc
@@ -48,25 +48,30 @@ extern "C" {
/* ************************ DEG TRAVERSAL ********************* */
namespace DEG {
+namespace {
typedef std::deque<OperationNode *> TraversalQueue;
enum {
DEG_NODE_VISITED = (1 << 0),
};
-static void deg_foreach_clear_flags(const Depsgraph *graph)
+typedef void (*DEGForeachOperation)(OperationNode *op_node, void *user_data);
+
+void deg_foreach_clear_flags(const Depsgraph *graph)
{
for (OperationNode *op_node : graph->operations) {
op_node->scheduled = false;
+ op_node->owner->custom_flags = 0;
}
for (IDNode *id_node : graph->id_nodes) {
id_node->custom_flags = 0;
}
}
-static void deg_foreach_dependent_ID(const Depsgraph *graph,
+void deg_foreach_dependent_operation(const Depsgraph *graph,
const ID *id,
- DEGForeachIDCallback callback,
+ eDepsObjectComponentType source_component_type,
+ DEGForeachOperation callback,
void *user_data)
{
/* Start with getting ID node from the graph. */
@@ -81,9 +86,14 @@ static void deg_foreach_dependent_ID(const Depsgraph *graph,
/* Start with scheduling all operations from ID node. */
TraversalQueue queue;
GHASH_FOREACH_BEGIN (ComponentNode *, comp_node, target_id_node->components) {
+ if (source_component_type != DEG_OB_COMP_ANY &&
+ nodeTypeToObjectComponent(comp_node->type) != source_component_type) {
+ continue;
+ }
for (OperationNode *op_node : comp_node->operations) {
queue.push_back(op_node);
op_node->scheduled = true;
+ op_node->owner->custom_flags |= DEG_NODE_VISITED;
}
}
GHASH_FOREACH_END();
@@ -94,14 +104,7 @@ static void deg_foreach_dependent_ID(const Depsgraph *graph,
OperationNode *op_node = queue.front();
queue.pop_front();
for (;;) {
- /* Check whether we need to inform callee about corresponding ID node. */
- ComponentNode *comp_node = op_node->owner;
- IDNode *id_node = comp_node->owner;
- if ((id_node->custom_flags & DEG_NODE_VISITED) == 0) {
- /* TODO(sergey): Is it orig or CoW? */
- callback(id_node->id_orig, user_data);
- id_node->custom_flags |= DEG_NODE_VISITED;
- }
+ callback(op_node, user_data);
/* Schedule outgoing operation nodes. */
if (op_node->outlinks.size() == 1) {
OperationNode *to_node = (OperationNode *)op_node->outlinks[0]->to;
@@ -127,10 +130,68 @@ static void deg_foreach_dependent_ID(const Depsgraph *graph,
}
}
-static void deg_foreach_ancestor_ID(const Depsgraph *graph,
- const ID *id,
- DEGForeachIDCallback callback,
- void *user_data)
+struct ForeachIDComponentData {
+ DEGForeachIDComponentCallback callback;
+ void *user_data;
+};
+
+void deg_foreach_dependent_component_callback(OperationNode *op_node, void *user_data_v)
+{
+ ForeachIDComponentData *user_data = reinterpret_cast<ForeachIDComponentData *>(user_data_v);
+ ComponentNode *comp_node = op_node->owner;
+ if ((comp_node->custom_flags & DEG_NODE_VISITED) == 0) {
+ IDNode *id_node = comp_node->owner;
+ user_data->callback(
+ id_node->id_orig, nodeTypeToObjectComponent(comp_node->type), user_data->user_data);
+ comp_node->custom_flags |= DEG_NODE_VISITED;
+ }
+}
+
+void deg_foreach_dependent_ID_component(const Depsgraph *graph,
+ const ID *id,
+ eDepsObjectComponentType source_component_type,
+ DEGForeachIDComponentCallback callback,
+ void *user_data)
+{
+ ForeachIDComponentData data;
+ data.callback = callback;
+ data.user_data = user_data;
+ deg_foreach_dependent_operation(
+ graph, id, source_component_type, deg_foreach_dependent_component_callback, &data);
+}
+
+struct ForeachIDData {
+ DEGForeachIDCallback callback;
+ void *user_data;
+};
+
+void deg_foreach_dependent_ID_callback(OperationNode *op_node, void *user_data_v)
+{
+ ForeachIDData *user_data = reinterpret_cast<ForeachIDData *>(user_data_v);
+ ComponentNode *comp_node = op_node->owner;
+ IDNode *id_node = comp_node->owner;
+ if ((id_node->custom_flags & DEG_NODE_VISITED) == 0) {
+ user_data->callback(id_node->id_orig, user_data->user_data);
+ id_node->custom_flags |= DEG_NODE_VISITED;
+ }
+}
+
+void deg_foreach_dependent_ID(const Depsgraph *graph,
+ const ID *id,
+ DEGForeachIDCallback callback,
+ void *user_data)
+{
+ ForeachIDData data;
+ data.callback = callback;
+ data.user_data = user_data;
+ deg_foreach_dependent_operation(
+ graph, id, DEG_OB_COMP_ANY, deg_foreach_dependent_ID_callback, &data);
+}
+
+void deg_foreach_ancestor_ID(const Depsgraph *graph,
+ const ID *id,
+ DEGForeachIDCallback callback,
+ void *user_data)
{
/* Start with getting ID node from the graph. */
IDNode *target_id_node = graph->find_id_node(id);
@@ -196,15 +257,14 @@ static void deg_foreach_ancestor_ID(const Depsgraph *graph,
}
}
-static void deg_foreach_id(const Depsgraph *depsgraph,
- DEGForeachIDCallback callback,
- void *user_data)
+void deg_foreach_id(const Depsgraph *depsgraph, DEGForeachIDCallback callback, void *user_data)
{
for (const IDNode *id_node : depsgraph->id_nodes) {
callback(id_node->id_orig, user_data);
}
}
+} // namespace
} // namespace DEG
void DEG_foreach_dependent_ID(const Depsgraph *depsgraph,
@@ -215,6 +275,16 @@ void DEG_foreach_dependent_ID(const Depsgraph *depsgraph,
DEG::deg_foreach_dependent_ID((const DEG::Depsgraph *)depsgraph, id, callback, user_data);
}
+void DEG_foreach_dependent_ID_component(const Depsgraph *depsgraph,
+ const ID *id,
+ eDepsObjectComponentType source_component_type,
+ DEGForeachIDComponentCallback callback,
+ void *user_data)
+{
+ DEG::deg_foreach_dependent_ID_component(
+ (const DEG::Depsgraph *)depsgraph, id, source_component_type, callback, user_data);
+}
+
void DEG_foreach_ancestor_ID(const Depsgraph *depsgraph,
const ID *id,
DEGForeachIDCallback callback,
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 be78eee91cc..1f310957896 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
@@ -87,6 +87,7 @@ extern "C" {
#include "BKE_library_query.h"
#include "BKE_modifier.h"
#include "BKE_object.h"
+#include "BKE_pointcache.h"
#include "BKE_sequencer.h"
#include "BKE_sound.h"
}
@@ -577,6 +578,7 @@ void update_armature_edit_mode_pointers(const Depsgraph * /*depsgraph*/,
const bArmature *armature_orig = (const bArmature *)id_orig;
bArmature *armature_cow = (bArmature *)id_cow;
armature_cow->edbo = armature_orig->edbo;
+ armature_cow->act_edbone = armature_orig->act_edbone;
}
void update_curve_edit_mode_pointers(const Depsgraph * /*depsgraph*/,
@@ -683,10 +685,29 @@ void set_particle_system_modifiers_loaded(Object *object_cow)
}
}
-void update_particles_after_copy(const Object *object_orig, Object *object_cow)
+void reset_particle_system_edit_eval(const Depsgraph *depsgraph, Object *object_cow)
+{
+ /* Inactive (and render) dependency graphs are living in own little bubble, should not care about
+ * edit mode at all. */
+ if (!DEG_is_active(reinterpret_cast<const ::Depsgraph *>(depsgraph))) {
+ return;
+ }
+ LISTBASE_FOREACH (ParticleSystem *, psys, &object_cow->particlesystem) {
+ ParticleSystem *orig_psys = psys->orig_psys;
+ if (orig_psys->edit != NULL) {
+ orig_psys->edit->psys_eval = NULL;
+ orig_psys->edit->psmd_eval = NULL;
+ }
+ }
+}
+
+void update_particles_after_copy(const Depsgraph *depsgraph,
+ const Object *object_orig,
+ Object *object_cow)
{
update_particle_system_orig_pointers(object_orig, object_cow);
set_particle_system_modifiers_loaded(object_cow);
+ reset_particle_system_edit_eval(depsgraph, object_cow);
}
void update_pose_orig_pointers(const bPose *pose_orig, bPose *pose_cow)
@@ -765,7 +786,7 @@ void update_id_after_copy(const Depsgraph *depsgraph,
}
BKE_pose_pchan_index_rebuild(object_cow->pose);
}
- update_particles_after_copy(object_orig, object_cow);
+ update_particles_after_copy(depsgraph, object_orig, object_cow);
update_modifiers_orig_pointers(object_orig, object_cow);
break;
}
@@ -1321,6 +1342,50 @@ void ObjectRuntimeBackup::restore_pose_channel_runtime_data(Object *object)
}
}
+/* Backup of movie clip runtime data. */
+
+class MovieClipBackup {
+ public:
+ MovieClipBackup();
+
+ void reset();
+
+ void init_from_movieclip(MovieClip *movieclip);
+ void restore_to_movieclip(MovieClip *movieclip);
+
+ struct anim *anim;
+ struct MovieClipCache *cache;
+};
+
+MovieClipBackup::MovieClipBackup()
+{
+ reset();
+}
+
+void MovieClipBackup::reset()
+{
+ anim = NULL;
+ cache = NULL;
+}
+
+void MovieClipBackup::init_from_movieclip(MovieClip *movieclip)
+{
+ anim = movieclip->anim;
+ cache = movieclip->cache;
+ /* Clear pointers stored in the movie clip, so they are not freed when copied-on-written
+ * datablock is freed for re-allocation. */
+ movieclip->anim = NULL;
+ movieclip->cache = NULL;
+}
+
+void MovieClipBackup::restore_to_movieclip(MovieClip *movieclip)
+{
+ movieclip->anim = anim;
+ movieclip->cache = cache;
+
+ reset();
+}
+
class RuntimeBackup {
public:
RuntimeBackup() : drawdata_ptr(NULL)
@@ -1339,6 +1404,7 @@ class RuntimeBackup {
ObjectRuntimeBackup object_backup;
DrawDataList drawdata_backup;
DrawDataList *drawdata_ptr;
+ MovieClipBackup movieclip_backup;
};
void RuntimeBackup::init_from_id(ID *id)
@@ -1357,6 +1423,9 @@ void RuntimeBackup::init_from_id(ID *id)
case ID_SO:
sound_backup.init_from_sound(reinterpret_cast<bSound *>(id));
break;
+ case ID_MC:
+ movieclip_backup.init_from_movieclip(reinterpret_cast<MovieClip *>(id));
+ break;
default:
break;
}
@@ -1382,6 +1451,9 @@ void RuntimeBackup::restore_to_id(ID *id)
case ID_SO:
sound_backup.restore_to_sound(reinterpret_cast<bSound *>(id));
break;
+ case ID_MC:
+ movieclip_backup.restore_to_movieclip(reinterpret_cast<MovieClip *>(id));
+ break;
default:
break;
}
diff --git a/source/blender/depsgraph/intern/node/deg_node.cc b/source/blender/depsgraph/intern/node/deg_node.cc
index 289c9a76cc7..16c934e72fe 100644
--- a/source/blender/depsgraph/intern/node/deg_node.cc
+++ b/source/blender/depsgraph/intern/node/deg_node.cc
@@ -120,6 +120,134 @@ const char *nodeTypeAsString(NodeType type)
return "UNKNOWN";
}
+NodeType nodeTypeFromSceneComponent(eDepsSceneComponentType component)
+{
+ switch (component) {
+ case DEG_SCENE_COMP_PARAMETERS:
+ return NodeType::PARAMETERS;
+ case DEG_SCENE_COMP_ANIMATION:
+ return NodeType::ANIMATION;
+ case DEG_SCENE_COMP_SEQUENCER:
+ return NodeType::SEQUENCER;
+ }
+ return NodeType::UNDEFINED;
+}
+
+eDepsSceneComponentType nodeTypeToSceneComponent(NodeType type)
+{
+ switch (type) {
+ case NodeType::PARAMETERS:
+ return DEG_SCENE_COMP_PARAMETERS;
+ case NodeType::ANIMATION:
+ return DEG_SCENE_COMP_ANIMATION;
+ case NodeType::SEQUENCER:
+ return DEG_SCENE_COMP_SEQUENCER;
+
+ case NodeType::OPERATION:
+ case NodeType::TIMESOURCE:
+ case NodeType::ID_REF:
+ case NodeType::LAYER_COLLECTIONS:
+ case NodeType::COPY_ON_WRITE:
+ case NodeType::OBJECT_FROM_LAYER:
+ case NodeType::AUDIO:
+ case NodeType::ARMATURE:
+ case NodeType::GENERIC_DATABLOCK:
+ case NodeType::PARTICLE_SYSTEM:
+ case NodeType::PARTICLE_SETTINGS:
+ case NodeType::SHADING_PARAMETERS:
+ case NodeType::POINT_CACHE:
+ case NodeType::BATCH_CACHE:
+ case NodeType::DUPLI:
+ case NodeType::SYNCHRONIZATION:
+ case NodeType::UNDEFINED:
+ case NodeType::NUM_TYPES:
+ case NodeType::TRANSFORM:
+ case NodeType::GEOMETRY:
+ case NodeType::EVAL_POSE:
+ case NodeType::BONE:
+ case NodeType::SHADING:
+ case NodeType::CACHE:
+ case NodeType::PROXY:
+ return DEG_SCENE_COMP_PARAMETERS;
+ }
+ BLI_assert(!"Unhandled node type, not suppsed to happen.");
+ return DEG_SCENE_COMP_PARAMETERS;
+}
+
+NodeType nodeTypeFromObjectComponent(eDepsObjectComponentType component_type)
+{
+ switch (component_type) {
+ case DEG_OB_COMP_ANY:
+ return NodeType::UNDEFINED;
+ case DEG_OB_COMP_PARAMETERS:
+ return NodeType::PARAMETERS;
+ case DEG_OB_COMP_PROXY:
+ return NodeType::PROXY;
+ case DEG_OB_COMP_ANIMATION:
+ return NodeType::ANIMATION;
+ case DEG_OB_COMP_TRANSFORM:
+ return NodeType::TRANSFORM;
+ case DEG_OB_COMP_GEOMETRY:
+ return NodeType::GEOMETRY;
+ case DEG_OB_COMP_EVAL_POSE:
+ return NodeType::EVAL_POSE;
+ case DEG_OB_COMP_BONE:
+ return NodeType::BONE;
+ case DEG_OB_COMP_SHADING:
+ return NodeType::SHADING;
+ case DEG_OB_COMP_CACHE:
+ return NodeType::CACHE;
+ }
+ return NodeType::UNDEFINED;
+}
+
+eDepsObjectComponentType nodeTypeToObjectComponent(NodeType type)
+{
+ switch (type) {
+ case NodeType::PARAMETERS:
+ return DEG_OB_COMP_PARAMETERS;
+ case NodeType::PROXY:
+ return DEG_OB_COMP_PROXY;
+ case NodeType::ANIMATION:
+ return DEG_OB_COMP_ANIMATION;
+ case NodeType::TRANSFORM:
+ return DEG_OB_COMP_TRANSFORM;
+ case NodeType::GEOMETRY:
+ return DEG_OB_COMP_GEOMETRY;
+ case NodeType::EVAL_POSE:
+ return DEG_OB_COMP_EVAL_POSE;
+ case NodeType::BONE:
+ return DEG_OB_COMP_BONE;
+ case NodeType::SHADING:
+ return DEG_OB_COMP_SHADING;
+ case NodeType::CACHE:
+ return DEG_OB_COMP_CACHE;
+
+ case NodeType::OPERATION:
+ case NodeType::TIMESOURCE:
+ case NodeType::ID_REF:
+ case NodeType::SEQUENCER:
+ case NodeType::LAYER_COLLECTIONS:
+ case NodeType::COPY_ON_WRITE:
+ case NodeType::OBJECT_FROM_LAYER:
+ case NodeType::AUDIO:
+ case NodeType::ARMATURE:
+ case NodeType::GENERIC_DATABLOCK:
+ case NodeType::PARTICLE_SYSTEM:
+ case NodeType::PARTICLE_SETTINGS:
+ case NodeType::SHADING_PARAMETERS:
+ case NodeType::POINT_CACHE:
+ case NodeType::BATCH_CACHE:
+ case NodeType::DUPLI:
+ case NodeType::SYNCHRONIZATION:
+ case NodeType::UNDEFINED:
+ case NodeType::NUM_TYPES:
+ return DEG_OB_COMP_PARAMETERS;
+ }
+ BLI_assert(!"Unhandled node type, not suppsed to happen.");
+ return DEG_OB_COMP_PARAMETERS;
+}
+
/*******************************************************************************
* Type information.
*/
diff --git a/source/blender/depsgraph/intern/node/deg_node.h b/source/blender/depsgraph/intern/node/deg_node.h
index 705dae41470..eea69502baa 100644
--- a/source/blender/depsgraph/intern/node/deg_node.h
+++ b/source/blender/depsgraph/intern/node/deg_node.h
@@ -27,6 +27,8 @@
#include "BLI_utildefines.h"
+#include "DEG_depsgraph_build.h"
+
struct GHash;
struct ID;
struct Scene;
@@ -95,7 +97,7 @@ enum class NodeType {
/* Audio-related evaluation. */
AUDIO,
ARMATURE,
- /* Un-interestying datablock, which is a part of dependency graph, but does
+ /* Un-interesting data-block, which is a part of dependency graph, but does
* not have very distinctive update procedure. */
GENERIC_DATABLOCK,
@@ -130,6 +132,12 @@ enum class NodeType {
};
const char *nodeTypeAsString(NodeType type);
+NodeType nodeTypeFromSceneComponent(eDepsSceneComponentType component_type);
+eDepsSceneComponentType nodeTypeToSceneComponent(NodeType type);
+
+NodeType nodeTypeFromObjectComponent(eDepsObjectComponentType component_type);
+eDepsObjectComponentType nodeTypeToObjectComponent(NodeType type);
+
/* All nodes in Depsgraph are descended from this. */
struct Node {
/* Helper class for static typeinfo in subclasses. */
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 d0f544dd3c6..12d70131031 100644
--- a/source/blender/draw/engines/eevee/eevee_depth_of_field.c
+++ b/source/blender/draw/engines/eevee/eevee_depth_of_field.c
@@ -97,6 +97,9 @@ int EEVEE_depth_of_field_init(EEVEE_ViewLayerData *UNUSED(sldata),
int buffer_size[2] = {(int)viewport_size[0] / 2, (int)viewport_size[1] / 2};
+ buffer_size[0] = max_ii(1, buffer_size[0]);
+ buffer_size[1] = max_ii(1, buffer_size[1]);
+
eGPUTextureFormat down_format = DRW_state_draw_background() ? GPU_R11F_G11F_B10F : GPU_RGBA16F;
effects->dof_down_near = DRW_texture_pool_query_2d(
diff --git a/source/blender/draw/engines/eevee/eevee_effects.c b/source/blender/draw/engines/eevee/eevee_effects.c
index 021afa64fee..1b152afa3bf 100644
--- a/source/blender/draw/engines/eevee/eevee_effects.c
+++ b/source/blender/draw/engines/eevee/eevee_effects.c
@@ -161,6 +161,12 @@ void EEVEE_effects_init(EEVEE_ViewLayerData *sldata,
effects->enabled_effects |= EEVEE_occlusion_init(sldata, vedata);
effects->enabled_effects |= EEVEE_screen_raytrace_init(sldata, vedata);
+ if ((effects->enabled_effects & EFFECT_TAA) && effects->taa_current_sample > 1) {
+ /* Update matrices here because EEVEE_screen_raytrace_init can have reset the
+ * taa_current_sample. (See T66811) */
+ EEVEE_temporal_sampling_update_matrices(vedata);
+ }
+
EEVEE_volumes_init(sldata, vedata);
EEVEE_subsurface_init(sldata, vedata);
diff --git a/source/blender/draw/engines/eevee/eevee_engine.c b/source/blender/draw/engines/eevee/eevee_engine.c
index 99be7ec631c..b36ad540ef9 100644
--- a/source/blender/draw/engines/eevee/eevee_engine.c
+++ b/source/blender/draw/engines/eevee/eevee_engine.c
@@ -303,6 +303,16 @@ static void eevee_draw_background(void *vedata)
DRW_stats_group_end();
DRW_view_set_active(NULL);
+
+ if (DRW_state_is_image_render() && (stl->effects->enabled_effects & EFFECT_SSR) &&
+ !stl->effects->ssr_was_valid_double_buffer) {
+ /* SSR needs one iteration to start properly. */
+ loop_len++;
+ /* Reset sampling (and accumulation) after the first sample to avoid
+ * washed out first bounce for SSR. */
+ EEVEE_temporal_sampling_reset(vedata);
+ stl->effects->ssr_was_valid_double_buffer = stl->g_data->valid_double_buffer;
+ }
}
/* Tonemapping and transfer result to default framebuffer. */
diff --git a/source/blender/draw/engines/eevee/eevee_lightprobes.c b/source/blender/draw/engines/eevee/eevee_lightprobes.c
index ddc5eae768e..5341661735f 100644
--- a/source/blender/draw/engines/eevee/eevee_lightprobes.c
+++ b/source/blender/draw/engines/eevee/eevee_lightprobes.c
@@ -212,6 +212,7 @@ void EEVEE_lightprobes_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata)
common_data->spec_toggle = true;
common_data->ssr_toggle = true;
+ common_data->ssrefract_toggle = true;
common_data->sss_toggle = true;
/* Placeholder planar pool: used when rendering planar reflections (avoid dependency loop). */
@@ -1264,6 +1265,7 @@ void EEVEE_lightprobes_refresh_planar(EEVEE_ViewLayerData *sldata, EEVEE_Data *v
common_data->prb_num_planar = 0;
/* Turn off ssr to avoid black specular */
common_data->ssr_toggle = false;
+ common_data->ssrefract_toggle = false;
common_data->sss_toggle = false;
common_data->ray_type = EEVEE_RAY_GLOSSY;
@@ -1281,6 +1283,7 @@ void EEVEE_lightprobes_refresh_planar(EEVEE_ViewLayerData *sldata, EEVEE_Data *v
/* Restore */
common_data->prb_num_planar = pinfo->num_planar;
common_data->ssr_toggle = true;
+ common_data->ssrefract_toggle = true;
common_data->sss_toggle = true;
/* Prefilter for SSR */
diff --git a/source/blender/draw/engines/eevee/eevee_lookdev.c b/source/blender/draw/engines/eevee/eevee_lookdev.c
index 2d4cc069697..e6e699bef10 100644
--- a/source/blender/draw/engines/eevee/eevee_lookdev.c
+++ b/source/blender/draw/engines/eevee/eevee_lookdev.c
@@ -71,6 +71,8 @@ void EEVEE_lookdev_cache_init(EEVEE_Data *vedata,
View3D *v3d = draw_ctx->v3d;
Scene *scene = draw_ctx->scene;
+ effects->lookdev_view = NULL;
+
if (LOOK_DEV_OVERLAY_ENABLED(v3d)) {
/* Viewport / Spheres size. */
rcti rect;
diff --git a/source/blender/draw/engines/eevee/eevee_materials.c b/source/blender/draw/engines/eevee/eevee_materials.c
index f5f3a7a70e3..61da9e21cc8 100644
--- a/source/blender/draw/engines/eevee/eevee_materials.c
+++ b/source/blender/draw/engines/eevee/eevee_materials.c
@@ -1659,14 +1659,17 @@ void EEVEE_materials_cache_populate(EEVEE_Data *vedata,
char *name = auto_layer_names;
for (int j = 0; j < auto_layer_count; ++j) {
/* TODO don't add these uniform when not needed (default pass shaders). */
+ /* FIXME: This is broken, as it overrides any autolayers srgb bool of the previous mesh
+ * that shares the same material. */
if (shgrp_array[i]) {
- DRW_shgroup_uniform_bool(shgrp_array[i], name, &auto_layer_is_srgb[j], 1);
+ DRW_shgroup_uniform_bool_copy(shgrp_array[i], name, auto_layer_is_srgb[j]);
}
if (shgrp_depth_array[i]) {
- DRW_shgroup_uniform_bool(shgrp_depth_array[i], name, &auto_layer_is_srgb[j], 1);
+ DRW_shgroup_uniform_bool_copy(shgrp_depth_array[i], name, auto_layer_is_srgb[j]);
}
if (shgrp_depth_clip_array[i]) {
- DRW_shgroup_uniform_bool(shgrp_depth_clip_array[i], name, &auto_layer_is_srgb[j], 1);
+ DRW_shgroup_uniform_bool_copy(
+ shgrp_depth_clip_array[i], name, auto_layer_is_srgb[j]);
}
/* Go to next layer name. */
while (*name != '\0') {
diff --git a/source/blender/draw/engines/eevee/eevee_private.h b/source/blender/draw/engines/eevee/eevee_private.h
index 166e8ac7473..bd08a61e3b8 100644
--- a/source/blender/draw/engines/eevee/eevee_private.h
+++ b/source/blender/draw/engines/eevee/eevee_private.h
@@ -562,6 +562,7 @@ typedef struct EEVEE_EffectsInfo {
/* SSR */
bool reflection_trace_full;
bool ssr_was_persp;
+ bool ssr_was_valid_double_buffer;
int ssr_neighbor_ofs;
int ssr_halfres_ofs[2];
struct GPUTexture *ssr_normal_input; /* Textures from pool */
@@ -653,11 +654,11 @@ typedef struct EEVEE_CommonUniformBuffer {
float ao_offset, ao_bounce_fac, ao_quality, ao_settings; /* vec4 */
/* Volumetric */
/* -- 16 byte aligned -- */
- int vol_tex_size[3], pad3; /* ivec3 */
- float vol_depth_param[3], pad4; /* vec3 */
- float vol_inv_tex_size[3], pad5; /* vec3 */
- float vol_jitter[3], pad6; /* vec3 */
- float vol_coord_scale[2], pad7[2]; /* vec2 */
+ int vol_tex_size[3], pad3; /* ivec3 */
+ float vol_depth_param[3], pad4; /* vec3 */
+ float vol_inv_tex_size[3], pad5; /* vec3 */
+ float vol_jitter[3], pad6; /* vec3 */
+ float vol_coord_scale[4]; /* vec4 */
/* -- 16 byte aligned -- */
float vol_history_alpha; /* float */
float vol_light_clamp; /* float */
@@ -671,6 +672,7 @@ typedef struct EEVEE_CommonUniformBuffer {
float ssr_firefly_fac; /* float */
float ssr_brdf_bias; /* float */
int ssr_toggle; /* bool */
+ int ssrefract_toggle; /* bool */
/* SubSurface Scattering */
float sss_jitter_threshold; /* float */
int sss_toggle; /* bool */
@@ -690,8 +692,6 @@ typedef struct EEVEE_CommonUniformBuffer {
int hiz_mip_offset; /* int */
int ray_type; /* int */
float ray_depth; /* float */
-
- float pad_common_ubo;
} EEVEE_CommonUniformBuffer;
BLI_STATIC_ASSERT_ALIGN(EEVEE_CommonUniformBuffer, 16)
diff --git a/source/blender/draw/engines/eevee/eevee_render.c b/source/blender/draw/engines/eevee/eevee_render.c
index 2afd0b1d313..286bcd8f738 100644
--- a/source/blender/draw/engines/eevee/eevee_render.c
+++ b/source/blender/draw/engines/eevee/eevee_render.c
@@ -536,6 +536,11 @@ void EEVEE_render_draw(EEVEE_Data *vedata, RenderEngine *engine, RenderLayer *rl
return;
}
+ /* SSR needs one iteration to start properly. */
+ if (stl->effects->enabled_effects & EFFECT_SSR) {
+ tot_sample += 1;
+ }
+
while (render_samples < tot_sample && !RE_engine_test_break(engine)) {
float clear_col[4] = {0.0f, 0.0f, 0.0f, 0.0f};
float clear_depth = 1.0f;
@@ -544,6 +549,25 @@ void EEVEE_render_draw(EEVEE_Data *vedata, RenderEngine *engine, RenderLayer *rl
double offset[3] = {0.0, 0.0, 0.0};
double r[3];
+ if ((stl->effects->enabled_effects & EFFECT_SSR) && (render_samples == 1) &&
+ !stl->effects->ssr_was_valid_double_buffer) {
+ /* SSR needs one iteration to start properly.
+ * This iteration was done, reset to the original target sample count. */
+ render_samples--;
+ tot_sample--;
+ /* Reset sampling (and accumulation) after the first sample to avoid
+ * washed out first bounce for SSR. */
+ EEVEE_temporal_sampling_reset(vedata);
+ stl->effects->ssr_was_valid_double_buffer = stl->g_data->valid_double_buffer;
+ }
+ /* Don't print every samples as it can lead to bad performance. (see T59649) */
+ else if ((render_samples % 25) == 0 || (render_samples + 1) == tot_sample) {
+ char info[42];
+ BLI_snprintf(
+ info, sizeof(info), "Rendering %u / %u samples", render_samples + 1, tot_sample);
+ RE_engine_update_stats(engine, NULL, info);
+ }
+
/* Copy previous persmat to UBO data */
copy_m4_m4(sldata->common_data.prev_persmat, stl->effects->prev_persmat);
@@ -557,14 +581,6 @@ void EEVEE_render_draw(EEVEE_Data *vedata, RenderEngine *engine, RenderLayer *rl
EEVEE_lightprobes_refresh(sldata, vedata);
EEVEE_lightprobes_refresh_planar(sldata, vedata);
- /* Don't print every samples as it can lead to bad performance. (see T59649) */
- if ((render_samples % 25) == 0 || (render_samples + 1) == tot_sample) {
- char info[42];
- BLI_snprintf(
- info, sizeof(info), "Rendering %u / %u samples", render_samples + 1, tot_sample);
- RE_engine_update_stats(engine, NULL, info);
- }
-
/* Refresh Shadows */
EEVEE_lights_update(sldata, vedata);
EEVEE_draw_shadows(sldata, vedata, stl->effects->taa_view);
diff --git a/source/blender/draw/engines/eevee/eevee_screen_raytrace.c b/source/blender/draw/engines/eevee/eevee_screen_raytrace.c
index 7b80daf8ed6..d53ed239f4e 100644
--- a/source/blender/draw/engines/eevee/eevee_screen_raytrace.c
+++ b/source/blender/draw/engines/eevee/eevee_screen_raytrace.c
@@ -135,6 +135,12 @@ int EEVEE_screen_raytrace_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata)
stl->g_data->valid_double_buffer = false;
}
+ if (!effects->ssr_was_valid_double_buffer) {
+ DRW_viewport_request_redraw();
+ EEVEE_temporal_sampling_reset(vedata);
+ }
+ effects->ssr_was_valid_double_buffer = stl->g_data->valid_double_buffer;
+
effects->reflection_trace_full = (scene_eval->eevee.flag & SCE_EEVEE_SSR_HALF_RESOLUTION) == 0;
common_data->ssr_thickness = scene_eval->eevee.ssr_thickness;
common_data->ssr_border_fac = scene_eval->eevee.ssr_border_fade;
@@ -153,6 +159,9 @@ int EEVEE_screen_raytrace_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata)
const bool high_qual_input = true; /* TODO dither low quality input */
const eGPUTextureFormat format = (high_qual_input) ? GPU_RGBA16F : GPU_RGBA8;
+ tracing_res[0] = max_ii(1, tracing_res[0]);
+ tracing_res[1] = max_ii(1, tracing_res[1]);
+
/* MRT for the shading pass in order to output needed data for the SSR pass. */
effects->ssr_specrough_input = DRW_texture_pool_query_2d(
size_fs[0], size_fs[1], format, &draw_engine_eevee_type);
diff --git a/source/blender/draw/engines/eevee/eevee_temporal_sampling.c b/source/blender/draw/engines/eevee/eevee_temporal_sampling.c
index 099147a82dd..96924efa8bc 100644
--- a/source/blender/draw/engines/eevee/eevee_temporal_sampling.c
+++ b/source/blender/draw/engines/eevee/eevee_temporal_sampling.c
@@ -253,7 +253,6 @@ int EEVEE_temporal_sampling_init(EEVEE_ViewLayerData *UNUSED(sldata), EEVEE_Data
if (!DRW_state_is_image_render()) {
effects->taa_current_sample += 1;
repro_flag = 0;
- EEVEE_temporal_sampling_update_matrices(vedata);
}
}
else {
diff --git a/source/blender/draw/engines/eevee/eevee_volumes.c b/source/blender/draw/engines/eevee/eevee_volumes.c
index 9c8ec6e52a4..f85c30044a9 100644
--- a/source/blender/draw/engines/eevee/eevee_volumes.c
+++ b/source/blender/draw/engines/eevee/eevee_volumes.c
@@ -178,6 +178,8 @@ void EEVEE_volumes_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata)
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]);
+ common_data->vol_coord_scale[2] = 1.0f / viewport_size[0];
+ common_data->vol_coord_scale[3] = 1.0f / viewport_size[1];
/* TODO compute snap to maxZBuffer for clustered rendering */
if ((common_data->vol_tex_size[0] != tex_size[0]) ||
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 3a31afc0224..274269846bc 100644
--- a/source/blender/draw/engines/eevee/shaders/bsdf_common_lib.glsl
+++ b/source/blender/draw/engines/eevee/shaders/bsdf_common_lib.glsl
@@ -915,8 +915,7 @@ void main()
# endif
# if defined(USE_ALPHA_BLEND)
- /* XXX fragile, better use real viewport resolution */
- vec2 uvs = gl_FragCoord.xy / vec2(2 * textureSize(maxzBuffer, 0).xy);
+ vec2 uvs = gl_FragCoord.xy * volCoordScale.zw;
vec3 transmittance, scattering;
volumetric_resolve(uvs, gl_FragCoord.z, transmittance, scattering);
fragColor.rgb = cl.radiance * transmittance + scattering;
diff --git a/source/blender/draw/engines/eevee/shaders/common_uniforms_lib.glsl b/source/blender/draw/engines/eevee/shaders/common_uniforms_lib.glsl
index da0778b8a10..c7ae2417904 100644
--- a/source/blender/draw/engines/eevee/shaders/common_uniforms_lib.glsl
+++ b/source/blender/draw/engines/eevee/shaders/common_uniforms_lib.glsl
@@ -23,6 +23,7 @@ layout(std140) uniform common_block
float ssrFireflyFac;
float ssrBrdfBias;
bool ssrToggle;
+ bool ssrefractToggle;
/* SubSurface Scattering */
float sssJitterThreshold;
bool sssToggle;
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 6b3d9ee4517..53f1517505c 100644
--- a/source/blender/draw/engines/eevee/shaders/lit_surface_frag.glsl
+++ b/source/blender/draw/engines/eevee/shaders/lit_surface_frag.glsl
@@ -1,14 +1,14 @@
#ifndef LIT_SURFACE_UNIFORM
-#define LIT_SURFACE_UNIFORM
+# define LIT_SURFACE_UNIFORM
uniform float refractionDepth;
-#ifndef UTIL_TEX
-# define UTIL_TEX
+# ifndef UTIL_TEX
+# define UTIL_TEX
uniform sampler2DArray utilTex;
-# define texelfetch_noise_tex(coord) texelFetch(utilTex, ivec3(ivec2(coord) % LUT_SIZE, 2.0), 0)
-#endif /* UTIL_TEX */
+# define texelfetch_noise_tex(coord) texelFetch(utilTex, ivec3(ivec2(coord) % LUT_SIZE, 2.0), 0)
+# endif /* UTIL_TEX */
in vec3 worldPosition;
in vec3 viewPosition;
@@ -16,7 +16,7 @@ in vec3 viewPosition;
in vec3 worldNormal;
in vec3 viewNormal;
-#ifdef HAIR_SHADER
+# ifdef HAIR_SHADER
in vec3 hairTangent; /* world space */
in float hairThickTime;
in float hairThickness;
@@ -24,7 +24,7 @@ in float hairTime;
flat in int hairStrandID;
uniform int hairThicknessRes = 1;
-#endif
+# endif
#endif /* LIT_SURFACE_UNIFORM */
@@ -33,82 +33,82 @@ uniform int hairThicknessRes = 1;
* This leads to a lot of deadcode. Better idea would be to only generate the one needed.
*/
#if !defined(SURFACE_DEFAULT)
-#define SURFACE_DEFAULT
-#define CLOSURE_NAME eevee_closure_default
-#define CLOSURE_DIFFUSE
-#define CLOSURE_GLOSSY
+# define SURFACE_DEFAULT
+# define CLOSURE_NAME eevee_closure_default
+# define CLOSURE_DIFFUSE
+# define CLOSURE_GLOSSY
#endif /* SURFACE_DEFAULT */
#if !defined(SURFACE_DEFAULT_CLEARCOAT) && !defined(CLOSURE_NAME)
-#define SURFACE_DEFAULT_CLEARCOAT
-#define CLOSURE_NAME eevee_closure_default_clearcoat
-#define CLOSURE_DIFFUSE
-#define CLOSURE_GLOSSY
-#define CLOSURE_CLEARCOAT
+# define SURFACE_DEFAULT_CLEARCOAT
+# define CLOSURE_NAME eevee_closure_default_clearcoat
+# define CLOSURE_DIFFUSE
+# define CLOSURE_GLOSSY
+# define CLOSURE_CLEARCOAT
#endif /* SURFACE_DEFAULT_CLEARCOAT */
#if !defined(SURFACE_PRINCIPLED) && !defined(CLOSURE_NAME)
-#define SURFACE_PRINCIPLED
-#define CLOSURE_NAME eevee_closure_principled
-#define CLOSURE_DIFFUSE
-#define CLOSURE_GLOSSY
-#define CLOSURE_CLEARCOAT
-#define CLOSURE_REFRACTION
-#define CLOSURE_SUBSURFACE
+# define SURFACE_PRINCIPLED
+# define CLOSURE_NAME eevee_closure_principled
+# define CLOSURE_DIFFUSE
+# define CLOSURE_GLOSSY
+# define CLOSURE_CLEARCOAT
+# define CLOSURE_REFRACTION
+# define CLOSURE_SUBSURFACE
#endif /* SURFACE_PRINCIPLED */
#if !defined(SURFACE_CLEARCOAT) && !defined(CLOSURE_NAME)
-#define SURFACE_CLEARCOAT
-#define CLOSURE_NAME eevee_closure_clearcoat
-#define CLOSURE_GLOSSY
-#define CLOSURE_CLEARCOAT
+# define SURFACE_CLEARCOAT
+# define CLOSURE_NAME eevee_closure_clearcoat
+# define CLOSURE_GLOSSY
+# define CLOSURE_CLEARCOAT
#endif /* SURFACE_CLEARCOAT */
#if !defined(SURFACE_DIFFUSE) && !defined(CLOSURE_NAME)
-#define SURFACE_DIFFUSE
-#define CLOSURE_NAME eevee_closure_diffuse
-#define CLOSURE_DIFFUSE
+# define SURFACE_DIFFUSE
+# define CLOSURE_NAME eevee_closure_diffuse
+# define CLOSURE_DIFFUSE
#endif /* SURFACE_DIFFUSE */
#if !defined(SURFACE_SUBSURFACE) && !defined(CLOSURE_NAME)
-#define SURFACE_SUBSURFACE
-#define CLOSURE_NAME eevee_closure_subsurface
-#define CLOSURE_DIFFUSE
-#define CLOSURE_SUBSURFACE
+# define SURFACE_SUBSURFACE
+# define CLOSURE_NAME eevee_closure_subsurface
+# define CLOSURE_DIFFUSE
+# define CLOSURE_SUBSURFACE
#endif /* SURFACE_SUBSURFACE */
#if !defined(SURFACE_SKIN) && !defined(CLOSURE_NAME)
-#define SURFACE_SKIN
-#define CLOSURE_NAME eevee_closure_skin
-#define CLOSURE_DIFFUSE
-#define CLOSURE_SUBSURFACE
-#define CLOSURE_GLOSSY
+# define SURFACE_SKIN
+# define CLOSURE_NAME eevee_closure_skin
+# define CLOSURE_DIFFUSE
+# define CLOSURE_SUBSURFACE
+# define CLOSURE_GLOSSY
#endif /* SURFACE_SKIN */
#if !defined(SURFACE_GLOSSY) && !defined(CLOSURE_NAME)
-#define SURFACE_GLOSSY
-#define CLOSURE_NAME eevee_closure_glossy
-#define CLOSURE_GLOSSY
+# define SURFACE_GLOSSY
+# define CLOSURE_NAME eevee_closure_glossy
+# define CLOSURE_GLOSSY
#endif /* SURFACE_GLOSSY */
#if !defined(SURFACE_REFRACT) && !defined(CLOSURE_NAME)
-#define SURFACE_REFRACT
-#define CLOSURE_NAME eevee_closure_refraction
-#define CLOSURE_REFRACTION
+# define SURFACE_REFRACT
+# define CLOSURE_NAME eevee_closure_refraction
+# define CLOSURE_REFRACTION
#endif /* SURFACE_REFRACT */
#if !defined(SURFACE_GLASS) && !defined(CLOSURE_NAME)
-#define SURFACE_GLASS
-#define CLOSURE_NAME eevee_closure_glass
-#define CLOSURE_GLOSSY
-#define CLOSURE_REFRACTION
+# define SURFACE_GLASS
+# define CLOSURE_NAME eevee_closure_glass
+# define CLOSURE_GLOSSY
+# define CLOSURE_REFRACTION
#endif /* SURFACE_GLASS */
/* Safety : CLOSURE_CLEARCOAT implies CLOSURE_GLOSSY */
#ifdef CLOSURE_CLEARCOAT
-#ifndef CLOSURE_GLOSSY
-# define CLOSURE_GLOSSY
-#endif
+# ifndef CLOSURE_GLOSSY
+# define CLOSURE_GLOSSY
+# endif
#endif /* CLOSURE_CLEARCOAT */
void CLOSURE_NAME(vec3 N
@@ -184,7 +184,7 @@ void CLOSURE_NAME(vec3 N
#ifdef SHADOW_SHADER
return;
-#endif
+#else
/* Zero length vectors cause issues, see: T51979. */
float len = length(N);
@@ -193,23 +193,23 @@ void CLOSURE_NAME(vec3 N
}
N /= len;
-#ifdef CLOSURE_CLEARCOAT
+# ifdef CLOSURE_CLEARCOAT
len = length(C_N);
if (isnan(len)) {
return;
}
C_N /= len;
-#endif
+# endif
-#if defined(CLOSURE_GLOSSY) || defined(CLOSURE_REFRACTION)
+# if defined(CLOSURE_GLOSSY) || defined(CLOSURE_REFRACTION)
roughness = clamp(roughness, 1e-8, 0.9999);
float roughnessSquared = roughness * roughness;
-#endif
+# endif
-#ifdef CLOSURE_CLEARCOAT
+# ifdef CLOSURE_CLEARCOAT
C_roughness = clamp(C_roughness, 1e-8, 0.9999);
float C_roughnessSquared = C_roughness * C_roughness;
-#endif
+# endif
vec3 V = cameraVec;
@@ -219,16 +219,16 @@ void CLOSURE_NAME(vec3 N
/* -------------------- SCENE LIGHTS LIGHTING --------------------- */
/* ---------------------------------------------------------------- */
-#ifdef CLOSURE_GLOSSY
+# ifdef CLOSURE_GLOSSY
vec2 lut_uv = lut_coords_ltc(dot(N, V), roughness);
vec4 ltc_mat = texture(utilTex, vec3(lut_uv, 0.0)).rgba;
-#endif
+# endif
-#ifdef CLOSURE_CLEARCOAT
+# ifdef CLOSURE_CLEARCOAT
vec2 lut_uv_clear = lut_coords_ltc(dot(C_N, V), C_roughness);
vec4 ltc_mat_clear = texture(utilTex, vec3(lut_uv_clear, 0.0)).rgba;
vec3 out_spec_clear = vec3(0.0);
-#endif
+# endif
for (int i = 0; i < MAX_LIGHT && i < laNumLight; ++i) {
LightData ld = lights_data[i];
@@ -245,34 +245,34 @@ void CLOSURE_NAME(vec3 N
vec3 l_color_vis = ld.l_color * l_vis;
-#ifdef CLOSURE_DIFFUSE
+# ifdef CLOSURE_DIFFUSE
out_diff += l_color_vis * light_diffuse(ld, N, V, l_vector);
-#endif
+# endif
-#ifdef CLOSURE_SUBSURFACE
+# ifdef CLOSURE_SUBSURFACE
out_trans += ld.l_color * light_translucent(ld, worldPosition, -N, l_vector, sss_scale);
-#endif
+# endif
-#ifdef CLOSURE_GLOSSY
+# ifdef CLOSURE_GLOSSY
out_spec += l_color_vis * light_specular(ld, ltc_mat, N, V, l_vector) * ld.l_spec;
-#endif
+# endif
-#ifdef CLOSURE_CLEARCOAT
+# ifdef CLOSURE_CLEARCOAT
out_spec_clear += l_color_vis * light_specular(ld, ltc_mat_clear, C_N, V, l_vector) *
ld.l_spec;
-#endif
+# endif
}
-#ifdef CLOSURE_GLOSSY
+# ifdef CLOSURE_GLOSSY
vec2 brdf_lut_lights = texture(utilTex, vec3(lut_uv, 1.0)).ba;
out_spec *= F_area(f0, f90, brdf_lut_lights.xy);
-#endif
+# endif
-#ifdef CLOSURE_CLEARCOAT
+# ifdef CLOSURE_CLEARCOAT
vec2 brdf_lut_lights_clear = texture(utilTex, vec3(lut_uv_clear, 1.0)).ba;
out_spec_clear *= F_area(vec3(0.04), vec3(1.0), brdf_lut_lights_clear.xy);
out_spec += out_spec_clear * C_intensity;
-#endif
+# endif
/* ---------------------------------------------------------------- */
/* ---------------- SPECULAR ENVIRONMENT LIGHTING ----------------- */
@@ -280,19 +280,19 @@ void CLOSURE_NAME(vec3 N
/* Accumulate incoming light from all sources until accumulator is full. Then apply Occlusion and
* BRDF. */
-#ifdef CLOSURE_GLOSSY
+# ifdef CLOSURE_GLOSSY
vec4 spec_accum = vec4(0.0);
-#endif
+# endif
-#ifdef CLOSURE_CLEARCOAT
+# ifdef CLOSURE_CLEARCOAT
vec4 C_spec_accum = vec4(0.0);
-#endif
+# endif
-#ifdef CLOSURE_REFRACTION
+# ifdef CLOSURE_REFRACTION
vec4 refr_accum = vec4(0.0);
-#endif
+# endif
-#ifdef CLOSURE_GLOSSY
+# ifdef CLOSURE_GLOSSY
/* ---------------------------- */
/* Planar Reflections */
/* ---------------------------- */
@@ -310,23 +310,23 @@ void CLOSURE_NAME(vec3 N
accumulate_light(spec, fade, spec_accum);
}
-#ifdef CLOSURE_CLEARCOAT
+# ifdef CLOSURE_CLEARCOAT
vec3 C_spec = probe_evaluate_planar(float(i), pd, worldPosition, C_N, V, C_roughness, fade);
accumulate_light(C_spec, fade, C_spec_accum);
-#endif
+# endif
}
}
-#endif
+# endif
-#ifdef CLOSURE_GLOSSY
+# ifdef CLOSURE_GLOSSY
vec3 spec_dir = get_specular_reflection_dominant_dir(N, V, roughnessSquared);
-#endif
+# endif
-#ifdef CLOSURE_CLEARCOAT
+# ifdef CLOSURE_CLEARCOAT
vec3 C_spec_dir = get_specular_reflection_dominant_dir(C_N, V, C_roughnessSquared);
-#endif
+# endif
-#ifdef CLOSURE_REFRACTION
+# ifdef CLOSURE_REFRACTION
/* Refract the view vector using the depth heuristic.
* Then later Refract a second time the already refracted
* ray using the inverse ior. */
@@ -337,14 +337,14 @@ void CLOSURE_NAME(vec3 N
worldPosition, refr_V, worldPosition - N * refractionDepth, N) :
worldPosition;
vec3 refr_dir = get_specular_refraction_dominant_dir(N, refr_V, roughness, final_ior);
-#endif
+# endif
-#ifdef CLOSURE_REFRACTION
+# ifdef CLOSURE_REFRACTION
/* ---------------------------- */
/* Screen Space Refraction */
/* ---------------------------- */
-#ifdef USE_REFRACTION
- if (ssrToggle && roughness < ssrMaxRoughness + 0.2) {
+# ifdef USE_REFRACTION
+ if (ssrefractToggle && roughness < ssrMaxRoughness + 0.2) {
/* Find approximated position of the 2nd refraction event. */
vec3 refr_vpos = (refractionDepth > 0.0) ? transform_point(ViewMatrix, refr_pos) :
viewPosition;
@@ -352,25 +352,25 @@ void CLOSURE_NAME(vec3 N
trans.a *= smoothstep(ssrMaxRoughness + 0.2, ssrMaxRoughness, roughness);
accumulate_light(trans.rgb, trans.a, refr_accum);
}
-#endif
+# endif
-#endif
+# endif
/* ---------------------------- */
/* Specular probes */
/* ---------------------------- */
-#if defined(CLOSURE_GLOSSY) || defined(CLOSURE_REFRACTION)
-
-#if defined(CLOSURE_GLOSSY) && defined(CLOSURE_REFRACTION)
-# define GLASS_ACCUM 1
-# define ACCUM min(refr_accum.a, spec_accum.a)
-#elif defined(CLOSURE_REFRACTION)
-# define GLASS_ACCUM 0
-# define ACCUM refr_accum.a
-#else
-# define GLASS_ACCUM 0
-# define ACCUM spec_accum.a
-#endif
+# if defined(CLOSURE_GLOSSY) || defined(CLOSURE_REFRACTION)
+
+# if defined(CLOSURE_GLOSSY) && defined(CLOSURE_REFRACTION)
+# define GLASS_ACCUM 1
+# define ACCUM min(refr_accum.a, spec_accum.a)
+# elif defined(CLOSURE_REFRACTION)
+# define GLASS_ACCUM 0
+# define ACCUM refr_accum.a
+# else
+# define GLASS_ACCUM 0
+# define ACCUM spec_accum.a
+# endif
/* Starts at 1 because 0 is world probe */
for (int i = 1; ACCUM < 0.999 && i < prbNumRenderCube && i < MAX_PROBE; ++i) {
@@ -378,80 +378,80 @@ void CLOSURE_NAME(vec3 N
if (fade > 0.0) {
-#if GLASS_ACCUM
+# if GLASS_ACCUM
if (spec_accum.a < 0.999) {
-#endif
-#ifdef CLOSURE_GLOSSY
+# endif
+# ifdef CLOSURE_GLOSSY
if (!(ssrToggle && ssr_id == outputSsrId)) {
vec3 spec = probe_evaluate_cube(i, worldPosition, spec_dir, roughness);
accumulate_light(spec, fade, spec_accum);
}
-#endif
+# endif
-#ifdef CLOSURE_CLEARCOAT
+# ifdef CLOSURE_CLEARCOAT
vec3 C_spec = probe_evaluate_cube(i, worldPosition, C_spec_dir, C_roughness);
accumulate_light(C_spec, fade, C_spec_accum);
-#endif
-#if GLASS_ACCUM
+# endif
+# if GLASS_ACCUM
}
-#endif
+# endif
-#if GLASS_ACCUM
+# if GLASS_ACCUM
if (refr_accum.a < 0.999) {
-#endif
-#ifdef CLOSURE_REFRACTION
+# endif
+# ifdef CLOSURE_REFRACTION
vec3 trans = probe_evaluate_cube(i, refr_pos, refr_dir, roughnessSquared);
accumulate_light(trans, fade, refr_accum);
-#endif
-#if GLASS_ACCUM
+# endif
+# if GLASS_ACCUM
}
-#endif
+# endif
}
}
-#undef GLASS_ACCUM
-#undef ACCUM
+# undef GLASS_ACCUM
+# undef ACCUM
/* ---------------------------- */
/* World Probe */
/* ---------------------------- */
-#ifdef CLOSURE_GLOSSY
+# ifdef CLOSURE_GLOSSY
if (spec_accum.a < 0.999) {
if (!(ssrToggle && ssr_id == outputSsrId)) {
vec3 spec = probe_evaluate_world_spec(spec_dir, roughness);
accumulate_light(spec, 1.0, spec_accum);
}
-# ifdef CLOSURE_CLEARCOAT
+# ifdef CLOSURE_CLEARCOAT
vec3 C_spec = probe_evaluate_world_spec(C_spec_dir, C_roughness);
accumulate_light(C_spec, 1.0, C_spec_accum);
-# endif
+# endif
}
-#endif
+# endif
-#ifdef CLOSURE_REFRACTION
+# ifdef CLOSURE_REFRACTION
if (refr_accum.a < 0.999) {
vec3 trans = probe_evaluate_world_spec(refr_dir, roughnessSquared);
accumulate_light(trans, 1.0, refr_accum);
}
-#endif
-#endif /* Specular probes */
+# endif
+# endif /* Specular probes */
/* ---------------------------- */
/* Ambient Occlusion */
/* ---------------------------- */
-#if defined(CLOSURE_GLOSSY) || defined(CLOSURE_DIFFUSE)
+# if defined(CLOSURE_GLOSSY) || defined(CLOSURE_DIFFUSE)
/* HACK: Fix for translucent BSDF. (see T65631) */
bool same_side = dot((gl_FrontFacing) ? worldNormal : -worldNormal, N) > 0.0;
vec3 bent_normal;
float final_ao = occlusion_compute(same_side ? N : -N, viewPosition, ao, rand, bent_normal);
-#endif
+# endif
/* ---------------------------- */
/* Specular Output */
/* ---------------------------- */
float NV = dot(N, V);
-#ifdef CLOSURE_GLOSSY
+# ifdef CLOSURE_GLOSSY
vec2 uv = lut_coords(NV, roughness);
vec2 brdf_lut = texture(utilTex, vec3(uv, 1.0)).rg;
@@ -466,15 +466,15 @@ void CLOSURE_NAME(vec3 N
}
out_spec += spec_accum.rgb * ssr_spec * spec_occlu;
-#endif
+# endif
-#ifdef CLOSURE_REFRACTION
+# ifdef CLOSURE_REFRACTION
float btdf = get_btdf_lut(utilTex, NV, roughness, ior);
out_refr += refr_accum.rgb * btdf;
-#endif
+# endif
-#ifdef CLOSURE_CLEARCOAT
+# ifdef CLOSURE_CLEARCOAT
NV = dot(C_N, V);
vec2 C_uv = lut_coords(NV, C_roughness);
vec2 C_brdf_lut = texture(utilTex, vec3(C_uv, 1.0)).rg;
@@ -482,19 +482,19 @@ void CLOSURE_NAME(vec3 N
specular_occlusion(NV, final_ao, C_roughness);
out_spec += C_spec_accum.rgb * C_fresnel * C_intensity;
-#endif
+# endif
-#ifdef CLOSURE_GLOSSY
+# ifdef CLOSURE_GLOSSY
/* Global toggle for lightprobe baking. */
out_spec *= float(specToggle);
-#endif
+# endif
/* ---------------------------------------------------------------- */
/* ---------------- DIFFUSE ENVIRONMENT LIGHTING ------------------ */
/* ---------------------------------------------------------------- */
/* Accumulate light from all sources until accumulator is full. Then apply Occlusion and BRDF. */
-#ifdef CLOSURE_DIFFUSE
+# ifdef CLOSURE_DIFFUSE
vec4 diff_accum = vec4(0.0);
/* ---------------------------- */
@@ -522,6 +522,7 @@ void CLOSURE_NAME(vec3 N
}
out_diff += diff_accum.rgb * gtao_multibounce(final_ao, albedo);
+# endif
#endif
}
@@ -529,21 +530,21 @@ void CLOSURE_NAME(vec3 N
#undef CLOSURE_NAME
#ifdef CLOSURE_DIFFUSE
-#undef CLOSURE_DIFFUSE
+# undef CLOSURE_DIFFUSE
#endif
#ifdef CLOSURE_GLOSSY
-#undef CLOSURE_GLOSSY
+# undef CLOSURE_GLOSSY
#endif
#ifdef CLOSURE_CLEARCOAT
-#undef CLOSURE_CLEARCOAT
+# undef CLOSURE_CLEARCOAT
#endif
#ifdef CLOSURE_REFRACTION
-#undef CLOSURE_REFRACTION
+# undef CLOSURE_REFRACTION
#endif
#ifdef CLOSURE_SUBSURFACE
-#undef CLOSURE_SUBSURFACE
+# undef CLOSURE_SUBSURFACE
#endif
diff --git a/source/blender/draw/engines/eevee/shaders/volumetric_integration_frag.glsl b/source/blender/draw/engines/eevee/shaders/volumetric_integration_frag.glsl
index e756cafba52..acd1e58ff97 100644
--- a/source/blender/draw/engines/eevee/shaders/volumetric_integration_frag.glsl
+++ b/source/blender/draw/engines/eevee/shaders/volumetric_integration_frag.glsl
@@ -48,6 +48,10 @@ void main()
float cell_depth = volume_z_to_view_z((float(i) + 1.0) / tex_size.z);
float ray_len = orig_ray_len * cell_depth;
+ /* Emission does not work of there is no extinction because
+ * Tr evaluates to 1.0 leading to Lscat = 0.0. (See T65771) */
+ s_extinction = max(vec3(1e-7) * step(1e-5, Lscat), s_extinction);
+
/* Evaluate Scattering */
float s_len = abs(ray_len - prev_ray_len);
prev_ray_len = ray_len;
diff --git a/source/blender/draw/engines/eevee/shaders/volumetric_resolve_frag.glsl b/source/blender/draw/engines/eevee/shaders/volumetric_resolve_frag.glsl
index 757eb59eaa1..1ff7e848c40 100644
--- a/source/blender/draw/engines/eevee/shaders/volumetric_resolve_frag.glsl
+++ b/source/blender/draw/engines/eevee/shaders/volumetric_resolve_frag.glsl
@@ -2,9 +2,7 @@
/* Based on Frosbite Unified Volumetric.
* https://www.ea.com/frostbite/news/physically-based-unified-volumetric-rendering-in-frostbite */
-/* Step 4 : Apply final integration on top of the scene color.
- * Note that we do the blending ourself instead of relying
- * on hardware blending which would require 2 pass. */
+/* Step 4 : Apply final integration on top of the scene color. */
uniform sampler2D inSceneDepth;
diff --git a/source/blender/draw/engines/gpencil/gpencil_draw_utils.c b/source/blender/draw/engines/gpencil/gpencil_draw_utils.c
index 97d2d3393a9..181d2efbabb 100644
--- a/source/blender/draw/engines/gpencil/gpencil_draw_utils.c
+++ b/source/blender/draw/engines/gpencil/gpencil_draw_utils.c
@@ -57,7 +57,7 @@
#define SOLID 0
#define GRADIENT 1
#define RADIAL 2
-#define CHESS 3
+#define CHECKER 3
#define TEXTURE 4
#define PATTERN 5
@@ -240,7 +240,7 @@ static void gpencil_recalc_geometry_caches(Object *ob,
if (gps->flag & GP_STROKE_RECALC_GEOMETRY) {
/* Calculate triangles cache for filling area (must be done only after changes) */
if ((gps->tot_triangles == 0) || (gps->triangles == NULL)) {
- if ((gps->totpoints > 2) &&
+ if ((gps->totpoints > 2) && (gp_style->flag & GP_STYLE_FILL_SHOW) &&
((gp_style->fill_rgba[3] > GPENCIL_ALPHA_OPACITY_THRESH) || (gp_style->fill_style > 0) ||
(gpl->blend_mode != eGplBlendMode_Regular))) {
gpencil_triangulate_stroke_fill(ob, gps);
@@ -387,8 +387,8 @@ static DRWShadingGroup *gpencil_shgroup_fill_create(GPENCIL_Data *vedata,
stl->shgroups[id].fill_style = RADIAL;
}
break;
- case GP_STYLE_FILL_STYLE_CHESSBOARD:
- stl->shgroups[id].fill_style = CHESS;
+ case GP_STYLE_FILL_STYLE_CHECKER:
+ stl->shgroups[id].fill_style = CHECKER;
break;
case GP_STYLE_FILL_STYLE_TEXTURE:
if (gp_style->flag & GP_STYLE_FILL_PATTERN) {
diff --git a/source/blender/draw/engines/gpencil/gpencil_engine.c b/source/blender/draw/engines/gpencil/gpencil_engine.c
index 646fb359836..408c9759682 100644
--- a/source/blender/draw/engines/gpencil/gpencil_engine.c
+++ b/source/blender/draw/engines/gpencil/gpencil_engine.c
@@ -789,8 +789,11 @@ static void gpencil_prepare_fast_drawing(GPENCIL_StorageList *stl,
}
}
-static void gpencil_free_runtime_data(GPENCIL_StorageList *stl)
+void DRW_gpencil_free_runtime_data(void *ved)
{
+ GPENCIL_Data *vedata = (GPENCIL_Data *)ved;
+ GPENCIL_StorageList *stl = ((GPENCIL_Data *)vedata)->stl;
+
/* free gpu data */
DRW_TEXTURE_FREE_SAFE(stl->g_data->gpencil_blank_texture);
@@ -976,8 +979,6 @@ void GPENCIL_draw_scene(void *ved)
/* if the draw is for select, do a basic drawing and return */
if (DRW_state_is_select() || DRW_state_is_depth()) {
drw_gpencil_select_render(stl, psl);
- /* free memory */
- gpencil_free_runtime_data(stl);
return;
}
@@ -1010,7 +1011,7 @@ void GPENCIL_draw_scene(void *ved)
}
/* free memory */
- gpencil_free_runtime_data(stl);
+ DRW_gpencil_free_runtime_data(ved);
return;
}
@@ -1161,7 +1162,7 @@ void GPENCIL_draw_scene(void *ved)
}
}
/* free memory */
- gpencil_free_runtime_data(stl);
+ DRW_gpencil_free_runtime_data(ved);
/* reset */
if (DRW_state_is_fbo()) {
diff --git a/source/blender/draw/engines/gpencil/gpencil_engine.h b/source/blender/draw/engines/gpencil/gpencil_engine.h
index ee1ba805fad..14615a19760 100644
--- a/source/blender/draw/engines/gpencil/gpencil_engine.h
+++ b/source/blender/draw/engines/gpencil/gpencil_engine.h
@@ -363,12 +363,12 @@ typedef struct GpencilBatchCacheElem {
} GpencilBatchCacheElem;
typedef struct GpencilBatchGroup {
- bGPDlayer *gpl; /* reference to original layer */
- bGPDframe *gpf; /* reference to original frame */
- bGPDstroke *gps; /* reference to original stroke */
- short type; /* type of element */
- bool onion; /* the group is part of onion skin */
- int vertex_idx; /* index of vertex data */
+ struct bGPDlayer *gpl; /* reference to original layer */
+ struct bGPDframe *gpf; /* reference to original frame */
+ struct bGPDstroke *gps; /* reference to original stroke */
+ short type; /* type of element */
+ bool onion; /* the group is part of onion skin */
+ int vertex_idx; /* index of vertex data */
} GpencilBatchGroup;
typedef enum GpencilBatchGroup_Type {
@@ -511,6 +511,10 @@ void GPENCIL_render_to_image(void *vedata,
struct RenderLayer *render_layer,
const rcti *rect);
+/* TODO: GPXX workaround function to call free memory from draw manager while draw manager support
+ * scene finish callback. */
+void DRW_gpencil_free_runtime_data(void *ved);
+
/* Use of multisample framebuffers. */
#define MULTISAMPLE_GP_SYNC_ENABLE(lvl, fbl) \
{ \
diff --git a/source/blender/draw/engines/gpencil/gpencil_render.c b/source/blender/draw/engines/gpencil/gpencil_render.c
index faef95fe1a9..56ba90067cf 100644
--- a/source/blender/draw/engines/gpencil/gpencil_render.c
+++ b/source/blender/draw/engines/gpencil/gpencil_render.c
@@ -103,12 +103,9 @@ void GPENCIL_render_init(GPENCIL_Data *ved, RenderEngine *engine, struct Depsgra
invert_m4_m4(viewmat, viewinv);
- /* Reuse the view created by EEVEE or Workbench */
- if (DRW_view_default_get() == NULL) {
- DRWView *view = DRW_view_create(viewmat, winmat, NULL, NULL, NULL);
- DRW_view_default_set(view);
- DRW_view_set_active(view);
- }
+ DRWView *view = DRW_view_create(viewmat, winmat, NULL, NULL, NULL);
+ DRW_view_default_set(view);
+ DRW_view_set_active(view);
DRW_view_persmat_get(NULL, persmat, false);
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 87bf116ff89..64bb70f2a3f 100644
--- a/source/blender/draw/engines/gpencil/shaders/gpencil_fill_frag.glsl
+++ b/source/blender/draw/engines/gpencil/shaders/gpencil_fill_frag.glsl
@@ -30,7 +30,7 @@ uniform vec4 wire_color;
#define SOLID 0
#define GRADIENT 1
#define RADIAL 2
-#define CHESS 3
+#define CHECKER 3
#define TEXTURE 4
#define PATTERN 5
@@ -103,7 +103,7 @@ void main()
texture_read_as_srgb(
myTexture, myTexturePremultiplied, 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;
+ vec4 checker_color;
/* wireframe with x-ray discard */
if ((viewport_xray == 1) && (shading_type[0] == OB_WIRE)) {
@@ -152,18 +152,18 @@ void main()
texture_flip,
fragColor);
}
- /* chessboard */
- if (fill_type == CHESS) {
+ /* Checkerboard */
+ if (fill_type == CHECKER) {
vec2 pos = rot / pattern_gridsize;
if ((fract(pos.x) < 0.5 && fract(pos.y) < 0.5) ||
(fract(pos.x) > 0.5 && fract(pos.y) > 0.5)) {
- chesscolor = (texture_flip == 0) ? finalColor : color2;
+ checker_color = (texture_flip == 0) ? finalColor : color2;
}
else {
- chesscolor = (texture_flip == 0) ? color2 : finalColor;
+ checker_color = (texture_flip == 0) ? color2 : finalColor;
}
/* mix with texture */
- fragColor = (texture_mix == 1) ? mix(chesscolor, text_color, mix_factor) : chesscolor;
+ fragColor = (texture_mix == 1) ? mix(checker_color, text_color, mix_factor) : checker_color;
fragColor.a *= layer_opacity;
}
/* texture */
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 7872c1380ed..7eb12dbdeb9 100644
--- a/source/blender/draw/engines/workbench/shaders/workbench_prepass_vert.glsl
+++ b/source/blender/draw/engines/workbench/shaders/workbench_prepass_vert.glsl
@@ -2,14 +2,14 @@
#ifndef HAIR_SHADER
in vec3 pos;
in vec3 nor;
-in vec2 u; /* active texture layer */
+in vec2 au; /* active texture layer */
# ifdef V3D_SHADING_VERTEX_COLOR
-in vec3 c; /* active color */
+in vec3 ac; /* active color */
# endif
-# define uv u
+# define uv au
#else /* HAIR_SHADER */
# ifdef V3D_SHADING_TEXTURE_COLOR
-uniform samplerBuffer u; /* active texture layer */
+uniform samplerBuffer au; /* active texture layer */
# endif
flat out float hair_rand;
#endif /* HAIR_SHADER */
@@ -58,7 +58,7 @@ void main()
{
#ifdef HAIR_SHADER
# ifdef V3D_SHADING_TEXTURE_COLOR
- vec2 uv = hair_get_customdata_vec2(u);
+ vec2 uv = hair_get_customdata_vec2(au);
# endif
float time, thick_time, thickness;
vec3 world_pos, tan, binor;
@@ -86,7 +86,7 @@ void main()
#ifdef V3D_SHADING_VERTEX_COLOR
# ifndef HAIR_SHADER
- vertexColor = srgb_to_linear_attr(c);
+ vertexColor = srgb_to_linear_attr(ac);
# endif
#endif
diff --git a/source/blender/draw/engines/workbench/shaders/workbench_shadow_geom.glsl b/source/blender/draw/engines/workbench/shaders/workbench_shadow_geom.glsl
index 8ee70c37949..2c9190bfcf4 100644
--- a/source/blender/draw/engines/workbench/shaders/workbench_shadow_geom.glsl
+++ b/source/blender/draw/engines/workbench/shaders/workbench_shadow_geom.glsl
@@ -37,6 +37,7 @@ in VertexData
vData[];
#define DEGENERATE_TRIS_WORKAROUND
+#define DEGENERATE_TRIS_AREA_THRESHOLD 4e-17
#define len_sqr(a) dot(a, a)
@@ -67,7 +68,7 @@ void main()
#ifdef DEGENERATE_TRIS_WORKAROUND
/* Check if area is null */
vec2 faces_area = vec2(len_sqr(n1), len_sqr(n2));
- bvec2 degen_faces = equal(abs(faces_area), vec2(0.0));
+ bvec2 degen_faces = lessThan(abs(faces_area), vec2(DEGENERATE_TRIS_AREA_THRESHOLD));
/* Both triangles are degenerate, abort. */
if (all(degen_faces)) {
diff --git a/source/blender/draw/engines/workbench/workbench_data.c b/source/blender/draw/engines/workbench/workbench_data.c
index 04e1255521f..743a1fc42b6 100644
--- a/source/blender/draw/engines/workbench/workbench_data.c
+++ b/source/blender/draw/engines/workbench/workbench_data.c
@@ -24,6 +24,8 @@
#include "DNA_userdef_types.h"
+#include "ED_view3d.h"
+
#include "UI_resources.h"
#include "GPU_batch.h"
@@ -43,16 +45,14 @@ void workbench_private_data_init(WORKBENCH_PrivateData *wpd)
wpd->preferences = &U;
View3D *v3d = draw_ctx->v3d;
- if (!v3d) {
- wpd->shading = scene->display.shading;
- wpd->use_color_render_settings = true;
- }
- else if (v3d->shading.type == OB_RENDER && BKE_scene_uses_blender_workbench(scene)) {
+ if (!v3d || (v3d->shading.type == OB_RENDER && BKE_scene_uses_blender_workbench(scene))) {
wpd->shading = scene->display.shading;
+ wpd->shading.xray_alpha = XRAY_ALPHA((&scene->display));
wpd->use_color_render_settings = true;
}
else {
wpd->shading = v3d->shading;
+ wpd->shading.xray_alpha = XRAY_ALPHA(v3d);
wpd->use_color_render_settings = false;
}
diff --git a/source/blender/draw/engines/workbench/workbench_deferred.c b/source/blender/draw/engines/workbench/workbench_deferred.c
index 49b84b41744..735a0dcf7a0 100644
--- a/source/blender/draw/engines/workbench/workbench_deferred.c
+++ b/source/blender/draw/engines/workbench/workbench_deferred.c
@@ -215,13 +215,16 @@ static GPUShader *workbench_cavity_shader_get(bool cavity, bool curvature)
static GPUShader *ensure_deferred_prepass_shader(WORKBENCH_PrivateData *wpd,
bool is_uniform_color,
bool is_hair,
+ bool is_texture_painting,
eGPUShaderConfig sh_cfg)
{
WORKBENCH_DEFERRED_Shaders *sh_data = &e_data.sh_data[sh_cfg];
- int index = workbench_material_get_prepass_shader_index(wpd, is_uniform_color, is_hair);
+ int index = workbench_material_get_prepass_shader_index(
+ wpd, is_uniform_color, is_hair, is_texture_painting);
if (sh_data->prepass_sh_cache[index] == NULL) {
const GPUShaderConfigData *sh_cfg_data = &GPU_shader_cfg_data[sh_cfg];
- char *defines = workbench_material_build_defines(wpd, is_uniform_color, is_hair);
+ char *defines = workbench_material_build_defines(
+ wpd, is_uniform_color, is_hair, is_texture_painting);
char *prepass_vert = workbench_build_prepass_vert(is_hair);
char *prepass_frag = workbench_build_prepass_frag();
sh_data->prepass_sh_cache[index] = GPU_shader_create_from_arrays({
@@ -240,7 +243,7 @@ static GPUShader *ensure_deferred_composite_shader(WORKBENCH_PrivateData *wpd)
{
int index = workbench_material_get_composite_shader_index(wpd);
if (e_data.composite_sh_cache[index] == NULL) {
- char *defines = workbench_material_build_defines(wpd, false, false);
+ char *defines = workbench_material_build_defines(wpd, false, false, false);
char *composite_frag = workbench_build_composite_frag(wpd);
e_data.composite_sh_cache[index] = DRW_shader_create_fullscreen(composite_frag, defines);
MEM_freeN(composite_frag);
@@ -267,10 +270,11 @@ static GPUShader *ensure_background_shader(WORKBENCH_PrivateData *wpd)
static void select_deferred_shaders(WORKBENCH_PrivateData *wpd, eGPUShaderConfig sh_cfg)
{
- wpd->prepass_sh = ensure_deferred_prepass_shader(wpd, false, false, sh_cfg);
- wpd->prepass_hair_sh = ensure_deferred_prepass_shader(wpd, false, true, sh_cfg);
- wpd->prepass_uniform_sh = ensure_deferred_prepass_shader(wpd, true, false, sh_cfg);
- wpd->prepass_uniform_hair_sh = ensure_deferred_prepass_shader(wpd, true, true, sh_cfg);
+ wpd->prepass_sh = ensure_deferred_prepass_shader(wpd, false, false, false, sh_cfg);
+ wpd->prepass_hair_sh = ensure_deferred_prepass_shader(wpd, false, true, false, sh_cfg);
+ wpd->prepass_uniform_sh = ensure_deferred_prepass_shader(wpd, true, false, false, sh_cfg);
+ wpd->prepass_uniform_hair_sh = ensure_deferred_prepass_shader(wpd, true, true, false, sh_cfg);
+ wpd->prepass_textured_sh = ensure_deferred_prepass_shader(wpd, false, false, true, sh_cfg);
wpd->composite_sh = ensure_deferred_composite_shader(wpd);
wpd->background_sh = ensure_background_shader(wpd);
}
@@ -451,6 +455,8 @@ void workbench_deferred_engine_init(WORKBENCH_Data *vedata)
WORKBENCH_PrivateData *wpd = stl->g_data;
workbench_private_data_init(wpd);
+ wpd->shading.xray_alpha = 1.0f;
+
workbench_dof_engine_init(vedata, camera);
if (OIT_ENABLED(wpd)) {
@@ -481,7 +487,7 @@ void workbench_deferred_engine_init(WORKBENCH_Data *vedata)
e_data.composite_buffer_tx = DRW_texture_pool_query_2d(
size[0], size[1], comp_tex_format, &draw_engine_workbench_solid);
- if (MATDATA_PASS_ENABLED(wpd) || GPU_unused_fb_slot_workaround()) {
+ if (workbench_is_matdata_pass_enabled(wpd) || GPU_unused_fb_slot_workaround()) {
e_data.color_buffer_tx = DRW_texture_pool_query_2d(
size[0], size[1], col_tex_format, &draw_engine_workbench_solid);
}
@@ -521,7 +527,7 @@ void workbench_deferred_engine_init(WORKBENCH_Data *vedata)
GPU_ATTACHMENT_TEXTURE(e_data.composite_buffer_tx),
});
- if (!MATDATA_PASS_ENABLED(wpd) && !GPU_unused_fb_slot_workaround()) {
+ if (!workbench_is_matdata_pass_enabled(wpd) && !GPU_unused_fb_slot_workaround()) {
e_data.color_buffer_tx = DRW_texture_pool_query_2d(
size[0], size[1], col_tex_format, &draw_engine_workbench_solid);
}
@@ -673,7 +679,7 @@ void workbench_deferred_engine_free(void)
static void workbench_composite_uniforms(WORKBENCH_PrivateData *wpd, DRWShadingGroup *grp)
{
DRW_shgroup_uniform_block(grp, "world_block", wpd->world_ubo);
- if (MATDATA_PASS_ENABLED(wpd)) {
+ if (workbench_is_matdata_pass_enabled(wpd)) {
DRW_shgroup_uniform_texture_ref(grp, "materialBuffer", &e_data.color_buffer_tx);
}
else {
@@ -712,7 +718,6 @@ void workbench_deferred_cache_init(WORKBENCH_Data *vedata)
Scene *scene = draw_ctx->scene;
workbench_volume_cache_init(vedata);
-
select_deferred_shaders(wpd, draw_ctx->sh_cfg);
/* Background Pass */
@@ -867,7 +872,7 @@ static WORKBENCH_MaterialData *get_or_create_material_data(WORKBENCH_Data *vedat
const bool is_ghost = (ob->dtx & OB_DRAWXRAY);
/* Solid */
- workbench_material_update_data(wpd, ob, mat, &material_template);
+ workbench_material_update_data(wpd, ob, mat, &material_template, color_type);
material_template.object_id = OBJECT_ID_PASS_ENABLED(wpd) ? engine_object_data->object_id : 1;
material_template.color_type = color_type;
material_template.ima = ima;
@@ -878,9 +883,14 @@ static WORKBENCH_MaterialData *get_or_create_material_data(WORKBENCH_Data *vedat
material = BLI_ghash_lookup(wpd->material_hash, POINTER_FROM_UINT(hash));
if (material == NULL) {
material = MEM_mallocN(sizeof(WORKBENCH_MaterialData), __func__);
+ /* select the correct prepass shader */
+ GPUShader *shader = (wpd->shading.color_type == color_type) ? wpd->prepass_sh :
+ wpd->prepass_uniform_sh;
+ if (color_type == V3D_SHADING_TEXTURE_COLOR) {
+ shader = wpd->prepass_textured_sh;
+ }
material->shgrp = DRW_shgroup_create(
- (wpd->shading.color_type == color_type) ? wpd->prepass_sh : wpd->prepass_uniform_sh,
- (ob->dtx & OB_DRAWXRAY) ? psl->ghost_prepass_pass : psl->prepass_pass);
+ shader, (ob->dtx & OB_DRAWXRAY) ? psl->ghost_prepass_pass : psl->prepass_pass);
workbench_material_copy(material, &material_template);
DRW_shgroup_stencil_mask(material->shgrp, (ob->dtx & OB_DRAWXRAY) ? 0x00 : 0xFF);
DRW_shgroup_uniform_int(material->shgrp, "object_id", &material->object_id, 1);
@@ -933,6 +943,49 @@ static void workbench_cache_populate_particles(WORKBENCH_Data *vedata, Object *o
}
}
+static void workbench_cache_populate_texture_paint_mode(WORKBENCH_Data *vedata, Object *ob)
+{
+ WORKBENCH_StorageList *stl = vedata->stl;
+ WORKBENCH_PrivateData *wpd = stl->g_data;
+ const DRWContextState *draw_ctx = DRW_context_state_get();
+
+ Scene *scene = draw_ctx->scene;
+ const bool use_sculpt_pbvh = BKE_sculptsession_use_pbvh_draw(ob, draw_ctx->v3d);
+ WORKBENCH_MaterialData *material;
+
+ /* Force workbench to render active object textured when in texture paint mode */
+ const ImagePaintSettings *imapaint = &scene->toolsettings->imapaint;
+
+ /* Single Image mode */
+ if (imapaint->mode == IMAGEPAINT_MODE_IMAGE) {
+ Image *image = imapaint->canvas;
+ int interp = (imapaint->interp == IMAGEPAINT_INTERP_LINEAR) ? SHD_INTERP_LINEAR :
+ SHD_INTERP_CLOSEST;
+ int color_type = workbench_material_determine_color_type(wpd, image, ob, use_sculpt_pbvh);
+ struct GPUBatch *geom = DRW_cache_mesh_surface_texpaint_single_get(ob);
+ material = get_or_create_material_data(vedata, ob, NULL, image, NULL, color_type, interp);
+
+ DRW_shgroup_call(material->shgrp, geom, ob);
+ }
+ else {
+ /* IMAGEPAINT_MODE_MATERIAL */
+ const int materials_len = MAX2(1, ob->totcol);
+ struct GPUBatch **geom_array = DRW_cache_mesh_surface_texpaint_get(ob);
+ for (int i = 0; i < materials_len; i++) {
+ if (geom_array != NULL && geom_array[i] != NULL) {
+ 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, use_sculpt_pbvh);
+ material = get_or_create_material_data(vedata, ob, mat, image, iuser, color_type, interp);
+ DRW_shgroup_call(material->shgrp, geom_array[i], ob);
+ }
+ }
+ }
+}
+
void workbench_deferred_solid_cache_populate(WORKBENCH_Data *vedata, Object *ob)
{
WORKBENCH_StorageList *stl = vedata->stl;
@@ -961,7 +1014,7 @@ void workbench_deferred_solid_cache_populate(WORKBENCH_Data *vedata, Object *ob)
if (!(DRW_object_visibility_in_active_context(ob) & OB_VISIBLE_SELF)) {
return;
}
- if ((ob->dt < OB_SOLID) && !DRW_state_is_image_render()) {
+ if ((ob->dt < OB_SOLID) && !DRW_state_is_scene_render()) {
return;
}
@@ -973,8 +1026,15 @@ void workbench_deferred_solid_cache_populate(WORKBENCH_Data *vedata, Object *ob)
const int materials_len = MAX2(1, ob->totcol);
const Mesh *me = (ob->type == OB_MESH) ? ob->data : NULL;
bool has_transp_mat = false;
+ const bool use_texture_paint_drawing = !(DRW_state_is_image_render() &&
+ draw_ctx->v3d == NULL) &&
+ workbench_is_object_in_texture_paint_mode(ob) && me &&
+ me->mloopuv;
- if (!use_sculpt_pbvh && TEXTURE_DRAWING_ENABLED(wpd) && me && me->mloopuv) {
+ if (use_texture_paint_drawing) {
+ workbench_cache_populate_texture_paint_mode(vedata, ob);
+ }
+ else if (!use_sculpt_pbvh && 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++) {
@@ -987,10 +1047,8 @@ void workbench_deferred_solid_cache_populate(WORKBENCH_Data *vedata, Object *ob)
int color_type = workbench_material_determine_color_type(
wpd, image, ob, use_sculpt_pbvh);
if (color_type == V3D_SHADING_MATERIAL_COLOR && mat && mat->a < 1.0) {
- /* Hack */
- wpd->shading.xray_alpha = mat->a;
material = workbench_forward_get_or_create_material_data(
- vedata, ob, mat, image, iuser, color_type, 0, use_sculpt_pbvh);
+ vedata, ob, mat, image, iuser, color_type, 0);
has_transp_mat = true;
}
else {
@@ -1009,10 +1067,8 @@ void workbench_deferred_solid_cache_populate(WORKBENCH_Data *vedata, Object *ob)
int color_type = workbench_material_determine_color_type(wpd, NULL, ob, use_sculpt_pbvh);
if ((ob->color[3] < 1.0f) && (color_type == V3D_SHADING_OBJECT_COLOR)) {
- /* Hack */
- wpd->shading.xray_alpha = ob->color[3];
material = workbench_forward_get_or_create_material_data(
- vedata, ob, NULL, NULL, NULL, color_type, 0, use_sculpt_pbvh);
+ vedata, ob, NULL, NULL, NULL, color_type, 0);
has_transp_mat = true;
}
else {
@@ -1046,10 +1102,8 @@ void workbench_deferred_solid_cache_populate(WORKBENCH_Data *vedata, Object *ob)
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, use_sculpt_pbvh);
+ vedata, ob, mat, NULL, NULL, V3D_SHADING_MATERIAL_COLOR, 0);
has_transp_mat = true;
}
else {
@@ -1071,10 +1125,8 @@ void workbench_deferred_solid_cache_populate(WORKBENCH_Data *vedata, Object *ob)
if (geoms != NULL && geoms[i] != NULL) {
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, use_sculpt_pbvh);
+ vedata, ob, mat, NULL, NULL, V3D_SHADING_MATERIAL_COLOR, 0);
has_transp_mat = true;
}
else {
diff --git a/source/blender/draw/engines/workbench/workbench_effect_dof.c b/source/blender/draw/engines/workbench/workbench_effect_dof.c
index 69d0500f155..22840a2a756 100644
--- a/source/blender/draw/engines/workbench/workbench_effect_dof.c
+++ b/source/blender/draw/engines/workbench/workbench_effect_dof.c
@@ -173,7 +173,7 @@ void workbench_dof_engine_init(WORKBENCH_Data *vedata, Object *camera)
}
const float *full_size = DRW_viewport_size_get();
- int size[2] = {full_size[0] / 2, full_size[1] / 2};
+ int size[2] = {max_ii(1, (int)full_size[0] / 2), max_ii(1, (int)full_size[1] / 2)};
#if 0
/* NOTE: We Ceil here in order to not miss any edge texel if using a NPO2 texture. */
int shrink_h_size[2] = {ceilf(size[0] / 8.0f), size[1]};
diff --git a/source/blender/draw/engines/workbench/workbench_forward.c b/source/blender/draw/engines/workbench/workbench_forward.c
index 612a3901ca0..4c1fce550e8 100644
--- a/source/blender/draw/engines/workbench/workbench_forward.c
+++ b/source/blender/draw/engines/workbench/workbench_forward.c
@@ -141,8 +141,7 @@ WORKBENCH_MaterialData *workbench_forward_get_or_create_material_data(WORKBENCH_
Image *ima,
ImageUser *iuser,
int color_type,
- int interp,
- bool use_sculpt_pbvh)
+ int interp)
{
const DRWContextState *draw_ctx = DRW_context_state_get();
WORKBENCH_FORWARD_Shaders *sh_data = &e_data.sh_data[draw_ctx->sh_cfg];
@@ -160,7 +159,7 @@ WORKBENCH_MaterialData *workbench_forward_get_or_create_material_data(WORKBENCH_
DRWShadingGroup *grp;
/* Solid */
- workbench_material_update_data(wpd, ob, mat, &material_template);
+ workbench_material_update_data(wpd, ob, mat, &material_template, color_type);
material_template.object_id = OBJECT_ID_PASS_ENABLED(wpd) ? engine_object_data->object_id : 1;
material_template.color_type = color_type;
material_template.ima = ima;
@@ -173,12 +172,17 @@ WORKBENCH_MaterialData *workbench_forward_get_or_create_material_data(WORKBENCH_
material = MEM_mallocN(sizeof(WORKBENCH_MaterialData), __func__);
/* transparent accum */
- grp = DRW_shgroup_create(wpd->shading.color_type == color_type ?
- wpd->transparent_accum_sh :
- wpd->transparent_accum_uniform_sh,
- psl->transparent_accum_pass);
+ /* select the correct transparent accum shader */
+ GPUShader *shader = (wpd->shading.color_type == color_type) ?
+ wpd->transparent_accum_sh :
+ wpd->transparent_accum_uniform_sh;
+ if (color_type == V3D_SHADING_TEXTURE_COLOR) {
+ shader = wpd->transparent_accum_textured_sh;
+ }
+
+ grp = DRW_shgroup_create(shader, psl->transparent_accum_pass);
DRW_shgroup_uniform_block(grp, "world_block", wpd->world_ubo);
- DRW_shgroup_uniform_float_copy(grp, "alpha", wpd->shading.xray_alpha);
+ DRW_shgroup_uniform_float_copy(grp, "alpha", material_template.alpha);
DRW_shgroup_uniform_vec4(grp, "viewvecs[0]", (float *)wpd->viewvecs, 3);
workbench_material_copy(material, &material_template);
if (STUDIOLIGHT_TYPE_MATCAP_ENABLED(wpd)) {
@@ -199,8 +203,7 @@ WORKBENCH_MaterialData *workbench_forward_get_or_create_material_data(WORKBENCH_
material->shgrp = grp;
/* Depth */
- if (workbench_material_determine_color_type(wpd, material->ima, ob, use_sculpt_pbvh) ==
- V3D_SHADING_TEXTURE_COLOR) {
+ if (color_type == 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);
@@ -223,13 +226,16 @@ WORKBENCH_MaterialData *workbench_forward_get_or_create_material_data(WORKBENCH_
static GPUShader *ensure_forward_accum_shaders(WORKBENCH_PrivateData *wpd,
bool is_uniform_color,
bool is_hair,
+ bool is_texture_painting,
eGPUShaderConfig sh_cfg)
{
WORKBENCH_FORWARD_Shaders *sh_data = &e_data.sh_data[sh_cfg];
- int index = workbench_material_get_accum_shader_index(wpd, is_uniform_color, is_hair);
+ int index = workbench_material_get_accum_shader_index(
+ wpd, is_uniform_color, is_hair, is_texture_painting);
if (sh_data->transparent_accum_sh_cache[index] == NULL) {
const GPUShaderConfigData *sh_cfg_data = &GPU_shader_cfg_data[sh_cfg];
- char *defines = workbench_material_build_defines(wpd, is_uniform_color, is_hair);
+ char *defines = workbench_material_build_defines(
+ wpd, is_uniform_color, is_hair, is_texture_painting);
char *transparent_accum_vert = workbench_build_forward_vert(is_hair);
char *transparent_accum_frag = workbench_build_forward_transparent_accum_frag();
sh_data->transparent_accum_sh_cache[index] = GPU_shader_create_from_arrays({
@@ -248,7 +254,7 @@ static GPUShader *ensure_forward_composite_shaders(WORKBENCH_PrivateData *wpd)
{
int index = OBJECT_OUTLINE_ENABLED(wpd) ? 1 : 0;
if (e_data.composite_sh_cache[index] == NULL) {
- char *defines = workbench_material_build_defines(wpd, false, false);
+ char *defines = workbench_material_build_defines(wpd, false, false, false);
char *composite_frag = workbench_build_forward_composite_frag();
e_data.composite_sh_cache[index] = DRW_shader_create_fullscreen(composite_frag, defines);
MEM_freeN(composite_frag);
@@ -260,10 +266,14 @@ static GPUShader *ensure_forward_composite_shaders(WORKBENCH_PrivateData *wpd)
void workbench_forward_choose_shaders(WORKBENCH_PrivateData *wpd, eGPUShaderConfig sh_cfg)
{
wpd->composite_sh = ensure_forward_composite_shaders(wpd);
- wpd->transparent_accum_sh = ensure_forward_accum_shaders(wpd, false, false, sh_cfg);
- wpd->transparent_accum_hair_sh = ensure_forward_accum_shaders(wpd, false, true, sh_cfg);
- wpd->transparent_accum_uniform_sh = ensure_forward_accum_shaders(wpd, true, false, sh_cfg);
- wpd->transparent_accum_uniform_hair_sh = ensure_forward_accum_shaders(wpd, true, true, sh_cfg);
+ wpd->transparent_accum_sh = ensure_forward_accum_shaders(wpd, false, false, false, sh_cfg);
+ wpd->transparent_accum_hair_sh = ensure_forward_accum_shaders(wpd, false, true, false, sh_cfg);
+ wpd->transparent_accum_uniform_sh = ensure_forward_accum_shaders(
+ wpd, true, false, false, sh_cfg);
+ wpd->transparent_accum_uniform_hair_sh = ensure_forward_accum_shaders(
+ wpd, true, true, false, sh_cfg);
+ wpd->transparent_accum_textured_sh = ensure_forward_accum_shaders(
+ wpd, false, false, true, sh_cfg);
}
void workbench_forward_outline_shaders_ensure(WORKBENCH_PrivateData *wpd, eGPUShaderConfig sh_cfg)
@@ -272,9 +282,9 @@ void workbench_forward_outline_shaders_ensure(WORKBENCH_PrivateData *wpd, eGPUSh
if (sh_data->object_outline_sh == NULL) {
const GPUShaderConfigData *sh_cfg_data = &GPU_shader_cfg_data[sh_cfg];
- char *defines = workbench_material_build_defines(wpd, false, false);
- char *defines_texture = workbench_material_build_defines(wpd, true, false);
- char *defines_hair = workbench_material_build_defines(wpd, false, true);
+ char *defines = workbench_material_build_defines(wpd, false, false, false);
+ char *defines_texture = workbench_material_build_defines(wpd, true, false, false);
+ char *defines_hair = workbench_material_build_defines(wpd, false, true, false);
char *forward_vert = workbench_build_forward_vert(false);
char *forward_hair_vert = workbench_build_forward_vert(true);
@@ -503,7 +513,7 @@ static void workbench_forward_cache_populate_particles(WORKBENCH_Data *vedata, O
workbench_material_get_image_and_mat(ob, part->omat, &image, &iuser, &interp, &mat);
int color_type = workbench_material_determine_color_type(wpd, image, ob, false);
WORKBENCH_MaterialData *material = workbench_forward_get_or_create_material_data(
- vedata, ob, mat, image, iuser, color_type, interp, false);
+ vedata, ob, mat, image, iuser, color_type, interp);
struct GPUShader *shader = (wpd->shading.color_type == color_type) ?
wpd->transparent_accum_hair_sh :
@@ -533,6 +543,53 @@ static void workbench_forward_cache_populate_particles(WORKBENCH_Data *vedata, O
}
}
}
+static void workbench_forward_cache_populate_texture_paint_mode(WORKBENCH_Data *vedata, Object *ob)
+{
+ WORKBENCH_StorageList *stl = vedata->stl;
+ WORKBENCH_PrivateData *wpd = stl->g_data;
+ const DRWContextState *draw_ctx = DRW_context_state_get();
+
+ Scene *scene = draw_ctx->scene;
+ const bool use_sculpt_pbvh = BKE_sculptsession_use_pbvh_draw(ob, draw_ctx->v3d);
+ WORKBENCH_MaterialData *material;
+
+ /* Force workbench to render active object textured when in texture paint mode */
+ const ImagePaintSettings *imapaint = &scene->toolsettings->imapaint;
+
+ /* Single Image mode */
+ if (imapaint->mode == IMAGEPAINT_MODE_IMAGE) {
+ Image *image = imapaint->canvas;
+ int interp = (imapaint->interp == IMAGEPAINT_INTERP_LINEAR) ? SHD_INTERP_LINEAR :
+ SHD_INTERP_CLOSEST;
+ int color_type = workbench_material_determine_color_type(wpd, image, ob, use_sculpt_pbvh);
+ struct GPUBatch *geom = DRW_cache_mesh_surface_texpaint_single_get(ob);
+ material = workbench_forward_get_or_create_material_data(
+ vedata, ob, NULL, image, NULL, color_type, interp);
+
+ DRW_shgroup_call(material->shgrp, geom, ob);
+ DRW_shgroup_call(material->shgrp_object_outline, geom, ob);
+ }
+ else {
+ /* IMAGEPAINT_MODE_MATERIAL */
+ const int materials_len = MAX2(1, ob->totcol);
+ struct GPUBatch **geom_array = DRW_cache_mesh_surface_texpaint_get(ob);
+ for (int i = 0; i < materials_len; i++) {
+ if (geom_array != NULL && geom_array[i] != NULL) {
+ 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, use_sculpt_pbvh);
+ material = workbench_forward_get_or_create_material_data(
+ vedata, ob, mat, image, iuser, color_type, interp);
+
+ DRW_shgroup_call(material->shgrp, geom_array[i], ob);
+ DRW_shgroup_call(material->shgrp_object_outline, geom_array[i], ob);
+ }
+ }
+ }
+}
void workbench_forward_cache_populate(WORKBENCH_Data *vedata, Object *ob)
{
@@ -571,8 +628,15 @@ void workbench_forward_cache_populate(WORKBENCH_Data *vedata, Object *ob)
const bool use_sculpt_pbvh = BKE_sculptsession_use_pbvh_draw(ob, draw_ctx->v3d);
const int materials_len = MAX2(1, ob->totcol);
const Mesh *me = (ob->type == OB_MESH) ? ob->data : NULL;
+ const bool use_texture_paint_drawing = !(DRW_state_is_image_render() &&
+ draw_ctx->v3d == NULL) &&
+ workbench_is_object_in_texture_paint_mode(ob) && me &&
+ me->mloopuv;
- if (!use_sculpt_pbvh && TEXTURE_DRAWING_ENABLED(wpd) && me && me->mloopuv) {
+ if (use_texture_paint_drawing) {
+ workbench_forward_cache_populate_texture_paint_mode(vedata, ob);
+ }
+ else if (!use_sculpt_pbvh && 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;
@@ -582,7 +646,7 @@ void workbench_forward_cache_populate(WORKBENCH_Data *vedata, Object *ob)
workbench_material_get_image_and_mat(ob, i + 1, &image, &iuser, &interp, &mat);
int color_type = workbench_material_determine_color_type(wpd, image, ob, use_sculpt_pbvh);
material = workbench_forward_get_or_create_material_data(
- vedata, ob, mat, image, iuser, color_type, interp, use_sculpt_pbvh);
+ vedata, ob, mat, image, iuser, color_type, interp);
DRW_shgroup_call(material->shgrp_object_outline, geom_array[i], ob);
DRW_shgroup_call(material->shgrp, geom_array[i], ob);
}
@@ -597,7 +661,7 @@ void workbench_forward_cache_populate(WORKBENCH_Data *vedata, Object *ob)
if (use_sculpt_pbvh) {
material = workbench_forward_get_or_create_material_data(
- vedata, ob, NULL, NULL, NULL, color_type, 0, use_sculpt_pbvh);
+ vedata, ob, NULL, NULL, NULL, color_type, 0);
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);
@@ -611,7 +675,7 @@ void workbench_forward_cache_populate(WORKBENCH_Data *vedata, Object *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, use_sculpt_pbvh);
+ vedata, ob, NULL, NULL, NULL, color_type, 0);
/* TODO(fclem) make this call optional */
DRW_shgroup_call(material->shgrp_object_outline, geom, ob);
if (!is_wire) {
@@ -628,7 +692,7 @@ void workbench_forward_cache_populate(WORKBENCH_Data *vedata, Object *ob)
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, use_sculpt_pbvh);
+ vedata, ob, mat, NULL, NULL, V3D_SHADING_MATERIAL_COLOR, 0);
shgrps[i] = material->shgrp;
}
/* TODO(fclem) make this call optional */
@@ -651,7 +715,7 @@ 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, use_sculpt_pbvh);
+ vedata, ob, mat, NULL, NULL, V3D_SHADING_MATERIAL_COLOR, 0);
/* TODO(fclem) make this call optional */
DRW_shgroup_call(material->shgrp_object_outline, mat_geom[i], ob);
if (!is_wire) {
diff --git a/source/blender/draw/engines/workbench/workbench_materials.c b/source/blender/draw/engines/workbench/workbench_materials.c
index d570fda9dac..6699a1954ba 100644
--- a/source/blender/draw/engines/workbench/workbench_materials.c
+++ b/source/blender/draw/engines/workbench/workbench_materials.c
@@ -41,23 +41,24 @@
void workbench_material_update_data(WORKBENCH_PrivateData *wpd,
Object *ob,
Material *mat,
- WORKBENCH_MaterialData *data)
+ WORKBENCH_MaterialData *data,
+ int color_type)
{
- /* When V3D_SHADING_TEXTURE_COLOR is active, use V3D_SHADING_MATERIAL_COLOR as fallback when no
- * texture could be determined */
- int color_type = wpd->shading.color_type == V3D_SHADING_TEXTURE_COLOR ?
- V3D_SHADING_MATERIAL_COLOR :
- wpd->shading.color_type;
copy_v3_fl3(data->diffuse_color, 0.8f, 0.8f, 0.8f);
copy_v3_v3(data->base_color, data->diffuse_color);
copy_v3_fl3(data->specular_color, 0.05f, 0.05f, 0.05f); /* Dielectric: 5% reflective. */
data->metallic = 0.0f;
data->roughness = 0.632455532f; /* sqrtf(0.4f); */
+ data->alpha = wpd->shading.xray_alpha;
if (color_type == V3D_SHADING_SINGLE_COLOR) {
copy_v3_v3(data->diffuse_color, wpd->shading.single_color);
copy_v3_v3(data->base_color, data->diffuse_color);
}
+ else if (color_type == V3D_SHADING_ERROR_COLOR) {
+ copy_v3_fl3(data->diffuse_color, 0.8, 0.0, 0.8);
+ copy_v3_v3(data->base_color, data->diffuse_color);
+ }
else if (color_type == V3D_SHADING_RANDOM_COLOR) {
uint hash = BLI_ghashutil_strhash_p_murmur(ob->id.name);
if (ob->id.lib) {
@@ -72,10 +73,12 @@ void workbench_material_update_data(WORKBENCH_PrivateData *wpd,
else if (ELEM(color_type, V3D_SHADING_OBJECT_COLOR, V3D_SHADING_VERTEX_COLOR)) {
copy_v3_v3(data->diffuse_color, ob->color);
copy_v3_v3(data->base_color, data->diffuse_color);
+ data->alpha *= ob->color[3];
}
else {
- /* V3D_SHADING_MATERIAL_COLOR */
+ /* V3D_SHADING_MATERIAL_COLOR or V3D_SHADING_TEXTURE_COLOR */
if (mat) {
+ data->alpha *= mat->a;
if (SPECULAR_HIGHLIGHT_ENABLED(wpd)) {
copy_v3_v3(data->base_color, &mat->r);
mul_v3_v3fl(data->diffuse_color, &mat->r, 1.0f - mat->metallic);
@@ -94,13 +97,19 @@ void workbench_material_update_data(WORKBENCH_PrivateData *wpd,
char *workbench_material_build_defines(WORKBENCH_PrivateData *wpd,
bool is_uniform_color,
- bool is_hair)
+ bool is_hair,
+ bool is_texture_painting)
{
char *str = NULL;
bool use_textures = (wpd->shading.color_type == V3D_SHADING_TEXTURE_COLOR) && !is_uniform_color;
bool use_vertex_colors = (wpd->shading.color_type == V3D_SHADING_VERTEX_COLOR) &&
!is_uniform_color;
+ if (is_texture_painting) {
+ use_textures = true;
+ use_vertex_colors = false;
+ }
+
DynStr *ds = BLI_dynstr_new();
if (wpd->shading.flag & V3D_SHADING_OBJECT_OUTLINE) {
@@ -127,7 +136,7 @@ char *workbench_material_build_defines(WORKBENCH_PrivateData *wpd,
if (OBJECT_ID_PASS_ENABLED(wpd)) {
BLI_dynstr_append(ds, "#define OBJECT_ID_PASS_ENABLED\n");
}
- if (MATDATA_PASS_ENABLED(wpd)) {
+ if (workbench_is_matdata_pass_enabled(wpd)) {
BLI_dynstr_append(ds, "#define MATDATA_PASS_ENABLED\n");
}
if (NORMAL_VIEWPORT_PASS_ENABLED(wpd)) {
@@ -169,6 +178,7 @@ uint workbench_material_get_hash(WORKBENCH_MaterialData *material_template, bool
input[3] = (uint)(material_template->roughness * 512);
result += BLI_ghashutil_uinthash_v4_murmur(input);
+ result += BLI_ghashutil_uinthash((uint)(material_template->alpha * 512));
result += BLI_ghashutil_uinthash((uint)is_ghost);
result += BLI_ghashutil_uinthash(material_template->color_type);
@@ -189,22 +199,27 @@ int workbench_material_get_composite_shader_index(WORKBENCH_PrivateData *wpd)
SET_FLAG_FROM_TEST(index, wpd->shading.flag & V3D_SHADING_SHADOW, 1 << 2);
SET_FLAG_FROM_TEST(index, wpd->shading.flag & V3D_SHADING_CAVITY, 1 << 3);
SET_FLAG_FROM_TEST(index, wpd->shading.flag & V3D_SHADING_OBJECT_OUTLINE, 1 << 4);
- SET_FLAG_FROM_TEST(index, MATDATA_PASS_ENABLED(wpd), 1 << 5);
+ SET_FLAG_FROM_TEST(index, workbench_is_matdata_pass_enabled(wpd), 1 << 5);
BLI_assert(index < MAX_COMPOSITE_SHADERS);
return index;
}
int workbench_material_get_prepass_shader_index(WORKBENCH_PrivateData *wpd,
bool is_uniform_color,
- bool is_hair)
+ bool is_hair,
+ bool is_texture_painting)
{
bool use_textures = (wpd->shading.color_type == V3D_SHADING_TEXTURE_COLOR) && !is_uniform_color;
bool use_vertex_colors = (wpd->shading.color_type == V3D_SHADING_VERTEX_COLOR) &&
!is_uniform_color;
+ if (is_texture_painting) {
+ use_textures = true;
+ use_vertex_colors = false;
+ }
/* NOTE: change MAX_PREPASS_SHADERS accordingly when modifying this function. */
int index = 0;
SET_FLAG_FROM_TEST(index, is_hair, 1 << 0);
- SET_FLAG_FROM_TEST(index, MATDATA_PASS_ENABLED(wpd), 1 << 1);
+ SET_FLAG_FROM_TEST(index, workbench_is_matdata_pass_enabled(wpd), 1 << 1);
SET_FLAG_FROM_TEST(index, OBJECT_ID_PASS_ENABLED(wpd), 1 << 2);
SET_FLAG_FROM_TEST(index, NORMAL_VIEWPORT_PASS_ENABLED(wpd), 1 << 3);
SET_FLAG_FROM_TEST(index, MATCAP_ENABLED(wpd), 1 << 4);
@@ -216,11 +231,18 @@ int workbench_material_get_prepass_shader_index(WORKBENCH_PrivateData *wpd,
int workbench_material_get_accum_shader_index(WORKBENCH_PrivateData *wpd,
bool is_uniform_color,
- bool is_hair)
+ bool is_hair,
+ bool is_texture_painting)
{
bool use_textures = (wpd->shading.color_type == V3D_SHADING_TEXTURE_COLOR) && !is_uniform_color;
bool use_vertex_colors = (wpd->shading.color_type == V3D_SHADING_VERTEX_COLOR) &&
!is_uniform_color;
+ if (is_texture_painting) {
+ use_textures = true;
+ use_vertex_colors = false;
+ is_hair = false;
+ }
+
/* NOTE: change MAX_ACCUM_SHADERS accordingly when modifying this function. */
int index = 0;
/* 2 bits FLAT/STUDIO/MATCAP + Specular highlight */
@@ -249,6 +271,13 @@ int workbench_material_determine_color_type(WORKBENCH_PrivateData *wpd,
if (color_type == V3D_SHADING_VERTEX_COLOR && (me == NULL || me->mloopcol == NULL)) {
color_type = V3D_SHADING_OBJECT_COLOR;
}
+
+ /* Force V3D_SHADING_TEXTURE_COLOR for active object when in texture painting
+ * no matter the shading color that the user has chosen, when there is no
+ * texture we will render the object with the error color */
+ if (workbench_is_object_in_texture_paint_mode(ob)) {
+ color_type = ima ? V3D_SHADING_TEXTURE_COLOR : V3D_SHADING_ERROR_COLOR;
+ }
return color_type;
}
@@ -288,33 +317,31 @@ void workbench_material_shgroup_uniform(WORKBENCH_PrivateData *wpd,
const bool deferred,
const int interp)
{
- if (deferred && !MATDATA_PASS_ENABLED(wpd)) {
- return;
- }
-
- if (workbench_material_determine_color_type(wpd, material->ima, ob, false) ==
- V3D_SHADING_TEXTURE_COLOR) {
- 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, "imagePremultiplied", (material->ima->alpha_mode == IMA_ALPHA_PREMUL));
- DRW_shgroup_uniform_bool_copy(grp, "imageNearest", (interp == SHD_INTERP_CLOSEST));
- }
- else {
- DRW_shgroup_uniform_vec3(grp,
- "materialDiffuseColor",
- (use_metallic) ? material->base_color : material->diffuse_color,
- 1);
- }
-
- if (SPECULAR_HIGHLIGHT_ENABLED(wpd)) {
- if (use_metallic) {
- DRW_shgroup_uniform_float(grp, "materialMetallic", &material->metallic, 1);
+ if (!deferred || workbench_is_matdata_pass_enabled(wpd)) {
+ if (workbench_material_determine_color_type(wpd, material->ima, ob, false) ==
+ V3D_SHADING_TEXTURE_COLOR) {
+ 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, "imagePremultiplied", (material->ima->alpha_mode == IMA_ALPHA_PREMUL));
+ DRW_shgroup_uniform_bool_copy(grp, "imageNearest", (interp == SHD_INTERP_CLOSEST));
}
else {
- DRW_shgroup_uniform_vec3(grp, "materialSpecularColor", material->specular_color, 1);
+ DRW_shgroup_uniform_vec3(grp,
+ "materialDiffuseColor",
+ (use_metallic) ? material->base_color : material->diffuse_color,
+ 1);
+ }
+
+ if (SPECULAR_HIGHLIGHT_ENABLED(wpd)) {
+ if (use_metallic) {
+ DRW_shgroup_uniform_float(grp, "materialMetallic", &material->metallic, 1);
+ }
+ else {
+ DRW_shgroup_uniform_vec3(grp, "materialSpecularColor", material->specular_color, 1);
+ }
+ DRW_shgroup_uniform_float(grp, "materialRoughness", &material->roughness, 1);
}
- DRW_shgroup_uniform_float(grp, "materialRoughness", &material->roughness, 1);
}
if (WORLD_CLIPPING_ENABLED(wpd)) {
diff --git a/source/blender/draw/engines/workbench/workbench_private.h b/source/blender/draw/engines/workbench/workbench_private.h
index 34196c6aa04..17144c4dc10 100644
--- a/source/blender/draw/engines/workbench/workbench_private.h
+++ b/source/blender/draw/engines/workbench/workbench_private.h
@@ -43,6 +43,7 @@
#define TEXTURE_DRAWING_ENABLED(wpd) (wpd->shading.color_type == V3D_SHADING_TEXTURE_COLOR)
#define VERTEX_COLORS_ENABLED(wpd) (wpd->shading.color_type == V3D_SHADING_VERTEX_COLOR)
+#define MATERIAL_COLORS_ENABLED(wpd) (wpd->shading.color_type == V3D_SHADING_MATERIAL_COLOR)
#define FLAT_ENABLED(wpd) (wpd->shading.light == V3D_LIGHTING_FLAT)
#define STUDIOLIGHT_ENABLED(wpd) (wpd->shading.light == V3D_LIGHTING_STUDIO)
#define MATCAP_ENABLED(wpd) (wpd->shading.light == V3D_LIGHTING_MATCAP)
@@ -81,8 +82,6 @@
(!STUDIOLIGHT_TYPE_MATCAP_ENABLED(wpd)))
#define OBJECT_OUTLINE_ENABLED(wpd) (wpd->shading.flag & V3D_SHADING_OBJECT_OUTLINE)
#define OBJECT_ID_PASS_ENABLED(wpd) (OBJECT_OUTLINE_ENABLED(wpd) || CURVATURE_ENABLED(wpd))
-#define MATDATA_PASS_ENABLED(wpd) \
- (wpd->shading.color_type != V3D_SHADING_SINGLE_COLOR || MATCAP_ENABLED(wpd))
#define NORMAL_VIEWPORT_COMP_PASS_ENABLED(wpd) \
(MATCAP_ENABLED(wpd) || STUDIOLIGHT_ENABLED(wpd) || SHADOW_ENABLED(wpd))
#define NORMAL_VIEWPORT_PASS_ENABLED(wpd) \
@@ -208,12 +207,14 @@ typedef struct WORKBENCH_PrivateData {
struct GPUShader *prepass_hair_sh;
struct GPUShader *prepass_uniform_sh;
struct GPUShader *prepass_uniform_hair_sh;
+ struct GPUShader *prepass_textured_sh;
struct GPUShader *composite_sh;
struct GPUShader *background_sh;
struct GPUShader *transparent_accum_sh;
struct GPUShader *transparent_accum_hair_sh;
struct GPUShader *transparent_accum_uniform_sh;
struct GPUShader *transparent_accum_uniform_hair_sh;
+ struct GPUShader *transparent_accum_textured_sh;
View3DShading shading;
StudioLight *studio_light;
const UserDef *preferences;
@@ -286,6 +287,7 @@ typedef struct WORKBENCH_MaterialData {
float base_color[3];
float diffuse_color[3];
float specular_color[3];
+ float alpha;
float metallic;
float roughness;
int object_id;
@@ -353,6 +355,32 @@ BLI_INLINE bool workbench_is_fxaa_enabled(WORKBENCH_PrivateData *wpd)
}
}
+/** Is texture paint mode enabled (globally) */
+BLI_INLINE bool workbench_is_in_texture_paint_mode(void)
+{
+ const DRWContextState *draw_ctx = DRW_context_state_get();
+ return draw_ctx->object_mode == OB_MODE_TEXTURE_PAINT;
+}
+
+/** Is texture paint mode active for the given object */
+BLI_INLINE bool workbench_is_object_in_texture_paint_mode(Object *ob)
+{
+ const DRWContextState *draw_ctx = DRW_context_state_get();
+ if (ob->type == OB_MESH && (draw_ctx->obact == ob)) {
+ const enum eContextObjectMode mode = CTX_data_mode_enum_ex(
+ draw_ctx->object_edit, draw_ctx->obact, draw_ctx->object_mode);
+ return (mode == CTX_MODE_PAINT_TEXTURE);
+ }
+
+ return false;
+}
+
+BLI_INLINE bool workbench_is_matdata_pass_enabled(WORKBENCH_PrivateData *wpd)
+{
+ return (wpd->shading.color_type != V3D_SHADING_SINGLE_COLOR || MATCAP_ENABLED(wpd)) ||
+ workbench_is_in_texture_paint_mode();
+}
+
/* workbench_deferred.c */
void workbench_deferred_engine_init(WORKBENCH_Data *vedata);
void workbench_deferred_engine_free(void);
@@ -382,8 +410,7 @@ WORKBENCH_MaterialData *workbench_forward_get_or_create_material_data(WORKBENCH_
Image *ima,
ImageUser *iuser,
int color_type,
- int interp,
- bool use_sculpt_pbvh);
+ int interp);
/* workbench_effect_aa.c */
void workbench_aa_create_pass(WORKBENCH_Data *vedata, GPUTexture **tx);
@@ -421,19 +448,23 @@ void workbench_material_get_image_and_mat(
Object *ob, int mat_nr, Image **r_image, ImageUser **r_iuser, int *r_interp, Material **r_mat);
char *workbench_material_build_defines(WORKBENCH_PrivateData *wpd,
bool is_uniform_color,
- bool is_hair);
+ bool is_hair,
+ bool is_texture_painting);
void workbench_material_update_data(WORKBENCH_PrivateData *wpd,
Object *ob,
Material *mat,
- WORKBENCH_MaterialData *data);
+ WORKBENCH_MaterialData *data,
+ int color_type);
uint workbench_material_get_hash(WORKBENCH_MaterialData *material_template, bool is_ghost);
int workbench_material_get_composite_shader_index(WORKBENCH_PrivateData *wpd);
int workbench_material_get_prepass_shader_index(WORKBENCH_PrivateData *wpd,
bool is_uniform_color,
- bool is_hair);
+ bool is_hair,
+ bool is_texture_painting);
int workbench_material_get_accum_shader_index(WORKBENCH_PrivateData *wpd,
bool is_uniform_color,
- bool is_hair);
+ bool is_hair,
+ bool is_texture_painting);
void workbench_material_shgroup_uniform(WORKBENCH_PrivateData *wpd,
DRWShadingGroup *grp,
WORKBENCH_MaterialData *material,
diff --git a/source/blender/draw/intern/draw_armature.c b/source/blender/draw/intern/draw_armature.c
index 4f387de16a8..30e51333f0f 100644
--- a/source/blender/draw/intern/draw_armature.c
+++ b/source/blender/draw/intern/draw_armature.c
@@ -883,7 +883,7 @@ static void update_color(const Object *ob, const float const_color[4])
#define NO_ALPHA(c) (((c)[3] = 1.0f), (c))
UI_GetThemeColor3fv(TH_SELECT, NO_ALPHA(g_theme.select_color));
- UI_GetThemeColor3fv(TH_EDGE_SELECT, NO_ALPHA(g_theme.edge_select_color));
+ UI_GetThemeColorShade3fv(TH_EDGE_SELECT, 60, NO_ALPHA(g_theme.edge_select_color));
UI_GetThemeColorShade3fv(TH_EDGE_SELECT, -20, NO_ALPHA(g_theme.bone_select_color));
UI_GetThemeColor3fv(TH_WIRE, NO_ALPHA(g_theme.wire_color));
UI_GetThemeColor3fv(TH_WIRE_EDIT, NO_ALPHA(g_theme.wire_edit_color));
@@ -1886,19 +1886,23 @@ static void draw_armature_edit(Object *ob)
{
const DRWContextState *draw_ctx = DRW_context_state_get();
EditBone *eBone;
- bArmature *arm = ob->data;
int index;
const bool is_select = DRW_state_is_select();
- update_color(ob, NULL);
- edbo_compute_bbone_child(arm);
-
const bool show_text = DRW_state_show_text();
const bool show_relations = ((draw_ctx->v3d->flag & V3D_HIDE_HELPLINES) == 0);
- const Object *orig_object = DEG_get_original_object(ob);
+ const Object *ob_orig = DEG_get_original_object(ob);
+ /* FIXME(campbell): We should be able to use the CoW object,
+ * however the active bone isn't updated. Long term solution is an 'EditArmature' struct.
+ * for now we can draw from the original armature. See: T66773. */
+ // bArmature *arm = ob->data;
+ bArmature *arm = ob_orig->data;
- for (eBone = arm->edbo->first, index = orig_object->runtime.select_id; eBone;
+ update_color(ob, NULL);
+ edbo_compute_bbone_child(arm);
+
+ for (eBone = arm->edbo->first, index = ob_orig->runtime.select_id; eBone;
eBone = eBone->next, index += 0x10000) {
if (eBone->layer & arm->layer) {
if ((eBone->flag & BONE_HIDDEN_A) == 0) {
@@ -1974,6 +1978,7 @@ static void draw_armature_edit(Object *ob)
static void draw_armature_pose(Object *ob, const float const_color[4])
{
const DRWContextState *draw_ctx = DRW_context_state_get();
+ const Scene *scene = draw_ctx->scene;
bArmature *arm = ob->data;
bPoseChannel *pchan;
int index = -1;
@@ -1986,19 +1991,35 @@ static void draw_armature_pose(Object *ob, const float const_color[4])
return;
}
- // if (!(base->flag & OB_FROMDUPLI)) // TODO
- {
+ bool is_pose_select = false;
+ /* Object can be edited in the scene. */
+ if ((ob->base_flag & (BASE_FROM_SET | BASE_FROM_DUPLI)) == 0) {
if ((draw_ctx->object_mode & OB_MODE_POSE) || (ob == draw_ctx->object_pose)) {
arm->flag |= ARM_POSEMODE;
}
+ is_pose_select =
+ /* If we're in pose-mode or object-mode with the ability to enter pose mode. */
+ (
+ /* Draw as if in pose mode (when selection is possible). */
+ (arm->flag & ARM_POSEMODE) ||
+ /* When we're in object mode, which may select bones. */
+ ((ob->mode & OB_MODE_POSE) &&
+ (
+ /* Switch from object mode when object lock is disabled. */
+ ((draw_ctx->object_mode == OB_MODE_OBJECT) &&
+ (scene->toolsettings->object_flag & SCE_OBJECT_MODE_LOCK) == 0) ||
+ /* Allow selection when in weight-paint mode
+ * (selection code ensures this wont become active). */
+ ((draw_ctx->object_mode == OB_MODE_WEIGHT_PAINT) &&
+ (draw_ctx->object_pose != NULL))))) &&
+ DRW_state_is_select();
- if (arm->flag & ARM_POSEMODE) {
- const Object *orig_object = DEG_get_original_object(ob);
- index = orig_object->runtime.select_id;
+ if (is_pose_select) {
+ const Object *ob_orig = DEG_get_original_object(ob);
+ index = ob_orig->runtime.select_id;
}
}
- const bool is_pose_select = (arm->flag & ARM_POSEMODE) && DRW_state_is_select();
const bool show_text = DRW_state_show_text();
const bool show_relations = ((draw_ctx->v3d->flag & V3D_HIDE_HELPLINES) == 0);
diff --git a/source/blender/draw/intern/draw_cache.c b/source/blender/draw/intern/draw_cache.c
index 88125e884d5..e2e98a2db5a 100644
--- a/source/blender/draw/intern/draw_cache.c
+++ b/source/blender/draw/intern/draw_cache.c
@@ -3016,7 +3016,7 @@ GPUBatch *DRW_cache_bone_dof_sphere_get(void)
pz = z;
}
}
- /* TODO alloc right count from the begining. */
+ /* TODO allocate right count from the beginning. */
GPU_vertbuf_data_resize(vbo, v);
SHC.drw_bone_dof_sphere = GPU_batch_create_ex(GPU_PRIM_TRIS, vbo, NULL, GPU_BATCH_OWNS_VBO);
@@ -4037,7 +4037,7 @@ void drw_batch_cache_generate_requested(Object *ob)
const enum eContextObjectMode mode = CTX_data_mode_enum_ex(
draw_ctx->object_edit, draw_ctx->obact, draw_ctx->object_mode);
const bool is_paint_mode = ELEM(
- mode, CTX_MODE_PAINT_TEXTURE, CTX_MODE_PAINT_VERTEX, CTX_MODE_PAINT_WEIGHT);
+ mode, CTX_MODE_SCULPT, CTX_MODE_PAINT_TEXTURE, CTX_MODE_PAINT_VERTEX, CTX_MODE_PAINT_WEIGHT);
const bool use_hide = ((ob->type == OB_MESH) &&
((is_paint_mode && (ob == draw_ctx->obact) &&
diff --git a/source/blender/draw/intern/draw_cache_impl_curve.c b/source/blender/draw/intern/draw_cache_impl_curve.c
index 1d6f2aaa070..75c498dfd88 100644
--- a/source/blender/draw/intern/draw_cache_impl_curve.c
+++ b/source/blender/draw/intern/draw_cache_impl_curve.c
@@ -791,7 +791,7 @@ static void curve_create_edit_data_and_handles(CurveRenderData *rdata,
}
else if (bp) {
int pt_len = nu->pntsu * nu->pntsv;
- for (int a = 0; a < pt_len; a++, bp++) {
+ for (int a = 0; a < pt_len; a++, bp++, vbo_len_used += 1) {
if (bp->hide == true) {
continue;
}
@@ -819,7 +819,6 @@ static void curve_create_edit_data_and_handles(CurveRenderData *rdata,
if (vbo_pos) {
GPU_vertbuf_attr_set(vbo_pos, attr_id.pos, vbo_len_used, bp->vec);
}
- vbo_len_used += 1;
}
}
}
diff --git a/source/blender/draw/intern/draw_cache_impl_mesh.c b/source/blender/draw/intern/draw_cache_impl_mesh.c
index f4acb586c5e..306031809d1 100644
--- a/source/blender/draw/intern/draw_cache_impl_mesh.c
+++ b/source/blender/draw/intern/draw_cache_impl_mesh.c
@@ -25,6 +25,7 @@
#include "MEM_guardedalloc.h"
+#include "BLI_bitmap.h"
#include "BLI_buffer.h"
#include "BLI_utildefines.h"
#include "BLI_math_vector.h"
@@ -46,6 +47,7 @@
#include "BKE_mesh.h"
#include "BKE_mesh_tangent.h"
#include "BKE_mesh_runtime.h"
+#include "BKE_modifier.h"
#include "BKE_object_deform.h"
#include "atomic_ops.h"
@@ -244,17 +246,21 @@ typedef struct MeshRenderData {
struct {
struct {
MLoopUV **uv;
+ MLoopCol **vcol;
+ float (**tangent)[4];
+
int uv_len;
int uv_active;
+ int uv_render;
int uv_mask_active;
- MLoopCol **vcol;
int vcol_len;
int vcol_active;
+ int vcol_render;
- float (**tangent)[4];
int tangent_len;
int tangent_active;
+ int tangent_render;
bool *auto_vcol;
} layers;
@@ -469,7 +475,7 @@ static DRW_MeshCDMask mesh_cd_calc_used_gpu_layers(const Mesh *me,
case CD_MTFACE: {
if (layer == -1) {
layer = (name[0] != '\0') ? CustomData_get_named_layer(cd_ldata, CD_MLOOPUV, name) :
- CustomData_get_active_layer(cd_ldata, CD_MLOOPUV);
+ CustomData_get_render_layer(cd_ldata, CD_MLOOPUV);
}
if (layer != -1) {
cd_used.uv |= (1 << layer);
@@ -479,11 +485,11 @@ static DRW_MeshCDMask mesh_cd_calc_used_gpu_layers(const Mesh *me,
case CD_TANGENT: {
if (layer == -1) {
layer = (name[0] != '\0') ? CustomData_get_named_layer(cd_ldata, CD_MLOOPUV, name) :
- CustomData_get_active_layer(cd_ldata, CD_MLOOPUV);
+ CustomData_get_render_layer(cd_ldata, CD_MLOOPUV);
/* Only fallback to orco (below) when we have no UV layers, see: T56545 */
if (layer == -1 && name[0] != '\0') {
- layer = CustomData_get_active_layer(cd_ldata, CD_MLOOPUV);
+ layer = CustomData_get_render_layer(cd_ldata, CD_MLOOPUV);
}
}
if (layer != -1) {
@@ -499,7 +505,7 @@ static DRW_MeshCDMask mesh_cd_calc_used_gpu_layers(const Mesh *me,
case CD_MCOL: {
if (layer == -1) {
layer = (name[0] != '\0') ? CustomData_get_named_layer(cd_ldata, CD_MLOOPCOL, name) :
- CustomData_get_active_layer(cd_ldata, CD_MLOOPCOL);
+ CustomData_get_render_layer(cd_ldata, CD_MLOOPCOL);
}
if (layer != -1) {
cd_used.vcol |= (1 << layer);
@@ -883,9 +889,12 @@ static MeshRenderData *mesh_render_data_create_ex(Mesh *me,
}
rdata->cd.layers.uv_active = CustomData_get_active_layer(cd_ldata, CD_MLOOPUV);
+ rdata->cd.layers.uv_render = CustomData_get_render_layer(cd_ldata, CD_MLOOPUV);
rdata->cd.layers.uv_mask_active = CustomData_get_stencil_layer(cd_ldata, CD_MLOOPUV);
rdata->cd.layers.vcol_active = CustomData_get_active_layer(cd_ldata, CD_MLOOPCOL);
+ rdata->cd.layers.vcol_render = CustomData_get_render_layer(cd_ldata, CD_MLOOPCOL);
rdata->cd.layers.tangent_active = rdata->cd.layers.uv_active;
+ rdata->cd.layers.tangent_render = rdata->cd.layers.uv_render;
#define CD_VALIDATE_ACTIVE_LAYER(active_index, used) \
if ((active_index != -1) && (used & (1 << active_index)) == 0) { \
@@ -894,9 +903,12 @@ static MeshRenderData *mesh_render_data_create_ex(Mesh *me,
((void)0)
CD_VALIDATE_ACTIVE_LAYER(rdata->cd.layers.uv_active, cd_used->uv);
+ CD_VALIDATE_ACTIVE_LAYER(rdata->cd.layers.uv_render, cd_used->uv);
CD_VALIDATE_ACTIVE_LAYER(rdata->cd.layers.uv_mask_active, cd_used->uv);
CD_VALIDATE_ACTIVE_LAYER(rdata->cd.layers.tangent_active, cd_used->tan);
+ CD_VALIDATE_ACTIVE_LAYER(rdata->cd.layers.tangent_render, cd_used->tan);
CD_VALIDATE_ACTIVE_LAYER(rdata->cd.layers.vcol_active, cd_used->vcol);
+ CD_VALIDATE_ACTIVE_LAYER(rdata->cd.layers.vcol_render, cd_used->vcol);
#undef CD_VALIDATE_ACTIVE_LAYER
@@ -980,6 +992,7 @@ static MeshRenderData *mesh_render_data_create_ex(Mesh *me,
* NOTE 2 : Replicate changes to code_generate_vertex_new() in gpu_codegen.c */
if (rdata->cd.layers.vcol_len != 0) {
int act_vcol = rdata->cd.layers.vcol_active;
+ int ren_vcol = rdata->cd.layers.vcol_render;
for (int i_src = 0, i_dst = 0; i_src < cd_layers_src.vcol_len; i_src++, i_dst++) {
if ((cd_used->vcol & (1 << i_src)) == 0) {
/* This is a non-used VCol slot. Skip. */
@@ -987,6 +1000,9 @@ static MeshRenderData *mesh_render_data_create_ex(Mesh *me,
if (rdata->cd.layers.vcol_active >= i_src) {
act_vcol--;
}
+ if (rdata->cd.layers.vcol_render >= i_src) {
+ ren_vcol--;
+ }
}
else {
const char *name = CustomData_get_layer_name(cd_ldata, CD_MLOOPCOL, i_src);
@@ -1009,10 +1025,13 @@ static MeshRenderData *mesh_render_data_create_ex(Mesh *me,
}
}
}
+ /* Actual active Vcol slot inside vcol layers used for shading. */
if (rdata->cd.layers.vcol_active != -1) {
- /* Actual active Vcol slot inside vcol layers used for shading. */
rdata->cd.layers.vcol_active = act_vcol;
}
+ if (rdata->cd.layers.vcol_render != -1) {
+ rdata->cd.layers.vcol_render = ren_vcol;
+ }
}
/* Start Fresh */
@@ -1020,11 +1039,15 @@ static MeshRenderData *mesh_render_data_create_ex(Mesh *me,
CustomData_free_layers(cd_ldata, CD_MLOOPTANGENT, rdata->loop_len);
if (rdata->cd.layers.uv_len != 0) {
+ int ren_uv = rdata->cd.layers.uv_render;
int act_uv = rdata->cd.layers.uv_active;
for (int i_src = 0, i_dst = 0; i_src < cd_layers_src.uv_len; i_src++, i_dst++) {
if ((cd_used->uv & (1 << i_src)) == 0) {
/* This is a non-used UV slot. Skip. */
i_dst--;
+ if (rdata->cd.layers.uv_render >= i_src) {
+ ren_uv--;
+ }
if (rdata->cd.layers.uv_active >= i_src) {
act_uv--;
}
@@ -1043,8 +1066,11 @@ static MeshRenderData *mesh_render_data_create_ex(Mesh *me,
rdata->cd.uuid.auto_mix[i_dst], sizeof(*rdata->cd.uuid.auto_mix), "a%u", hash);
}
}
+ /* Actual active / Render UV slot inside uv layers used for shading. */
+ if (rdata->cd.layers.uv_render != -1) {
+ rdata->cd.layers.uv_render = ren_uv;
+ }
if (rdata->cd.layers.uv_active != -1) {
- /* Actual active UV slot inside uv layers used for shading. */
rdata->cd.layers.uv_active = act_uv;
}
}
@@ -1143,9 +1169,13 @@ static MeshRenderData *mesh_render_data_create_ex(Mesh *me,
int i_dst = 0;
int act_tan = rdata->cd.layers.tangent_active;
+ int ren_tan = rdata->cd.layers.tangent_render;
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_render >= i_src) {
+ ren_tan--;
+ }
if (rdata->cd.layers.tangent_active >= i_src) {
act_tan--;
}
@@ -1171,10 +1201,13 @@ static MeshRenderData *mesh_render_data_create_ex(Mesh *me,
}
}
}
+ /* Actual active rangent slot inside uv layers used for shading. */
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 (rdata->cd.layers.tangent_render != -1) {
+ rdata->cd.layers.tangent_render = ren_tan;
+ }
if (cd_used->tan_orco != 0) {
const char *name = CustomData_get_layer_name(&rdata->cd.output.ldata, CD_TANGENT, i_dst);
@@ -1812,6 +1845,36 @@ static bool add_edit_facedot_mapped(MeshRenderData *rdata,
return true;
}
+static bool add_edit_facedot_subdiv(MeshRenderData *rdata,
+ GPUVertBuf *vbo,
+ const uint fdot_pos_id,
+ const uint fdot_nor_flag_id,
+ const int vert,
+ const int poly,
+ const int base_vert_idx)
+{
+ BLI_assert(rdata->types & (MR_DATATYPE_VERT | MR_DATATYPE_LOOP | MR_DATATYPE_POLY));
+ const int *p_origindex = rdata->mapped.p_origindex;
+ const int p_orig = p_origindex[poly];
+ if (p_orig == ORIGINDEX_NONE) {
+ return false;
+ }
+ BMEditMesh *em = rdata->edit_bmesh;
+ const BMFace *efa = BM_face_at_index(em->bm, p_orig);
+ if (BM_elem_flag_test(efa, BM_ELEM_HIDDEN)) {
+ return false;
+ }
+
+ Mesh *me_cage = em->mesh_eval_cage;
+ const MVert *mvert = &me_cage->mvert[vert];
+
+ GPUPackedNormal nor = GPU_normal_convert_i10_s3(mvert->no);
+ nor.w = BM_elem_flag_test(efa, BM_ELEM_SELECT) ? ((efa == em->bm->act_face) ? -1 : 1) : 0;
+ GPU_vertbuf_attr_set(vbo, fdot_nor_flag_id, base_vert_idx, &nor);
+ GPU_vertbuf_attr_set(vbo, fdot_pos_id, base_vert_idx, mvert->co);
+
+ return true;
+}
/** \} */
@@ -1985,6 +2048,7 @@ typedef struct MeshBatchCache {
/* Indices to vloops. */
GPUIndexBuf *loops_tris;
GPUIndexBuf *loops_lines;
+ GPUIndexBuf *loops_lines_paint_mask;
GPUIndexBuf *loops_line_strips;
/* Edit mode. */
GPUIndexBuf *edit_loops_points; /* verts */
@@ -2025,7 +2089,7 @@ typedef struct MeshBatchCache {
GPUBatch *loose_edges;
GPUBatch *edge_detection;
GPUBatch *wire_edges; /* Individual edges with face normals. */
- GPUBatch *wire_loops; /* Loops around faces. */
+ GPUBatch *wire_loops; /* Loops around faces. no edges between selected faces */
GPUBatch *wire_loops_uvs; /* Same as wire_loops but only has uvs. */
} batch;
@@ -2227,15 +2291,17 @@ void DRW_mesh_batch_cache_dirty_tag(Mesh *me, int mode)
case BKE_MESH_BATCH_DIRTY_SELECT_PAINT:
/* Paint mode selection flag is packed inside the nor attrib.
* Note that it can be slow if auto smooth is enabled. (see T63946) */
+ GPU_INDEXBUF_DISCARD_SAFE(cache->ibo.loops_lines_paint_mask);
GPU_VERTBUF_DISCARD_SAFE(cache->ordered.loop_pos_nor);
GPU_BATCH_DISCARD_SAFE(cache->batch.surface);
GPU_BATCH_DISCARD_SAFE(cache->batch.wire_loops);
+ GPU_BATCH_DISCARD_SAFE(cache->batch.wire_edges);
if (cache->surf_per_mat) {
for (int i = 0; i < cache->mat_len; i++) {
GPU_BATCH_DISCARD_SAFE(cache->surf_per_mat[i]);
}
}
- cache->batch_ready &= ~(MBC_SURFACE | MBC_WIRE_LOOPS | MBC_SURF_PER_MAT);
+ cache->batch_ready &= ~(MBC_SURFACE | MBC_WIRE_EDGES | MBC_WIRE_LOOPS | MBC_SURF_PER_MAT);
break;
case BKE_MESH_BATCH_DIRTY_ALL:
cache->is_dirty = true;
@@ -2719,7 +2785,10 @@ static void mesh_create_edit_vertex_loops(MeshRenderData *rdata,
}
/* TODO: We could use gl_PrimitiveID as index instead of using another VBO. */
-static void mesh_create_edit_facedots_select_id(MeshRenderData *rdata, GPUVertBuf *vbo)
+static void mesh_create_edit_facedots_select_id(MeshRenderData *rdata,
+ GPUVertBuf *vbo,
+ Scene *scene,
+ Object *ob)
{
const int poly_len = mesh_render_data_polys_len_get_maybe_mapped(rdata);
@@ -2754,12 +2823,32 @@ static void mesh_create_edit_facedots_select_id(MeshRenderData *rdata, GPUVertBu
}
else {
const int *p_origindex = rdata->mapped.p_origindex;
- for (int poly = 0; poly < poly_len; poly++) {
- const int p_orig = p_origindex[poly];
- if (p_orig != ORIGINDEX_NONE) {
- const BMFace *efa = BM_face_at_index(rdata->edit_bmesh->bm, p_orig);
- if (!BM_elem_flag_test(efa, BM_ELEM_HIDDEN)) {
- *((uint *)GPU_vertbuf_raw_step(&idx_step)) = p_orig;
+ if (modifiers_usesSubsurfFacedots(scene, ob)) {
+ Mesh *me_cage = rdata->mapped.me_cage;
+ const MPoly *mpoly = me_cage->mpoly;
+ for (int p = 0; p < poly_len; p++, mpoly++) {
+ const int p_orig = p_origindex[p];
+ if (p_orig != ORIGINDEX_NONE) {
+ const MLoop *mloop = me_cage->mloop + mpoly->loopstart;
+ for (int l = 0; l < mpoly->totloop; l++, mloop++) {
+ if (me_cage->mvert[mloop->v].flag & ME_VERT_FACEDOT) {
+ const BMFace *efa = BM_face_at_index(rdata->edit_bmesh->bm, p_orig);
+ if (!BM_elem_flag_test(efa, BM_ELEM_HIDDEN)) {
+ *((uint *)GPU_vertbuf_raw_step(&idx_step)) = p_orig;
+ }
+ }
+ }
+ }
+ }
+ }
+ else {
+ for (int poly = 0; poly < poly_len; poly++) {
+ const int p_orig = p_origindex[poly];
+ if (p_orig != ORIGINDEX_NONE) {
+ const BMFace *efa = BM_face_at_index(rdata->edit_bmesh->bm, p_orig);
+ if (!BM_elem_flag_test(efa, BM_ELEM_HIDDEN)) {
+ *((uint *)GPU_vertbuf_raw_step(&idx_step)) = p_orig;
+ }
}
}
}
@@ -2929,7 +3018,7 @@ static void mesh_create_loop_edge_fac(MeshRenderData *rdata, GPUVertBuf *vbo)
BM_ITER_ELEM (loop, &iter_loop, efa, BM_LOOPS_OF_FACE) {
float ratio = mesh_loop_edge_factor_get(
efa->no, loop->v->co, loop->v->no, loop->next->v->co);
- vertbuf_raw_step(&wd_step, ratio * 255);
+ vertbuf_raw_step(&wd_step, ratio * 253 + 1);
}
}
BLI_assert(GPU_vertbuf_raw_used(&wd_step) == loop_len);
@@ -3201,9 +3290,12 @@ static void mesh_create_loop_uv_and_tan(MeshRenderData *rdata, GPUVertBuf *vbo)
attr_name = mesh_render_data_uv_auto_layer_uuid_get(rdata, i);
GPU_vertformat_alias_add(&format, attr_name);
- if (i == rdata->cd.layers.uv_active) {
+ if (i == rdata->cd.layers.uv_render) {
GPU_vertformat_alias_add(&format, "u");
}
+ if (i == rdata->cd.layers.uv_active) {
+ GPU_vertformat_alias_add(&format, "au");
+ }
if (i == rdata->cd.layers.uv_mask_active) {
GPU_vertformat_alias_add(&format, "mu");
}
@@ -3217,9 +3309,12 @@ static void mesh_create_loop_uv_and_tan(MeshRenderData *rdata, GPUVertBuf *vbo)
#else
tangent_id[i] = GPU_vertformat_attr_add(&format, attr_name, GPU_COMP_F32, 4, GPU_FETCH_FLOAT);
#endif
- if (i == rdata->cd.layers.tangent_active) {
+ if (i == rdata->cd.layers.tangent_render) {
GPU_vertformat_alias_add(&format, "t");
}
+ if (i == rdata->cd.layers.tangent_active) {
+ GPU_vertformat_alias_add(&format, "at");
+ }
}
/* HACK: Create a dummy attribute in case there is no valid UV/tangent layer. */
@@ -3318,9 +3413,12 @@ static void mesh_create_loop_vcol(MeshRenderData *rdata, GPUVertBuf *vbo)
attr_name = mesh_render_data_vcol_auto_layer_uuid_get(rdata, i);
GPU_vertformat_alias_add(&format, attr_name);
}
- if (i == rdata->cd.layers.vcol_active) {
+ if (i == rdata->cd.layers.vcol_render) {
GPU_vertformat_alias_add(&format, "c");
}
+ if (i == rdata->cd.layers.vcol_active) {
+ GPU_vertformat_alias_add(&format, "ac");
+ }
}
GPU_vertbuf_init_with_format(vbo, &format);
@@ -3369,7 +3467,10 @@ static void mesh_create_loop_vcol(MeshRenderData *rdata, GPUVertBuf *vbo)
#undef USE_COMP_MESH_DATA
}
-static void mesh_create_edit_facedots(MeshRenderData *rdata, GPUVertBuf *vbo_facedots_pos_nor_data)
+static void mesh_create_edit_facedots(MeshRenderData *rdata,
+ GPUVertBuf *vbo_facedots_pos_nor_data,
+ Scene *scene,
+ Object *ob)
{
const int poly_len = mesh_render_data_polys_len_get_maybe_mapped(rdata);
const int verts_facedot_len = poly_len;
@@ -3411,21 +3512,37 @@ static void mesh_create_edit_facedots(MeshRenderData *rdata, GPUVertBuf *vbo_fac
}
}
else {
-#if 0 /* TODO(fclem): Mapped facedots are not following the original face. */
- Mesh *me_cage = rdata->mapped.me_cage;
- const MVert *mvert = me_cage->mvert;
- const MEdge *medge = me_cage->medge;
- const int *e_origindex = rdata->mapped.e_origindex;
- const int *v_origindex = rdata->mapped.v_origindex;
-#endif
- for (int i = 0; i < poly_len; i++) {
- if (add_edit_facedot_mapped(rdata,
- vbo_facedots_pos_nor_data,
- attr_id.fdot_pos,
- attr_id.fdot_nor_flag,
- i,
- facedot_len_used)) {
- facedot_len_used += 1;
+ if (modifiers_usesSubsurfFacedots(scene, ob)) {
+ /* Facedots that follow surbsurf face center. */
+ Mesh *me_cage = rdata->mapped.me_cage;
+ const MPoly *mpoly = me_cage->mpoly;
+ for (int p = 0; p < poly_len; p++, mpoly++) {
+ const MLoop *mloop = me_cage->mloop + mpoly->loopstart;
+ for (int l = 0; l < mpoly->totloop; l++, mloop++) {
+ if (me_cage->mvert[mloop->v].flag & ME_VERT_FACEDOT) {
+ if (add_edit_facedot_subdiv(rdata,
+ vbo_facedots_pos_nor_data,
+ attr_id.fdot_pos,
+ attr_id.fdot_nor_flag,
+ mloop->v,
+ p,
+ facedot_len_used)) {
+ facedot_len_used += 1;
+ }
+ }
+ }
+ }
+ }
+ else {
+ for (int i = 0; i < poly_len; i++) {
+ if (add_edit_facedot_mapped(rdata,
+ vbo_facedots_pos_nor_data,
+ attr_id.fdot_pos,
+ attr_id.fdot_nor_flag,
+ i,
+ facedot_len_used)) {
+ facedot_len_used += 1;
+ }
}
}
}
@@ -3788,10 +3905,89 @@ static void mesh_create_loops_lines(MeshRenderData *rdata, GPUIndexBuf *ibo, con
}
}
}
- else {
- /* Implement ... eventually if needed. */
+
+ GPU_indexbuf_build_in_place(&elb, ibo);
+}
+
+static void mesh_create_loops_lines_paint_mask(MeshRenderData *rdata, GPUIndexBuf *ibo)
+{
+ const int loop_len = mesh_render_data_loops_len_get(rdata);
+ const int poly_len = mesh_render_data_polys_len_get(rdata);
+ const int edge_len = mesh_render_data_edges_len_get(rdata);
+
+ GPUIndexBufBuilder elb;
+ GPU_indexbuf_init(&elb, GPU_PRIM_LINES, loop_len, loop_len);
+
+ if (rdata->edit_bmesh) {
+ /* painting does not use the edit_bmesh */
BLI_assert(0);
}
+ else {
+ if (rdata->me->editflag & ME_EDIT_PAINT_FACE_SEL) {
+ /* Each edge has two bits used to count selected edges as 0, 1, 2+. */
+ BLI_bitmap *edges_used = BLI_BITMAP_NEW(edge_len * 2, __func__);
+
+ /* Fill the edge bitmap table. */
+ for (int poly = 0; poly < poly_len; poly++) {
+ const MPoly *mpoly = &rdata->mpoly[poly];
+
+ /* Do not check faces that are hidden and faces that aren't selected */
+ if (mpoly->flag & ME_HIDE || ((mpoly->flag & ME_FACE_SEL) == 0)) {
+ continue;
+ }
+
+ for (int loop_index = mpoly->loopstart, loop_index_end = mpoly->loopstart + mpoly->totloop;
+ loop_index < loop_index_end;
+ loop_index++) {
+ const MLoop *mloop = &rdata->mloop[loop_index];
+ const int e_a = mloop->e * 2;
+ const int e_b = e_a + 1;
+ if (!BLI_BITMAP_TEST(edges_used, e_a)) {
+ BLI_BITMAP_ENABLE(edges_used, e_a);
+ }
+ else {
+ BLI_BITMAP_ENABLE(edges_used, e_b);
+ }
+ }
+ }
+
+ for (int poly = 0; poly < poly_len; poly++) {
+ const MPoly *mpoly = &rdata->mpoly[poly];
+ if (!(mpoly->flag & ME_HIDE)) {
+
+ for (int loop_index_next = mpoly->loopstart,
+ loop_index_end = mpoly->loopstart + mpoly->totloop,
+ loop_index_curr = loop_index_end - 1;
+ loop_index_next < loop_index_end;
+ loop_index_curr = loop_index_next++) {
+ const MLoop *mloop = &rdata->mloop[loop_index_curr];
+ const int e_a = mloop->e * 2;
+ const int e_b = e_a + 1;
+
+ /* Draw if a boundary or entirely unselected. */
+ if (!BLI_BITMAP_TEST(edges_used, e_b)) {
+ GPU_indexbuf_add_line_verts(&elb, loop_index_curr, loop_index_next);
+ }
+ }
+ }
+ }
+
+ MEM_freeN(edges_used);
+ }
+ else {
+ /* Add edges. */
+ for (int poly = 0; poly < poly_len; poly++) {
+ const MPoly *mpoly = &rdata->mpoly[poly];
+ for (int loop_index_next = mpoly->loopstart,
+ loop_index_end = mpoly->loopstart + mpoly->totloop,
+ loop_index_curr = loop_index_end - 1;
+ loop_index_next < loop_index_end;
+ loop_index_curr = loop_index_next++) {
+ GPU_indexbuf_add_line_verts(&elb, loop_index_curr, loop_index_next);
+ }
+ }
+ }
+ }
GPU_indexbuf_build_in_place(&elb, ibo);
}
@@ -5053,8 +5249,8 @@ void DRW_mesh_batch_cache_create_requested(
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)) {
- DRW_ibo_request(cache->batch.wire_loops, &cache->ibo.loops_line_strips);
+ if (DRW_batch_requested(cache->batch.wire_loops, GPU_PRIM_LINES)) {
+ DRW_ibo_request(cache->batch.wire_loops, &cache->ibo.loops_lines_paint_mask);
DRW_vbo_request(cache->batch.wire_loops, &cache->ordered.loop_pos_nor);
}
if (DRW_batch_requested(cache->batch.wire_edges, GPU_PRIM_LINES)) {
@@ -5207,6 +5403,9 @@ void DRW_mesh_batch_cache_create_requested(
mr_flag, cache->ibo.loops_tris, MR_DATATYPE_LOOP | MR_DATATYPE_POLY | MR_DATATYPE_LOOPTRI);
DRW_ADD_FLAG_FROM_IBO_REQUEST(
mr_flag, cache->ibo.loops_lines, MR_DATATYPE_LOOP | MR_DATATYPE_EDGE | MR_DATATYPE_POLY);
+ DRW_ADD_FLAG_FROM_IBO_REQUEST(mr_flag,
+ cache->ibo.loops_lines_paint_mask,
+ MR_DATATYPE_LOOP | MR_DATATYPE_EDGE | MR_DATATYPE_POLY);
DRW_ADD_FLAG_FROM_IBO_REQUEST(
mr_flag, cache->ibo.loops_line_strips, MR_DATATYPE_LOOP | MR_DATATYPE_POLY);
DRW_ADD_FLAG_FROM_IBO_REQUEST(
@@ -5323,6 +5522,9 @@ void DRW_mesh_batch_cache_create_requested(
if (DRW_ibo_requested(cache->ibo.loops_lines)) {
mesh_create_loops_lines(rdata, cache->ibo.loops_lines, use_hide);
}
+ if (DRW_ibo_requested(cache->ibo.loops_lines_paint_mask)) {
+ mesh_create_loops_lines_paint_mask(rdata, cache->ibo.loops_lines_paint_mask);
+ }
if (DRW_ibo_requested(cache->ibo.loops_line_strips)) {
mesh_create_loops_line_strips(rdata, cache->ibo.loops_line_strips, use_hide);
}
@@ -5359,10 +5561,12 @@ void DRW_mesh_batch_cache_create_requested(
cache->edit.loop_face_idx);
}
if (DRW_vbo_requested(cache->edit.facedots_pos_nor_data)) {
- mesh_create_edit_facedots(rdata, cache->edit.facedots_pos_nor_data);
+ Scene *scene = DRW_context_state_get()->scene;
+ mesh_create_edit_facedots(rdata, cache->edit.facedots_pos_nor_data, scene, ob);
}
if (DRW_vbo_requested(cache->edit.facedots_idx)) {
- mesh_create_edit_facedots_select_id(rdata, cache->edit.facedots_idx);
+ Scene *scene = DRW_context_state_get()->scene;
+ mesh_create_edit_facedots_select_id(rdata, cache->edit.facedots_idx, scene, ob);
}
if (DRW_ibo_requested(cache->ibo.edit_loops_points) ||
DRW_ibo_requested(cache->ibo.edit_loops_lines)) {
diff --git a/source/blender/draw/intern/draw_cache_impl_particles.c b/source/blender/draw/intern/draw_cache_impl_particles.c
index c66a737d684..6cd03d14bfd 100644
--- a/source/blender/draw/intern/draw_cache_impl_particles.c
+++ b/source/blender/draw/intern/draw_cache_impl_particles.c
@@ -835,7 +835,9 @@ static void particle_batch_cache_ensure_procedural_strand_data(PTCacheEdit *edit
ParticleHairCache *cache)
{
int active_uv = 0;
+ int render_uv = 0;
int active_col = 0;
+ int render_col = 0;
ParticleSystemModifierData *psmd = (ParticleSystemModifierData *)md;
@@ -843,10 +845,12 @@ static void particle_batch_cache_ensure_procedural_strand_data(PTCacheEdit *edit
if (CustomData_has_layer(&psmd->mesh_final->ldata, CD_MLOOPUV)) {
cache->num_uv_layers = CustomData_number_of_layers(&psmd->mesh_final->ldata, CD_MLOOPUV);
active_uv = CustomData_get_active_layer(&psmd->mesh_final->ldata, CD_MLOOPUV);
+ render_uv = CustomData_get_render_layer(&psmd->mesh_final->ldata, CD_MLOOPUV);
}
if (CustomData_has_layer(&psmd->mesh_final->ldata, CD_MLOOPCOL)) {
cache->num_col_layers = CustomData_number_of_layers(&psmd->mesh_final->ldata, CD_MLOOPCOL);
active_col = CustomData_get_active_layer(&psmd->mesh_final->ldata, CD_MLOOPCOL);
+ render_col = CustomData_get_render_layer(&psmd->mesh_final->ldata, CD_MLOOPCOL);
}
}
@@ -897,7 +901,10 @@ static void particle_batch_cache_ensure_procedural_strand_data(PTCacheEdit *edit
BLI_snprintf(cache->uv_layer_names[i][n++], MAX_LAYER_NAME_LEN, "a%u", hash);
if (i == active_uv) {
- BLI_strncpy(cache->uv_layer_names[i][n], "u", MAX_LAYER_NAME_LEN);
+ BLI_strncpy(cache->uv_layer_names[i][n++], "au", MAX_LAYER_NAME_LEN);
+ }
+ if (i == render_uv) {
+ BLI_strncpy(cache->uv_layer_names[i][n++], "u", MAX_LAYER_NAME_LEN);
}
}
/* Vertex colors */
@@ -917,7 +924,10 @@ static void particle_batch_cache_ensure_procedural_strand_data(PTCacheEdit *edit
}
if (i == active_col) {
- BLI_strncpy(cache->col_layer_names[i][n], "c", MAX_LAYER_NAME_LEN);
+ BLI_strncpy(cache->col_layer_names[i][n++], "ac", MAX_LAYER_NAME_LEN);
+ }
+ if (i == render_col) {
+ BLI_strncpy(cache->col_layer_names[i][n++], "c", MAX_LAYER_NAME_LEN);
}
}
@@ -1435,11 +1445,12 @@ static void drw_particle_get_hair_source(Object *object,
PTCacheEdit *edit,
ParticleDrawSource *r_draw_source)
{
+ const DRWContextState *draw_ctx = DRW_context_state_get();
r_draw_source->object = object;
r_draw_source->psys = psys;
r_draw_source->md = md;
r_draw_source->edit = edit;
- if ((object->mode & OB_MODE_PARTICLE_EDIT) != 0) {
+ if (psys_in_edit_mode(draw_ctx->depsgraph, psys)) {
r_draw_source->object = DEG_get_original_object(object);
r_draw_source->psys = psys_orig_get(psys);
}
diff --git a/source/blender/draw/intern/draw_hair_private.h b/source/blender/draw/intern/draw_hair_private.h
index 72c89832d3d..6eaba7e8811 100644
--- a/source/blender/draw/intern/draw_hair_private.h
+++ b/source/blender/draw/intern/draw_hair_private.h
@@ -24,7 +24,7 @@
#ifndef __DRAW_HAIR_PRIVATE_H__
#define __DRAW_HAIR_PRIVATE_H__
-#define MAX_LAYER_NAME_CT 3 /* u0123456789, u, a0123456789 */
+#define MAX_LAYER_NAME_CT 4 /* u0123456789, u, au, a0123456789 */
#define MAX_LAYER_NAME_LEN DECIMAL_DIGITS_BOUND(uint) + 2
#define MAX_THICKRES 2 /* see eHairType */
#define MAX_HAIR_SUBDIV 4 /* see hair_subdiv rna */
diff --git a/source/blender/draw/intern/draw_instance_data.c b/source/blender/draw/intern/draw_instance_data.c
index 3e5dfb53fc7..802f49d6549 100644
--- a/source/blender/draw/intern/draw_instance_data.c
+++ b/source/blender/draw/intern/draw_instance_data.c
@@ -141,7 +141,8 @@ GPUBatch *DRW_temp_batch_instance_request(DRWInstanceDataList *idatalist,
GPUBatch *batch = BLI_memblock_alloc(idatalist->pool_instancing);
bool is_compatible = (batch->gl_prim_type == geom->gl_prim_type) && (batch->inst == buf) &&
- (buf->vbo_id != 0) && (batch->phase == GPU_BATCH_READY_TO_DRAW);
+ (buf->vbo_id != 0) && (batch->phase == GPU_BATCH_READY_TO_DRAW) &&
+ (batch->elem == geom->elem);
for (int i = 0; i < GPU_BATCH_VBO_MAX_LEN && is_compatible; i++) {
if (batch->verts[i] != geom->verts[i]) {
is_compatible = false;
diff --git a/source/blender/draw/intern/draw_manager.c b/source/blender/draw/intern/draw_manager.c
index c4e3bd5cf91..2841e017ef6 100644
--- a/source/blender/draw/intern/draw_manager.c
+++ b/source/blender/draw/intern/draw_manager.c
@@ -88,6 +88,7 @@
#include "engines/basic/basic_engine.h"
#include "engines/workbench/workbench_engine.h"
#include "engines/external/external_engine.h"
+#include "engines/gpencil/gpencil_engine.h"
#include "GPU_context.h"
@@ -206,6 +207,8 @@ bool DRW_object_use_hide_faces(const struct Object *ob)
const Mesh *me = ob->data;
switch (ob->mode) {
+ case OB_MODE_SCULPT:
+ return true;
case OB_MODE_TEXTURE_PAINT:
return (me->editflag & ME_EDIT_PAINT_FACE_SEL) != 0;
case OB_MODE_VERTEX_PAINT:
@@ -1916,6 +1919,13 @@ void DRW_render_gpencil(struct RenderEngine *engine, struct Depsgraph *depsgraph
DST.buffer_finish_called = false;
}
+static void drw_view_reset(void)
+{
+ DST.view_default = NULL;
+ DST.view_active = NULL;
+ DST.view_previous = NULL;
+}
+
void DRW_render_to_image(RenderEngine *engine, struct Depsgraph *depsgraph)
{
Scene *scene = DEG_get_evaluated_scene(depsgraph);
@@ -1998,14 +2008,12 @@ void DRW_render_to_image(RenderEngine *engine, struct Depsgraph *depsgraph)
for (RenderView *render_view = render_result->views.first; render_view != NULL;
render_view = render_view->next) {
RE_SetActiveRenderView(render, render_view->name);
- /* Reset the view. */
- DST.view_default = NULL;
- DST.view_active = NULL;
- DST.view_previous = NULL;
+ drw_view_reset();
engine_type->draw_engine->render_to_image(data, engine, render_layer, &render_rect);
/* grease pencil: render result is merged in the previous render result. */
if (DRW_render_check_grease_pencil(depsgraph)) {
DRW_state_reset();
+ drw_view_reset();
DRW_render_gpencil_to_image(engine, render_layer, &render_rect);
}
DST.buffer_finish_called = false;
@@ -2374,6 +2382,13 @@ void DRW_draw_select_loop(struct Depsgraph *depsgraph,
}
}
+ /* TODO: GPXX Workaround for grease pencil selection while draw manager support a callback from
+ * scene finish */
+ void *data = GPU_viewport_engine_data_get(DST.viewport, &draw_engine_gpencil_type);
+ if (data != NULL) {
+ DRW_gpencil_free_runtime_data(data);
+ }
+
DRW_state_lock(0);
DRW_draw_callbacks_post_scene();
@@ -2590,6 +2605,8 @@ void DRW_draw_depth_object(ARegion *ar, GPUViewport *viewport, Object *object)
world_clip_planes = rv3d->clip_local;
}
+ drw_batch_cache_validate(object);
+
switch (object->type) {
case OB_MESH: {
GPUBatch *batch;
@@ -2715,6 +2732,14 @@ void DRW_draw_select_id_object(Scene *scene,
select_mode = ts->selectmode;
}
+ /* Init the scene of the draw context. When using face dot selection on
+ * when the subsurf modifier is active on the cage, the scene needs to be
+ * valid. It is read from the context in the
+ * `DRW_mesh_batch_cache_create_requested` and used in the `isDisabled`
+ * method of the SubSurfModifier. */
+ DRWContextState *draw_ctx = &DST.draw_ctx;
+ draw_ctx->scene = scene;
+
GPU_matrix_mul(ob->obmat);
const float(*world_clip_planes)[4] = NULL;
diff --git a/source/blender/draw/intern/draw_manager_shader.c b/source/blender/draw/intern/draw_manager_shader.c
index 5c3b5aa8a8e..d0aa6d55c03 100644
--- a/source/blender/draw/intern/draw_manager_shader.c
+++ b/source/blender/draw/intern/draw_manager_shader.c
@@ -202,12 +202,8 @@ static void drw_deferred_shader_add(GPUMaterial *mat, bool deferred)
/* Get the running job or a new one if none is running. Can only have one job per type & owner.
*/
- wmJob *wm_job = WM_jobs_get(wm,
- win,
- scene,
- "Shaders Compilation",
- WM_JOB_PROGRESS | WM_JOB_SUSPEND,
- WM_JOB_TYPE_SHADER_COMPILATION);
+ wmJob *wm_job = WM_jobs_get(
+ wm, win, scene, "Shaders Compilation", WM_JOB_PROGRESS, WM_JOB_TYPE_SHADER_COMPILATION);
DRWShaderCompiler *old_comp = (DRWShaderCompiler *)WM_jobs_customdata_get(wm_job);
@@ -238,6 +234,7 @@ static void drw_deferred_shader_add(GPUMaterial *mat, bool deferred)
WM_jobs_customdata_set(wm_job, comp, drw_deferred_shader_compilation_free);
WM_jobs_timer(wm_job, 0.1, NC_MATERIAL | ND_SHADING_DRAW, 0);
+ WM_jobs_delay_start(wm_job, 0.1);
WM_jobs_callbacks(wm_job, drw_deferred_shader_compilation_exec, NULL, NULL, NULL);
WM_jobs_start(wm, wm_job);
}
@@ -252,12 +249,8 @@ void DRW_deferred_shader_remove(GPUMaterial *mat)
continue;
}
for (wmWindow *win = wm->windows.first; win; win = win->next) {
- wmJob *wm_job = WM_jobs_get(wm,
- win,
- scene,
- "Shaders Compilation",
- WM_JOB_PROGRESS | WM_JOB_SUSPEND,
- WM_JOB_TYPE_SHADER_COMPILATION);
+ wmJob *wm_job = WM_jobs_get(
+ wm, win, scene, "Shaders Compilation", WM_JOB_PROGRESS, WM_JOB_TYPE_SHADER_COMPILATION);
DRWShaderCompiler *comp = (DRWShaderCompiler *)WM_jobs_customdata_get(wm_job);
if (comp != NULL) {
diff --git a/source/blender/draw/modes/edit_mesh_mode_text.c b/source/blender/draw/modes/edit_mesh_mode_text.c
index f3630a77e9a..7c7a9a586fa 100644
--- a/source/blender/draw/modes/edit_mesh_mode_text.c
+++ b/source/blender/draw/modes/edit_mesh_mode_text.c
@@ -66,7 +66,7 @@ void DRW_edit_mesh_mode_text_measure_stats(ARegion *ar,
/* when 2 edge-info options are enabled, space apart */
const bool do_edge_textpair = (v3d->overlay.edit_flag & V3D_OVERLAY_EDIT_EDGE_LEN) &&
(v3d->overlay.edit_flag & V3D_OVERLAY_EDIT_EDGE_ANG);
- const short edge_texpair_sep = (short)(5.0f * U.ui_scale);
+ const short edge_texpair_sep = (short)(5.0f * U.dpi_fac);
float clip_planes[4][4];
/* allow for displaying shape keys and deform mods */
BMIter iter;
diff --git a/source/blender/draw/modes/edit_text_mode.c b/source/blender/draw/modes/edit_text_mode.c
index 03f26e8ce63..448dc33077e 100644
--- a/source/blender/draw/modes/edit_text_mode.c
+++ b/source/blender/draw/modes/edit_text_mode.c
@@ -383,10 +383,10 @@ static void EDIT_TEXT_draw_scene(void *vedata)
DRW_draw_pass(psl->text_box_pass);
}
- set_inverted_drawing(1);
+ GPU_logic_op_invert_set(true);
DRW_draw_pass(psl->overlay_select_pass);
DRW_draw_pass(psl->overlay_cursor_pass);
- set_inverted_drawing(0);
+ GPU_logic_op_invert_set(false);
/* If you changed framebuffer, double check you rebind
* the default one with its textures attached before finishing */
diff --git a/source/blender/draw/modes/object_mode.c b/source/blender/draw/modes/object_mode.c
index 68f3e058693..9fc11e4f36f 100644
--- a/source/blender/draw/modes/object_mode.c
+++ b/source/blender/draw/modes/object_mode.c
@@ -322,6 +322,7 @@ typedef struct OBJECT_DupliData {
GPUBatch *outline_geom;
DRWShadingGroup *extra_shgrp;
GPUBatch *extra_geom;
+ short base_flag;
} OBJECT_DupliData;
static struct {
@@ -3276,7 +3277,12 @@ static void OBJECT_cache_populate_particles(OBJECT_Shaders *sh_data,
ParticleSettings *part = psys->part;
int draw_as = (part->draw_as == PART_DRAW_REND) ? part->ren_as : part->draw_as;
- if (draw_as != PART_DRAW_PATH) {
+ if (part->type == PART_HAIR) {
+ /* Hairs should have been rendered by the render engine.*/
+ continue;
+ }
+
+ if (!ELEM(draw_as, PART_DRAW_NOT, PART_DRAW_OB, PART_DRAW_GR)) {
struct GPUBatch *geom = DRW_cache_particles_get_dots(ob, psys);
DRWShadingGroup *shgrp = NULL;
struct GPUBatch *shape = NULL;
@@ -3286,6 +3292,7 @@ static void OBJECT_cache_populate_particles(OBJECT_Shaders *sh_data,
Material *ma = give_current_material(ob, part->omat);
switch (draw_as) {
+ default:
case PART_DRAW_DOT:
shgrp = DRW_shgroup_create(sh_data->part_dot, psl->particle);
DRW_shgroup_uniform_vec3(shgrp, "color", ma ? &ma->r : def_prim_col, 1);
@@ -3320,8 +3327,6 @@ static void OBJECT_cache_populate_particles(OBJECT_Shaders *sh_data,
DRW_shgroup_uniform_bool_copy(shgrp, "screen_space", false);
DRW_shgroup_call_instances_with_attribs(shgrp, NULL, shape, geom);
break;
- default:
- break;
}
}
}
@@ -3398,6 +3403,10 @@ BLI_INLINE OBJECT_DupliData *OBJECT_duplidata_get(Object *ob, void *vedata, bool
*dupli_data = MEM_callocN(sizeof(OBJECT_DupliData), "OBJECT_DupliData");
*init = true;
}
+ else if ((*dupli_data)->base_flag != ob->base_flag) {
+ /* Select state might have change, reinit. */
+ *init = true;
+ }
return *dupli_data;
}
return NULL;
@@ -3458,6 +3467,9 @@ static void OBJECT_cache_populate(void *vedata, Object *ob)
if (dupli_data && !init_duplidata) {
geom = dupli_data->outline_geom;
shgroup = dupli_data->outline_shgrp;
+ /* TODO: Remove. Only here to increment outline id counter. */
+ 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);
}
else {
if (stl->g_data->xray_enabled_and_not_wire || is_flat_object_viewed_from_side) {
@@ -3665,6 +3677,7 @@ static void OBJECT_cache_populate(void *vedata, Object *ob)
if (init_duplidata) {
dupli_data->extra_shgrp = shgroup;
dupli_data->extra_geom = geom;
+ dupli_data->base_flag = ob->base_flag;
}
}
diff --git a/source/blender/draw/modes/overlay_mode.c b/source/blender/draw/modes/overlay_mode.c
index ae5c0064cde..a5b1133abf4 100644
--- a/source/blender/draw/modes/overlay_mode.c
+++ b/source/blender/draw/modes/overlay_mode.c
@@ -50,6 +50,7 @@
typedef struct OVERLAY_DupliData {
DRWShadingGroup *shgrp;
struct GPUBatch *geom;
+ short base_flag;
} OVERLAY_DupliData;
typedef struct OVERLAY_StorageList {
@@ -370,9 +371,16 @@ static void overlay_cache_populate(void *vedata, Object *ob)
}
else {
if ((*dupli_data)->shgrp && (*dupli_data)->geom) {
- DRW_shgroup_call((*dupli_data)->shgrp, (*dupli_data)->geom, ob);
+ if ((*dupli_data)->base_flag == ob->base_flag) {
+ DRW_shgroup_call((*dupli_data)->shgrp, (*dupli_data)->geom, ob);
+ }
+ else {
+ /* Continue and create a new Shgroup. */
+ }
+ }
+ else {
+ return;
}
- return;
}
}
@@ -437,6 +445,7 @@ static void overlay_cache_populate(void *vedata, Object *ob)
if (dupli_data) {
(*dupli_data)->shgrp = shgrp;
(*dupli_data)->geom = geom;
+ (*dupli_data)->base_flag = ob->base_flag;
}
}
}
diff --git a/source/blender/draw/modes/paint_texture_mode.c b/source/blender/draw/modes/paint_texture_mode.c
index 6c2f170a220..7c164a74f2f 100644
--- a/source/blender/draw/modes/paint_texture_mode.c
+++ b/source/blender/draw/modes/paint_texture_mode.c
@@ -63,7 +63,7 @@ typedef struct PAINT_TEXTURE_PassList {
/* Declare all passes here and init them in
* PAINT_TEXTURE_cache_init().
* Only contains (DRWPass *) */
- struct DRWPass *image_faces;
+ struct DRWPass *stencil_mask_overlay;
struct DRWPass *wire_select_overlay;
struct DRWPass *face_select_overlay;
@@ -107,9 +107,7 @@ typedef struct PAINT_TEXTURE_Shaders {
* Add sources to source/blender/draw/modes/shaders
* init in PAINT_TEXTURE_engine_init();
* free in PAINT_TEXTURE_engine_free(); */
- struct GPUShader *fallback;
- struct GPUShader *image;
- struct GPUShader *image_mask;
+ struct GPUShader *stencil_mask_overlay;
struct GPUShader *wire_select_overlay;
struct GPUShader *face_select_overlay;
@@ -124,8 +122,7 @@ static struct {
typedef struct PAINT_TEXTURE_PrivateData {
/* This keeps the references of the shading groups for
* easy access in PAINT_TEXTURE_cache_populate() */
- DRWShadingGroup *shgroup_fallback;
- DRWShadingGroup **shgroup_image_array;
+ DRWShadingGroup *shgroup_stencil_mask;
/* face-mask */
DRWShadingGroup *lwire_select_shgrp;
@@ -144,18 +141,9 @@ static void PAINT_TEXTURE_engine_init(void *vedata)
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) {
+ if (!sh_data->stencil_mask_overlay) {
const GPUShaderConfigData *sh_cfg_data = &GPU_shader_cfg_data[draw_ctx->sh_cfg];
- sh_data->fallback = 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_gpu_shader_uniform_color_frag_glsl, NULL},
- .defs = (const char *[]){sh_cfg_data->def, NULL},
- });
-
- sh_data->image = GPU_shader_create_from_arrays({
+ sh_data->stencil_mask_overlay = GPU_shader_create_from_arrays({
.vert = (const char *[]){sh_cfg_data->lib,
datatoc_common_globals_lib_glsl,
datatoc_common_view_lib_glsl,
@@ -167,18 +155,6 @@ static void PAINT_TEXTURE_engine_init(void *vedata)
.defs = (const char *[]){sh_cfg_data->def, NULL},
});
- sh_data->image_mask = GPU_shader_create_from_arrays({
- .vert = (const char *[]){sh_cfg_data->lib,
- datatoc_common_globals_lib_glsl,
- datatoc_common_view_lib_glsl,
- datatoc_paint_texture_vert_glsl,
- NULL},
- .frag = (const char *[]){datatoc_common_colormanagement_lib_glsl,
- 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,
@@ -204,45 +180,39 @@ static void PAINT_TEXTURE_engine_init(void *vedata)
if (!stl->g_data) {
/* Alloc transient pointers */
stl->g_data = MEM_mallocN(sizeof(*stl->g_data), __func__);
- stl->g_data->shgroup_image_array = NULL;
+ stl->g_data->shgroup_stencil_mask = NULL;
}
stl->g_data->view_wires = DRW_view_create_with_zoffset(draw_ctx->rv3d, 1.0f);
}
-static DRWShadingGroup *create_texture_paint_shading_group(PAINT_TEXTURE_PassList *psl,
- const Image *image,
- const struct GPUTexture *texture,
- const DRWContextState *draw_ctx,
- const bool nearest_interp)
+static DRWShadingGroup *create_texture_paint_stencil_mask_shading_group(
+ PAINT_TEXTURE_PassList *psl, const DRWContextState *draw_ctx)
{
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 ? sh_data->image_mask : sh_data->image,
- psl->image_faces);
- DRW_shgroup_uniform_texture(grp, "image", texture);
- DRW_shgroup_uniform_bool_copy(
- grp, "imagePremultiplied", (image->alpha_mode == IMA_ALPHA_PREMUL));
+ DRWShadingGroup *grp = DRW_shgroup_create(sh_data->stencil_mask_overlay,
+ psl->stencil_mask_overlay);
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);
- DRW_shgroup_uniform_bool_copy(grp, "nearestInterp", nearest_interp);
-
- 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);
- DRW_shgroup_uniform_texture(grp, "maskingImage", stencil);
- DRW_shgroup_uniform_bool_copy(
- grp, "maskingImagePremultiplied", (imapaint->stencil->alpha_mode == IMA_ALPHA_PREMUL));
- DRW_shgroup_uniform_vec3(grp, "maskingColor", imapaint->stencil_col, 1);
- DRW_shgroup_uniform_bool_copy(grp, "maskingInvertStencil", masking_inverted);
- }
+
+ const bool masking_inverted = (imapaint->flag & IMAGEPAINT_PROJECT_LAYER_STENCIL_INV) > 0;
+ GPUTexture *stencil = GPU_texture_from_blender(imapaint->stencil, NULL, GL_TEXTURE_2D);
+ DRW_shgroup_uniform_texture(grp, "maskingImage", stencil);
+ DRW_shgroup_uniform_bool_copy(
+ grp, "maskingImagePremultiplied", (imapaint->stencil->alpha_mode == IMA_ALPHA_PREMUL));
+ DRW_shgroup_uniform_vec3(grp, "maskingColor", imapaint->stencil_col, 1);
+ DRW_shgroup_uniform_bool_copy(grp, "maskingInvertStencil", masking_inverted);
return grp;
}
+static bool PAINT_TEXTURE_stencil_mask_enabled(const ImagePaintSettings *imapaint)
+{
+ return imapaint->flag & IMAGEPAINT_PROJECT_LAYER_STENCIL && imapaint->stencil != NULL;
+}
+
/* Here init all passes and shading groups
* Assume that all Passes are NULL */
static void PAINT_TEXTURE_cache_init(void *vedata)
@@ -251,69 +221,17 @@ static void PAINT_TEXTURE_cache_init(void *vedata)
PAINT_TEXTURE_StorageList *stl = ((PAINT_TEXTURE_Data *)vedata)->stl;
const DRWContextState *draw_ctx = DRW_context_state_get();
- PAINT_TEXTURE_Shaders *sh_data = &e_data.sh_data[draw_ctx->sh_cfg];
-
- /* Create a pass */
- {
- DRWPass *pass = DRW_pass_create(
- "Image Color Pass", DRW_STATE_WRITE_COLOR | DRW_STATE_DEPTH_EQUAL | DRW_STATE_BLEND_ALPHA);
- 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 const float color[4] = {1.0f, 0.0f, 1.0f, 1.0};
- DRW_shgroup_uniform_vec4(shgrp, "color", color, 1);
-
- if (draw_ctx->sh_cfg == GPU_SHADER_CFG_CLIPPED) {
- DRW_shgroup_state_enable(shgrp, DRW_STATE_CLIP_PLANES);
- }
- psl->image_faces = pass;
- stl->g_data->shgroup_fallback = shgrp;
- }
+ Scene *scene = draw_ctx->scene;
+ const ImagePaintSettings *imapaint = &scene->toolsettings->imapaint;
- MEM_SAFE_FREE(stl->g_data->shgroup_image_array);
+ PAINT_TEXTURE_Shaders *sh_data = &e_data.sh_data[draw_ctx->sh_cfg];
- 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, ima, 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);
-
- if (tex) {
- DRWShadingGroup *grp = create_texture_paint_shading_group(
- psl, ima, 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;
- }
- }
+ /* Stencil Mask */
+ if (PAINT_TEXTURE_stencil_mask_enabled(imapaint)) {
+ DRWState state = DRW_STATE_WRITE_COLOR | DRW_STATE_DEPTH_EQUAL | DRW_STATE_BLEND_ALPHA;
+ psl->stencil_mask_overlay = DRW_pass_create("Stencil Mask Pass", state);
+ stl->g_data->shgroup_stencil_mask = create_texture_paint_stencil_mask_shading_group(psl,
+ draw_ctx);
}
/* Face Mask */
@@ -358,41 +276,18 @@ static void PAINT_TEXTURE_cache_populate(void *vedata, Object *ob)
if ((ob->type == OB_MESH) && (draw_ctx->obact == ob)) {
/* Get geometry cache */
- const Mesh *me = ob->data;
const Mesh *me_orig = DEG_get_original_object(ob)->data;
Scene *scene = draw_ctx->scene;
- const bool use_surface = draw_ctx->v3d->overlay.texture_paint_mode_opacity !=
- 0.0; // DRW_object_is_mode_shade(ob) == true;
- const bool use_material_slots = (scene->toolsettings->imapaint.mode ==
- IMAGEPAINT_MODE_MATERIAL);
+ const ImagePaintSettings *imapaint = &scene->toolsettings->imapaint;
+
const bool use_face_sel = (me_orig->editflag & ME_EDIT_PAINT_FACE_SEL) != 0;
+ const bool masking_enabled = imapaint->flag & IMAGEPAINT_PROJECT_LAYER_STENCIL &&
+ imapaint->stencil != NULL;
- if (use_surface) {
- if (me->mloopuv != NULL) {
- if (use_material_slots) {
- int mat_nr = max_ii(1, me->totcol);
- struct GPUBatch **geom_array = DRW_cache_mesh_surface_texpaint_get(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(stl->g_data->shgroup_image_array[index], geom_array[i], ob);
- }
- else {
- DRW_shgroup_call(stl->g_data->shgroup_fallback, geom_array[i], ob);
- }
- }
- }
- else {
- if (stl->g_data->shgroup_image_array[0]) {
- struct GPUBatch *geom = DRW_cache_mesh_surface_texpaint_single_get(ob);
- DRW_shgroup_call(stl->g_data->shgroup_image_array[0], geom, ob);
- }
- }
- }
- else {
- struct GPUBatch *geom = DRW_cache_mesh_surface_get(ob);
- DRW_shgroup_call(stl->g_data->shgroup_fallback, geom, ob);
+ if (masking_enabled) {
+ if (stl->g_data->shgroup_stencil_mask) {
+ struct GPUBatch *geom = DRW_cache_mesh_surface_texpaint_single_get(ob);
+ DRW_shgroup_call(stl->g_data->shgroup_stencil_mask, geom, ob);
}
}
@@ -408,32 +303,15 @@ static void PAINT_TEXTURE_cache_populate(void *vedata, Object *ob)
}
}
-/* Optional: Post-cache_populate callback */
-static void PAINT_TEXTURE_cache_finish(void *vedata)
-{
- PAINT_TEXTURE_PassList *psl = ((PAINT_TEXTURE_Data *)vedata)->psl;
- PAINT_TEXTURE_StorageList *stl = ((PAINT_TEXTURE_Data *)vedata)->stl;
-
- /* Do something here! dependent on the objects gathered */
- UNUSED_VARS(psl);
-
- MEM_SAFE_FREE(stl->g_data->shgroup_image_array);
-}
-
/* Draw time ! Control rendering pipeline from here */
static void PAINT_TEXTURE_draw_scene(void *vedata)
{
PAINT_TEXTURE_PassList *psl = ((PAINT_TEXTURE_Data *)vedata)->psl;
- PAINT_TEXTURE_FramebufferList *fbl = ((PAINT_TEXTURE_Data *)vedata)->fbl;
PAINT_TEXTURE_StorageList *stl = ((PAINT_TEXTURE_Data *)vedata)->stl;
- /* Default framebuffer and texture */
- DefaultFramebufferList *dfbl = DRW_viewport_framebuffer_list_get();
- DefaultTextureList *dtxl = DRW_viewport_texture_list_get();
-
- UNUSED_VARS(fbl, dfbl, dtxl);
-
- DRW_draw_pass(psl->image_faces);
+ if (psl->stencil_mask_overlay) {
+ DRW_draw_pass(psl->stencil_mask_overlay);
+ }
DRW_draw_pass(psl->face_select_overlay);
@@ -469,7 +347,7 @@ DrawEngineType draw_engine_paint_texture_type = {
&PAINT_TEXTURE_engine_free,
&PAINT_TEXTURE_cache_init,
&PAINT_TEXTURE_cache_populate,
- &PAINT_TEXTURE_cache_finish,
+ NULL,
NULL, /* draw_background but not needed by mode engines */
&PAINT_TEXTURE_draw_scene,
NULL,
diff --git a/source/blender/draw/modes/paint_vertex_mode.c b/source/blender/draw/modes/paint_vertex_mode.c
index 862fb92287c..bfd189189b4 100644
--- a/source/blender/draw/modes/paint_vertex_mode.c
+++ b/source/blender/draw/modes/paint_vertex_mode.c
@@ -227,8 +227,9 @@ static void PAINT_VERTEX_cache_init(void *vedata)
}
{
- DRWPass *pass = DRW_pass_create(
- "Wire Pass", DRW_STATE_WRITE_COLOR | DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_LESS_EQUAL);
+ DRWPass *pass = DRW_pass_create("Wire Pass",
+ (DRW_STATE_WRITE_COLOR | DRW_STATE_BLEND_ALPHA |
+ DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_LESS_EQUAL));
for (int i = 0; i < MODE_LEN; i++) {
DRWShadingGroup *shgrp = DRW_shgroup_create(sh_data->by_mode[i].wire_overlay, pass);
DRW_shgroup_uniform_block(shgrp, "globalsBlock", G_draw.block_ubo);
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 ac6b353412d..bc1975bac81 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
@@ -35,7 +35,7 @@ void main()
vertFlag = data;
- gl_PointSize = sizeVertex;
+ gl_PointSize = sizeVertex * 2.0;
gl_Position = pPos;
#ifdef USE_WORLD_CLIP_PLANES
diff --git a/source/blender/draw/modes/shaders/paint_texture_frag.glsl b/source/blender/draw/modes/shaders/paint_texture_frag.glsl
index e8722590802..edd7c2af001 100644
--- a/source/blender/draw/modes/shaders/paint_texture_frag.glsl
+++ b/source/blender/draw/modes/shaders/paint_texture_frag.glsl
@@ -1,35 +1,17 @@
-
-in vec2 uv_interp;
-#ifdef TEXTURE_PAINT_MASK
in vec2 masking_uv_interp;
-#endif
out vec4 fragColor;
-uniform sampler2D image;
-uniform bool imagePremultiplied;
uniform float alpha = 1.0;
-uniform bool nearestInterp;
-#ifdef TEXTURE_PAINT_MASK
uniform sampler2D maskingImage;
uniform bool maskingImagePremultiplied;
uniform vec3 maskingColor;
uniform bool maskingInvertStencil;
-#endif
void main()
{
- vec2 uv = uv_interp;
- if (nearestInterp) {
- vec2 tex_size = vec2(textureSize(image, 0).xy);
- uv = (floor(uv_interp * tex_size) + 0.5) / tex_size;
- }
-
- vec4 color = texture_read_as_srgb(image, imagePremultiplied, uv);
- color.a *= alpha;
-#ifdef TEXTURE_PAINT_MASK
vec4 mask = vec4(
texture_read_as_srgb(maskingImage, maskingImagePremultiplied, masking_uv_interp).rgb, 1.0);
if (maskingInvertStencil) {
@@ -37,8 +19,7 @@ void main()
}
float mask_step = smoothstep(0, 3.0, mask.r + mask.g + mask.b);
mask.rgb *= maskingColor;
- color = mix(color, mask, mask_step);
-#endif
+ mask.a = mask_step * alpha;
- fragColor = color;
+ fragColor = mask;
}
diff --git a/source/blender/draw/modes/shaders/paint_texture_vert.glsl b/source/blender/draw/modes/shaders/paint_texture_vert.glsl
index 564f988348e..ddfc2b51437 100644
--- a/source/blender/draw/modes/shaders/paint_texture_vert.glsl
+++ b/source/blender/draw/modes/shaders/paint_texture_vert.glsl
@@ -1,27 +1,15 @@
-in vec2 u; /* active uv map */
in vec3 pos;
-
-#ifdef TEXTURE_PAINT_MASK
in vec2 mu; /* masking uv map */
-#endif
-
-out vec2 uv_interp;
-#ifdef TEXTURE_PAINT_MASK
out vec2 masking_uv_interp;
-#endif
void main()
{
vec3 world_pos = point_object_to_world(pos);
gl_Position = point_world_to_ndc(world_pos);
- uv_interp = u;
-
-#ifdef TEXTURE_PAINT_MASK
masking_uv_interp = mu;
-#endif
#ifdef USE_WORLD_CLIP_PLANES
world_clip_planes_calc_clip_distance(world_pos);
diff --git a/source/blender/draw/modes/shaders/paint_vertex_vert.glsl b/source/blender/draw/modes/shaders/paint_vertex_vert.glsl
index 53e72cc8a20..24033432a48 100644
--- a/source/blender/draw/modes/shaders/paint_vertex_vert.glsl
+++ b/source/blender/draw/modes/shaders/paint_vertex_vert.glsl
@@ -1,6 +1,6 @@
in vec3 pos;
-in vec3 c; /* active color */
+in vec3 ac; /* active color */
out vec3 finalColor;
@@ -17,7 +17,7 @@ void main()
vec3 world_pos = point_object_to_world(pos);
gl_Position = point_world_to_ndc(world_pos);
- finalColor = srgb_to_linear_attr(c);
+ finalColor = srgb_to_linear_attr(ac);
#ifdef USE_WORLD_CLIP_PLANES
world_clip_planes_calc_clip_distance(world_pos);
diff --git a/source/blender/draw/modes/shaders/paint_wire_vert.glsl b/source/blender/draw/modes/shaders/paint_wire_vert.glsl
index 371c3120811..5857ffc9960 100644
--- a/source/blender/draw/modes/shaders/paint_wire_vert.glsl
+++ b/source/blender/draw/modes/shaders/paint_wire_vert.glsl
@@ -32,17 +32,21 @@ void main()
#ifdef USE_SELECT
finalColor = (is_select) ? colSel : colorWire;
+ finalColor.a = nor.w;
#else
# ifdef VERTEX_MODE
- finalColor = colorWire;
+ finalColor.xyz = colorWire.xyz;
+ finalColor.a = 1.0;
# else
/* Weight paint needs a light color to contrasts with dark weights. */
- finalColor.xyz = vec3(0.8, 0.8, 0.8);
+ finalColor = vec4(1, 1, 1, 0.2);
# endif
#endif
- finalColor.a = nor.w;
+ /* Needed for Radeon (TM) RX 480 Graphics. */
+#if defined(GPU_ATI)
gl_PointSize = sizeVertex * 2.0;
+#endif
#ifdef USE_WORLD_CLIP_PLANES
world_clip_planes_calc_clip_distance(world_pos);
diff --git a/source/blender/draw/modes/shaders/particle_strand_vert.glsl b/source/blender/draw/modes/shaders/particle_strand_vert.glsl
index c3f8fb89c17..45fadb4ed5e 100644
--- a/source/blender/draw/modes/shaders/particle_strand_vert.glsl
+++ b/source/blender/draw/modes/shaders/particle_strand_vert.glsl
@@ -55,16 +55,17 @@ void main()
#endif
#ifdef USE_POINTS
- gl_PointSize = sizeVertex;
+ float size = sizeVertex * 2.0;
+ gl_PointSize = size;
/* calculate concentric radii in pixels */
- float radius = 0.5 * sizeVertex;
+ float radius = sizeVertex;
/* start at the outside and progress toward the center */
radii[0] = radius;
radii[1] = radius - 1.0;
/* convert to PointCoord units */
- radii /= sizeVertex;
+ radii /= size;
#endif
}
diff --git a/source/blender/editors/animation/anim_channels_edit.c b/source/blender/editors/animation/anim_channels_edit.c
index 21b9c7252d2..b93d52a1b2d 100644
--- a/source/blender/editors/animation/anim_channels_edit.c
+++ b/source/blender/editors/animation/anim_channels_edit.c
@@ -1711,8 +1711,7 @@ static void update_dependencies_on_delete(bAnimListElem *ale)
AnimData *adt = BKE_animdata_from_id(id);
/* TODO(sergey): Technically, if the animation element is being deleted
* from a driver we don't have to tag action. This is something we can check
- * for in the future. For now just do most reliable tag whic hwas always
- * happening. */
+ * for in the future. For now just do most reliable tag which was always happening. */
if (adt != NULL) {
DEG_id_tag_update(id, ID_RECALC_ANIMATION);
if (adt->action != NULL) {
diff --git a/source/blender/editors/animation/anim_filter.c b/source/blender/editors/animation/anim_filter.c
index 8d30076103b..2d16ce30d31 100644
--- a/source/blender/editors/animation/anim_filter.c
+++ b/source/blender/editors/animation/anim_filter.c
@@ -2231,7 +2231,7 @@ static size_t animdata_filter_ds_textures(
}
}
- /* Firstly check that we actuallly have some textures,
+ /* Firstly check that we actually have some textures,
* by gathering all textures in a temp list. */
for (a = 0; a < MAX_MTEX; a++) {
Tex *tex = (mtex[a]) ? mtex[a]->tex : NULL;
@@ -3151,7 +3151,9 @@ static size_t animdata_filter_dopesheet(bAnimContext *ac,
}
/* movie clip's animation */
- items += animdata_filter_dopesheet_movieclips(ac, anim_data, ads, filter_mode);
+ if (!(ads->filterflag2 & ADS_FILTER_NOMOVIECLIPS) && !(ads->filterflag & ADS_FILTER_ONLYSEL)) {
+ items += animdata_filter_dopesheet_movieclips(ac, anim_data, ads, filter_mode);
+ }
/* Scene-linked animation - e.g. world, compositing nodes, scene anim
* (including sequencer currently). */
diff --git a/source/blender/editors/animation/anim_motion_paths.c b/source/blender/editors/animation/anim_motion_paths.c
index d3c6109afcd..7a5b57b1ce6 100644
--- a/source/blender/editors/animation/anim_motion_paths.c
+++ b/source/blender/editors/animation/anim_motion_paths.c
@@ -322,8 +322,8 @@ void animviz_calc_motionpaths(Depsgraph *depsgraph,
/* reset original environment */
/* NOTE: We don't always need to reevaluate the main scene, as the depsgraph
- * may be a temporary one that works on a subset of the data. We always have
- * to resoture the current frame though. */
+ * may be a temporary one that works on a subset of the data.
+ * We always have to restore the current frame though. */
CFRA = cfra;
if (!current_frame_only && restore) {
motionpaths_calc_update_scene(bmain, depsgraph);
diff --git a/source/blender/editors/animation/keyframing.c b/source/blender/editors/animation/keyframing.c
index 31f7a337d57..2e7ed7eae34 100644
--- a/source/blender/editors/animation/keyframing.c
+++ b/source/blender/editors/animation/keyframing.c
@@ -532,7 +532,7 @@ int insert_vert_fcurve(
* introduced discontinuities in how the param worked. */
beztr.back = 1.70158f;
- /* "elastic" easing - values here were hand-optimised for a default duration of
+ /* "elastic" easing - values here were hand-optimized for a default duration of
* ~10 frames (typical mograph motion length) */
beztr.amplitude = 0.8f;
beztr.period = 4.1f;
@@ -2249,10 +2249,16 @@ static int delete_key_v3d_exec(bContext *C, wmOperator *op)
Scene *scene = CTX_data_scene(C);
float cfra = (float)CFRA;
+ int selected_objects_len = 0;
+ int selected_objects_success_len = 0;
+ int success_multi = 0;
+
CTX_DATA_BEGIN (C, Object *, ob, selected_objects) {
ID *id = &ob->id;
int success = 0;
+ selected_objects_len += 1;
+
/* just those in active action... */
if ((ob->adt) && (ob->adt->action)) {
AnimData *adt = ob->adt;
@@ -2317,22 +2323,29 @@ static int delete_key_v3d_exec(bContext *C, wmOperator *op)
DEG_id_tag_update(&ob->adt->action->id, ID_RECALC_ANIMATION_NO_FLUSH);
}
- /* report success (or failure) */
+ /* Only for reporting. */
if (success) {
- BKE_reportf(op->reports,
- RPT_INFO,
- "Object '%s' successfully had %d keyframes removed",
- id->name + 2,
- success);
- }
- else {
- BKE_reportf(op->reports, RPT_ERROR, "No keyframes removed from Object '%s'", id->name + 2);
+ selected_objects_success_len += 1;
+ success_multi += success;
}
DEG_id_tag_update(&ob->id, ID_RECALC_TRANSFORM);
}
CTX_DATA_END;
+ /* report success (or failure) */
+ if (selected_objects_success_len) {
+ BKE_reportf(op->reports,
+ RPT_INFO,
+ "%d object(s) successfully had %d keyframes removed",
+ selected_objects_success_len,
+ success_multi);
+ }
+ else {
+ BKE_reportf(
+ op->reports, RPT_ERROR, "No keyframes removed from %d object(s)", selected_objects_len);
+ }
+
/* send updates */
WM_event_add_notifier(C, NC_OBJECT | ND_KEYS, NULL);
diff --git a/source/blender/editors/armature/armature_add.c b/source/blender/editors/armature/armature_add.c
index d02e58d48a9..d2fa77f90be 100644
--- a/source/blender/editors/armature/armature_add.c
+++ b/source/blender/editors/armature/armature_add.c
@@ -1121,6 +1121,8 @@ static int armature_bone_primitive_add_exec(bContext *C, wmOperator *op)
add_v3_v3v3(bone->tail, bone->head, imat[2]); // bone with unit length 1, pointing up Z
}
+ ED_armature_edit_refresh_layer_used(obedit->data);
+
/* note, notifier might evolve */
WM_event_add_notifier(C, NC_OBJECT | ND_BONE_SELECT, obedit);
diff --git a/source/blender/editors/armature/armature_edit.c b/source/blender/editors/armature/armature_edit.c
index c5430e06b6e..4e6661b1d15 100644
--- a/source/blender/editors/armature/armature_edit.c
+++ b/source/blender/editors/armature/armature_edit.c
@@ -862,6 +862,7 @@ static int armature_fill_bones_exec(bContext *C, wmOperator *op)
}
/* updates */
+ ED_armature_edit_refresh_layer_used(arm);
WM_event_add_notifier(C, NC_OBJECT | ND_POSE, obedit);
/* free points */
@@ -1053,6 +1054,7 @@ static int armature_merge_exec(bContext *C, wmOperator *op)
/* updates */
ED_armature_edit_sync_selection(arm->edbo);
+ ED_armature_edit_refresh_layer_used(arm);
WM_event_add_notifier(C, NC_OBJECT | ND_POSE, obedit);
}
MEM_freeN(objects);
@@ -1460,8 +1462,8 @@ static int armature_delete_selected_exec(bContext *C, wmOperator *UNUSED(op))
changed_multi = true;
ED_armature_edit_sync_selection(arm->edbo);
+ ED_armature_edit_refresh_layer_used(arm);
BKE_pose_tag_recalc(CTX_data_main(C), obedit->pose);
-
WM_event_add_notifier(C, NC_OBJECT | ND_BONE_SELECT, obedit);
}
}
@@ -1635,6 +1637,7 @@ static int armature_dissolve_selected_exec(bContext *C, wmOperator *UNUSED(op))
if (changed) {
changed_multi = true;
ED_armature_edit_sync_selection(arm->edbo);
+ ED_armature_edit_refresh_layer_used(arm);
WM_event_add_notifier(C, NC_OBJECT | ND_BONE_SELECT, obedit);
}
}
diff --git a/source/blender/editors/armature/armature_relations.c b/source/blender/editors/armature/armature_relations.c
index 2c61818d902..8722e575d15 100644
--- a/source/blender/editors/armature/armature_relations.c
+++ b/source/blender/editors/armature/armature_relations.c
@@ -38,6 +38,7 @@
#include "BKE_action.h"
#include "BKE_animsys.h"
+#include "BKE_armature.h"
#include "BKE_constraint.h"
#include "BKE_context.h"
#include "BKE_fcurve.h"
@@ -426,6 +427,7 @@ int join_armature_exec(bContext *C, wmOperator *op)
ED_armature_from_edit(bmain, arm);
ED_armature_edit_free(arm);
+ BKE_armature_refresh_layer_used(arm);
DEG_id_tag_update(&scene->id, ID_RECALC_SELECT);
WM_event_add_notifier(C, NC_SCENE | ND_OB_ACTIVE, scene);
@@ -671,6 +673,9 @@ static int separate_armature_exec(bContext *C, wmOperator *op)
ED_armature_to_edit(obedit->data);
+ ED_armature_edit_refresh_layer_used(obedit->data);
+ BKE_armature_refresh_layer_used(newob->data);
+
/* parents tips remain selected when connected children are removed. */
ED_armature_edit_deselect_all(obedit);
diff --git a/source/blender/editors/armature/armature_utils.c b/source/blender/editors/armature/armature_utils.c
index 5d424594229..d8777b7e0b7 100644
--- a/source/blender/editors/armature/armature_utils.c
+++ b/source/blender/editors/armature/armature_utils.c
@@ -85,6 +85,18 @@ void ED_armature_edit_validate_active(struct bArmature *arm)
}
}
+/* Update the layers_used variable after bones are moved between layer
+ * NOTE: Used to be done in drawing code in 2.7, but that won't work with
+ * Copy-on-Write, as drawing uses evaluated copies.
+ */
+void ED_armature_edit_refresh_layer_used(bArmature *arm)
+{
+ arm->layer_used = 0;
+ for (EditBone *ebo = arm->edbo->first; ebo; ebo = ebo->next) {
+ arm->layer_used |= ebo->layer;
+ }
+}
+
/* *************************************************************** */
/* Bone Operations */
diff --git a/source/blender/editors/armature/editarmature_undo.c b/source/blender/editors/armature/editarmature_undo.c
index 3a2440af2da..4a82a8fccee 100644
--- a/source/blender/editors/armature/editarmature_undo.c
+++ b/source/blender/editors/armature/editarmature_undo.c
@@ -174,7 +174,8 @@ static bool armature_undosys_step_encode(struct bContext *C,
static void armature_undosys_step_decode(struct bContext *C,
struct Main *UNUSED(bmain),
UndoStep *us_p,
- int UNUSED(dir))
+ int UNUSED(dir),
+ bool UNUSED(is_final))
{
ArmatureUndoStep *us = (ArmatureUndoStep *)us_p;
diff --git a/source/blender/editors/armature/pose_edit.c b/source/blender/editors/armature/pose_edit.c
index 745af06c7af..5daf6b584e5 100644
--- a/source/blender/editors/armature/pose_edit.c
+++ b/source/blender/editors/armature/pose_edit.c
@@ -872,6 +872,8 @@ static int pose_bone_layers_exec(bContext *C, wmOperator *op)
RNA_boolean_set_array(&ptr, "layers", layers);
if (prev_ob != ob) {
+ BKE_armature_refresh_layer_used(ob->data);
+
/* Note, notifier might evolve. */
WM_event_add_notifier(C, NC_OBJECT | ND_POSE, ob);
DEG_id_tag_update((ID *)ob->data, ID_RECALC_COPY_ON_WRITE);
@@ -949,6 +951,8 @@ static int armature_bone_layers_exec(bContext *C, wmOperator *op)
}
CTX_DATA_END;
+ ED_armature_edit_refresh_layer_used(ob->data);
+
/* note, notifier might evolve */
WM_event_add_notifier(C, NC_OBJECT | ND_POSE, ob);
diff --git a/source/blender/editors/armature/pose_select.c b/source/blender/editors/armature/pose_select.c
index e9ea49aaf03..8434fee6e78 100644
--- a/source/blender/editors/armature/pose_select.c
+++ b/source/blender/editors/armature/pose_select.c
@@ -40,6 +40,7 @@
#include "BKE_object.h"
#include "BKE_report.h"
#include "BKE_layer.h"
+#include "BKE_modifier.h"
#include "DEG_depsgraph.h"
@@ -181,10 +182,17 @@ bool ED_armature_pose_select_pick_with_buffer(ViewLayer *view_layer,
if (!extend && !deselect && !toggle) {
{
- uint bases_len = 0;
- Base **bases = BKE_object_pose_base_array_get_unique(view_layer, v3d, &bases_len);
- ED_pose_deselect_all_multi_ex(bases, bases_len, SEL_DESELECT, true);
- MEM_freeN(bases);
+ /* Don't use 'BKE_object_pose_base_array_get_unique'
+ * because we may be selecting from object mode. */
+ FOREACH_VISIBLE_BASE_BEGIN (view_layer, v3d, base_iter) {
+ Object *ob_iter = base_iter->object;
+ if ((ob_iter->type == OB_ARMATURE) && (ob_iter->mode & OB_MODE_POSE)) {
+ if (ED_pose_deselect_all(ob_iter, SEL_DESELECT, true)) {
+ ED_pose_bone_select_tag_update(ob_iter);
+ }
+ }
+ }
+ FOREACH_VISIBLE_BASE_END;
}
nearBone->flag |= (BONE_SELECTED | BONE_TIPSEL | BONE_ROOTSEL);
arm->act_bone = nearBone;
@@ -240,6 +248,38 @@ bool ED_armature_pose_select_pick_with_buffer(ViewLayer *view_layer,
return nearBone != NULL;
}
+/**
+ * While in weight-paint mode, a single pose may be active as well.
+ * While not common, it's possible we have multiple armatures deforming a mesh.
+ *
+ * This function de-selects all other objects, and selects the new base.
+ * It can't be set to the active object because we need
+ * to keep this set to the weight paint object.
+ */
+void ED_armature_pose_select_in_wpaint_mode(ViewLayer *view_layer, Base *base_select)
+{
+ BLI_assert(base_select && (base_select->object->type == OB_ARMATURE));
+ Object *ob_active = OBACT(view_layer);
+ BLI_assert(ob_active && (ob_active->mode & OB_MODE_WEIGHT_PAINT));
+ VirtualModifierData virtualModifierData;
+ ModifierData *md = modifiers_getVirtualModifierList(ob_active, &virtualModifierData);
+ for (; md; md = md->next) {
+ if (md->type == eModifierType_Armature) {
+ ArmatureModifierData *amd = (ArmatureModifierData *)md;
+ Object *ob_arm = amd->object;
+ if (ob_arm != NULL) {
+ Base *base_arm = BKE_view_layer_base_find(view_layer, ob_arm);
+ if ((base_arm != NULL) && (base_arm != base_select) && (base_arm->flag & BASE_SELECTED)) {
+ ED_object_base_select(base_arm, BA_DESELECT);
+ }
+ }
+ }
+ }
+ if ((base_select->flag & BASE_SELECTED) == 0) {
+ ED_object_base_select(base_select, BA_SELECT);
+ }
+}
+
/* 'select_mode' is usual SEL_SELECT/SEL_DESELECT/SEL_TOGGLE/SEL_INVERT.
* When true, 'ignore_visibility' makes this func also affect invisible bones
* (hidden or on hidden layers). */
diff --git a/source/blender/editors/armature/pose_slide.c b/source/blender/editors/armature/pose_slide.c
index 97317a86104..4c5a42cade6 100644
--- a/source/blender/editors/armature/pose_slide.c
+++ b/source/blender/editors/armature/pose_slide.c
@@ -584,7 +584,7 @@ static void pose_slide_apply_quat(tPoseSlideOp *pso, tPChanFCurveLink *pfl)
/* perform blending */
if (pso->mode == POSESLIDE_BREAKDOWN) {
- /* Just perform the interpol between quat_prev and
+ /* Just perform the interpolation between quat_prev and
* quat_next using pso->percentage as a guide. */
interp_qt_qtqt(quat_final, quat_prev, quat_next, pso->percentage);
}
diff --git a/source/blender/editors/curve/editcurve_undo.c b/source/blender/editors/curve/editcurve_undo.c
index d0c2afcb1d2..835abd1a630 100644
--- a/source/blender/editors/curve/editcurve_undo.c
+++ b/source/blender/editors/curve/editcurve_undo.c
@@ -238,10 +238,8 @@ static bool curve_undosys_step_encode(struct bContext *C,
return true;
}
-static void curve_undosys_step_decode(struct bContext *C,
- struct Main *bmain,
- UndoStep *us_p,
- int UNUSED(dir))
+static void curve_undosys_step_decode(
+ struct bContext *C, struct Main *bmain, UndoStep *us_p, int UNUSED(dir), bool UNUSED(is_final))
{
CurveUndoStep *us = (CurveUndoStep *)us_p;
diff --git a/source/blender/editors/curve/editfont.c b/source/blender/editors/curve/editfont.c
index ffbfb692ca9..db3d5ad401d 100644
--- a/source/blender/editors/curve/editfont.c
+++ b/source/blender/editors/curve/editfont.c
@@ -73,9 +73,9 @@ static int kill_selection(Object *obedit, int ins);
/************************* utilities ******************************/
-static char findaccent(char char1, unsigned int code)
+static wchar_t findaccent(wchar_t char1, unsigned int code)
{
- char new = 0;
+ wchar_t new = 0;
if (char1 == 'a') {
if (code == '`') {
@@ -170,7 +170,7 @@ static char findaccent(char char1, unsigned int code)
new = 186;
}
else if (code == 'e') {
- new = 143;
+ new = 339;
}
else if (code == 'c') {
new = 169;
@@ -191,7 +191,7 @@ static char findaccent(char char1, unsigned int code)
}
else if (char1 == 't') {
if (code == 'm') {
- new = 153;
+ new = 8482;
}
}
else if (char1 == 'u') {
@@ -342,7 +342,7 @@ static char findaccent(char char1, unsigned int code)
new = 247;
}
if (code == '|') {
- new = 135;
+ new = 8224;
}
if (code == '+') {
new = 177;
@@ -350,15 +350,15 @@ static char findaccent(char char1, unsigned int code)
}
else if (char1 == '|') {
if (code == '-') {
- new = 135;
+ new = 8224;
}
if (code == '=') {
- new = 136;
+ new = 8225;
}
}
else if (char1 == '=') {
if (code == '|') {
- new = 136;
+ new = 8225;
}
}
else if (char1 == '+') {
diff --git a/source/blender/editors/curve/editfont_undo.c b/source/blender/editors/curve/editfont_undo.c
index 82c19db7a4a..2f8f15bc6c7 100644
--- a/source/blender/editors/curve/editfont_undo.c
+++ b/source/blender/editors/curve/editfont_undo.c
@@ -62,7 +62,7 @@ typedef struct UndoFont {
wchar_t *textbuf;
struct CharInfo *textbufinfo;
- int len, pos;
+ int len, pos, selstart, selend;
#ifdef USE_ARRAY_STORE
struct {
@@ -241,10 +241,10 @@ static void undofont_to_editfont(UndoFont *uf, Curve *cu)
memcpy(ef->textbufinfo, uf->textbufinfo, final_size);
ef->pos = uf->pos;
+ ef->selstart = uf->selstart;
+ ef->selend = uf->selend;
ef->len = uf->len;
- ef->selstart = ef->selend = 0;
-
#ifdef USE_ARRAY_STORE
uf_arraystore_expand_clear(uf);
#endif
@@ -269,6 +269,8 @@ static void *undofont_from_editfont(UndoFont *uf, Curve *cu)
memcpy(uf->textbufinfo, ef->textbufinfo, final_size);
uf->pos = ef->pos;
+ uf->selstart = ef->selstart;
+ uf->selend = ef->selend;
uf->len = ef->len;
#ifdef USE_ARRAY_STORE
@@ -356,7 +358,8 @@ static bool font_undosys_step_encode(struct bContext *C,
static void font_undosys_step_decode(struct bContext *C,
struct Main *UNUSED(bmain),
UndoStep *us_p,
- int UNUSED(dir))
+ int UNUSED(dir),
+ bool UNUSED(is_final))
{
/* TODO(campbell): undo_system: use low-level API to set mode. */
ED_object_mode_set(C, OB_MODE_EDIT);
diff --git a/source/blender/editors/gizmo_library/gizmo_types/cage2d_gizmo.c b/source/blender/editors/gizmo_library/gizmo_types/cage2d_gizmo.c
index 780cca66fb9..ba3b8c2602e 100644
--- a/source/blender/editors/gizmo_library/gizmo_types/cage2d_gizmo.c
+++ b/source/blender/editors/gizmo_library/gizmo_types/cage2d_gizmo.c
@@ -101,6 +101,7 @@ static bool gizmo_calc_rect_view_margin(const wmGizmo *gz, const float dims[2],
handle_size *= gz->scale_final;
float scale_xy[2];
if (!gizmo_calc_rect_view_scale(gz, dims, scale_xy)) {
+ zero_v2(margin);
return false;
}
margin[0] = ((handle_size * scale_xy[0]));
diff --git a/source/blender/editors/gizmo_library/gizmo_types/dial3d_gizmo.c b/source/blender/editors/gizmo_library/gizmo_types/dial3d_gizmo.c
index 31e30a0dd1a..6d8ab096a26 100644
--- a/source/blender/editors/gizmo_library/gizmo_types/dial3d_gizmo.c
+++ b/source/blender/editors/gizmo_library/gizmo_types/dial3d_gizmo.c
@@ -129,7 +129,26 @@ static void dial_geom_draw(const float color[4],
immUniformColor4fv(color);
if (filled) {
- imm_draw_circle_fill_2d(pos, 0, 0, 1.0, DIAL_RESOLUTION);
+ if (arc_partial_angle == 0.0f) {
+ if (arc_inner_factor == 0.0f) {
+ imm_draw_circle_fill_2d(pos, 0, 0, 1.0, DIAL_RESOLUTION);
+ }
+ else {
+ imm_draw_disk_partial_fill_2d(
+ pos, 0, 0, arc_inner_factor, 1.0f, DIAL_RESOLUTION, 0, RAD2DEGF(M_PI * 2));
+ }
+ }
+ else {
+ float arc_partial_deg = RAD2DEGF((M_PI * 2) - arc_partial_angle);
+ imm_draw_disk_partial_fill_2d(pos,
+ 0,
+ 0,
+ arc_inner_factor,
+ 1.0f,
+ DIAL_RESOLUTION,
+ -arc_partial_deg / 2,
+ arc_partial_deg);
+ }
}
else {
if (arc_partial_angle == 0.0f) {
diff --git a/source/blender/editors/gpencil/drawgpencil.c b/source/blender/editors/gpencil/drawgpencil.c
index 5f08035a56b..809acc3b322 100644
--- a/source/blender/editors/gpencil/drawgpencil.c
+++ b/source/blender/editors/gpencil/drawgpencil.c
@@ -888,7 +888,7 @@ static void gp_draw_strokes(tGPDdraw *tgpw)
/* if disable fill, the colors with fill must be omitted too except fill boundary strokes */
if ((tgpw->disable_fill == 1) && (gp_style->fill_rgba[3] > 0.0f) &&
- ((gps->flag & GP_STROKE_NOFILL) == 0)) {
+ ((gps->flag & GP_STROKE_NOFILL) == 0) && (gp_style->flag & GP_STYLE_FILL_SHOW)) {
continue;
}
diff --git a/source/blender/editors/gpencil/gpencil_brush.c b/source/blender/editors/gpencil/gpencil_brush.c
index f5b27d8268d..7d866aedd87 100644
--- a/source/blender/editors/gpencil/gpencil_brush.c
+++ b/source/blender/editors/gpencil/gpencil_brush.c
@@ -579,6 +579,7 @@ static bool gp_brush_push_apply(
mul_v3_v3fl(delta, gso->dvec, inf);
/* apply */
+ mul_mat3_m4_v3(gso->object->obmat, delta); /* only rotation component */
add_v3_v3(&pt->x, delta);
/* compute lock axis */
@@ -646,7 +647,9 @@ static bool gp_brush_pinch_apply(
inf = gp_brush_influence_calc(gso, radius, co) / 5.0f;
/* 1) Make this point relative to the cursor/midpoint (dvec) */
- sub_v3_v3v3(vec, &pt->x, gso->dvec);
+ float fpt[3];
+ mul_v3_m4v3(fpt, gso->object->obmat, &pt->x);
+ sub_v3_v3v3(vec, fpt, gso->dvec);
/* 2) Shrink the distance by pulling the point towards the midpoint
* (0.0 = at midpoint, 1 = at edge of brush region)
@@ -664,7 +667,8 @@ static bool gp_brush_pinch_apply(
mul_v3_fl(vec, fac);
/* 3) Translate back to original space, with the shrinkage applied */
- add_v3_v3v3(&pt->x, gso->dvec, vec);
+ add_v3_v3v3(fpt, gso->dvec, vec);
+ mul_v3_m4v3(&pt->x, gso->object->imat, fpt);
/* compute lock axis */
gpsculpt_compute_lock_axis(gso, pt, save_pt);
@@ -713,11 +717,14 @@ static bool gp_brush_twist_apply(
axis_angle_normalized_to_mat3(rmat, axis, angle);
- /* Rotate point (no matrix-space transforms needed, as GP points are in world space) */
- sub_v3_v3v3(vec, &pt->x, gso->dvec); /* make relative to center
- * (center is stored in dvec) */
+ /* Rotate point */
+ float fpt[3];
+ mul_v3_m4v3(fpt, gso->object->obmat, &pt->x);
+ sub_v3_v3v3(vec, fpt, gso->dvec); /* make relative to center
+ * (center is stored in dvec) */
mul_m3_v3(rmat, vec);
- add_v3_v3v3(&pt->x, vec, gso->dvec); /* restore */
+ add_v3_v3v3(fpt, vec, gso->dvec); /* restore */
+ mul_v3_m4v3(&pt->x, gso->object->imat, fpt);
/* compute lock axis */
gpsculpt_compute_lock_axis(gso, pt, save_pt);
@@ -1090,8 +1097,12 @@ static void gp_brush_clone_add(bContext *C, tGP_BrushEditData *gso)
* get pasted relative to where the cursor is now
*/
for (i = 0, pt = new_stroke->points; i < new_stroke->totpoints; i++, pt++) {
+ /* Rotate around center new position */
+ mul_mat3_m4_v3(gso->object->obmat, &pt->x); /* only rotation component */
+
/* assume that the delta can just be applied, and then everything works */
add_v3_v3(&pt->x, delta);
+ mul_m4_v3(gso->object->imat, &pt->x);
}
/* Store ref for later */
diff --git a/source/blender/editors/gpencil/gpencil_data.c b/source/blender/editors/gpencil/gpencil_data.c
index 941c7645dc0..90a2b2d613c 100644
--- a/source/blender/editors/gpencil/gpencil_data.c
+++ b/source/blender/editors/gpencil/gpencil_data.c
@@ -1521,8 +1521,10 @@ static int gp_stroke_lock_color_exec(bContext *C, wmOperator *UNUSED(op))
/* first lock all colors */
for (short i = 0; i < *totcol; i++) {
Material *tmp_ma = give_current_material(ob, i + 1);
- tmp_ma->gp_style->flag |= GP_STYLE_COLOR_LOCKED;
- DEG_id_tag_update(&tmp_ma->id, ID_RECALC_COPY_ON_WRITE);
+ if (tmp_ma) {
+ tmp_ma->gp_style->flag |= GP_STYLE_COLOR_LOCKED;
+ DEG_id_tag_update(&tmp_ma->id, ID_RECALC_COPY_ON_WRITE);
+ }
}
/* loop all selected strokes and unlock any color */
@@ -2433,10 +2435,12 @@ static int gpencil_lock_layer_exec(bContext *C, wmOperator *UNUSED(op))
for (short i = 0; i < *totcol; i++) {
ma = give_current_material(ob, i + 1);
- gp_style = ma->gp_style;
- gp_style->flag |= GP_STYLE_COLOR_LOCKED;
- gp_style->flag |= GP_STYLE_COLOR_HIDE;
- DEG_id_tag_update(&ma->id, ID_RECALC_COPY_ON_WRITE);
+ if (ma) {
+ gp_style = ma->gp_style;
+ gp_style->flag |= GP_STYLE_COLOR_LOCKED;
+ gp_style->flag |= GP_STYLE_COLOR_HIDE;
+ DEG_id_tag_update(&ma->id, ID_RECALC_COPY_ON_WRITE);
+ }
}
/* loop all selected strokes and unlock any color used in active layer */
@@ -2515,7 +2519,7 @@ static int gpencil_color_isolate_exec(bContext *C, wmOperator *op)
for (short i = 0; i < *totcol; i++) {
ma = give_current_material(ob, i + 1);
/* Skip if this is the active one */
- if (ma == active_ma) {
+ if ((ma == NULL) || (ma == active_ma)) {
continue;
}
@@ -2534,6 +2538,9 @@ static int gpencil_color_isolate_exec(bContext *C, wmOperator *op)
/* Set flags on all "other" colors */
for (short i = 0; i < *totcol; i++) {
ma = give_current_material(ob, i + 1);
+ if (ma == NULL) {
+ continue;
+ }
gp_style = ma->gp_style;
if (gp_style == active_color) {
continue;
@@ -2548,6 +2555,9 @@ static int gpencil_color_isolate_exec(bContext *C, wmOperator *op)
/* Clear flags - Restore everything else */
for (short i = 0; i < *totcol; i++) {
ma = give_current_material(ob, i + 1);
+ if (ma == NULL) {
+ continue;
+ }
gp_style = ma->gp_style;
gp_style->flag &= ~flags;
DEG_id_tag_update(&ma->id, ID_RECALC_COPY_ON_WRITE);
@@ -2610,10 +2620,12 @@ static int gpencil_color_hide_exec(bContext *C, wmOperator *op)
MaterialGPencilStyle *color = NULL;
for (short i = 0; i < *totcol; i++) {
ma = give_current_material(ob, i + 1);
- color = ma->gp_style;
- if (active_color != color) {
- color->flag |= GP_STYLE_COLOR_HIDE;
- DEG_id_tag_update(&ma->id, ID_RECALC_COPY_ON_WRITE);
+ if (ma) {
+ color = ma->gp_style;
+ if (active_color != color) {
+ color->flag |= GP_STYLE_COLOR_HIDE;
+ DEG_id_tag_update(&ma->id, ID_RECALC_COPY_ON_WRITE);
+ }
}
}
}
@@ -2671,9 +2683,11 @@ static int gpencil_color_reveal_exec(bContext *C, wmOperator *UNUSED(op))
for (short i = 0; i < *totcol; i++) {
ma = give_current_material(ob, i + 1);
- gp_style = ma->gp_style;
- gp_style->flag &= ~GP_STYLE_COLOR_HIDE;
- DEG_id_tag_update(&ma->id, ID_RECALC_COPY_ON_WRITE);
+ if (ma) {
+ gp_style = ma->gp_style;
+ gp_style->flag &= ~GP_STYLE_COLOR_HIDE;
+ DEG_id_tag_update(&ma->id, ID_RECALC_COPY_ON_WRITE);
+ }
}
/* updates */
@@ -2722,9 +2736,11 @@ static int gpencil_color_lock_all_exec(bContext *C, wmOperator *UNUSED(op))
for (short i = 0; i < *totcol; i++) {
ma = give_current_material(ob, i + 1);
- gp_style = ma->gp_style;
- gp_style->flag |= GP_STYLE_COLOR_LOCKED;
- DEG_id_tag_update(&ma->id, ID_RECALC_COPY_ON_WRITE);
+ if (ma) {
+ gp_style = ma->gp_style;
+ gp_style->flag |= GP_STYLE_COLOR_LOCKED;
+ DEG_id_tag_update(&ma->id, ID_RECALC_COPY_ON_WRITE);
+ }
}
/* updates */
@@ -2773,9 +2789,11 @@ static int gpencil_color_unlock_all_exec(bContext *C, wmOperator *UNUSED(op))
for (short i = 0; i < *totcol; i++) {
ma = give_current_material(ob, i + 1);
- gp_style = ma->gp_style;
- gp_style->flag &= ~GP_STYLE_COLOR_LOCKED;
- DEG_id_tag_update(&ma->id, ID_RECALC_COPY_ON_WRITE);
+ if (ma) {
+ gp_style = ma->gp_style;
+ gp_style->flag &= ~GP_STYLE_COLOR_LOCKED;
+ DEG_id_tag_update(&ma->id, ID_RECALC_COPY_ON_WRITE);
+ }
}
/* updates */
diff --git a/source/blender/editors/gpencil/gpencil_edit.c b/source/blender/editors/gpencil/gpencil_edit.c
index 5459cd09e53..0c1c24a9432 100644
--- a/source/blender/editors/gpencil/gpencil_edit.c
+++ b/source/blender/editors/gpencil/gpencil_edit.c
@@ -883,7 +883,7 @@ static void gpencil_add_move_points(bGPDframe *gpf, bGPDstroke *gps)
}
gps->flag |= GP_STROKE_RECALC_GEOMETRY;
- /* if first point, add new point at the begining */
+ /* If first point, add new point at the beginning. */
if (do_first) {
copy_move_point(gps, temp_points, temp_dverts, 0, 0, true);
/* deselect old */
@@ -2804,6 +2804,9 @@ static int gp_stroke_cyclical_set_exec(bContext *C, wmOperator *op)
Object *ob = CTX_data_active_object(C);
const int type = RNA_enum_get(op->ptr, "type");
+ const bool geometry = RNA_boolean_get(op->ptr, "geometry");
+ const bool is_multiedit = (bool)GPENCIL_MULTIEDIT_SESSIONS_ON(gpd);
+ bGPDstroke *gps = NULL;
/* sanity checks */
if (ELEM(NULL, gpd)) {
@@ -2812,39 +2815,55 @@ static int gp_stroke_cyclical_set_exec(bContext *C, wmOperator *op)
/* loop all selected strokes */
CTX_DATA_BEGIN (C, bGPDlayer *, gpl, editable_gpencil_layers) {
- if (gpl->actframe == NULL) {
- continue;
- }
+ bGPDframe *init_gpf = (is_multiedit) ? gpl->frames.first : gpl->actframe;
- for (bGPDstroke *gps = gpl->actframe->strokes.last; gps; gps = gps->prev) {
- MaterialGPencilStyle *gp_style = BKE_material_gpencil_settings_get(ob, gps->mat_nr + 1);
+ for (bGPDframe *gpf = init_gpf; gpf; gpf = gpf->next) {
+ if ((gpf == gpl->actframe) || ((gpf->flag & GP_FRAME_SELECT) && (is_multiedit))) {
+ if (gpf == NULL) {
+ continue;
+ }
- /* skip strokes that are not selected or invalid for current view */
- if (((gps->flag & GP_STROKE_SELECT) == 0) || ED_gpencil_stroke_can_use(C, gps) == false) {
- continue;
- }
- /* skip hidden or locked colors */
- if (!gp_style || (gp_style->flag & GP_STYLE_COLOR_HIDE) ||
- (gp_style->flag & GP_STYLE_COLOR_LOCKED)) {
- continue;
- }
+ for (gps = gpf->strokes.first; gps; gps = gps->next) {
+ MaterialGPencilStyle *gp_style = BKE_material_gpencil_settings_get(ob, gps->mat_nr + 1);
+ /* skip strokes that are not selected or invalid for current view */
+ if (((gps->flag & GP_STROKE_SELECT) == 0) ||
+ ED_gpencil_stroke_can_use(C, gps) == false) {
+ continue;
+ }
+ /* skip hidden or locked colors */
+ if (!gp_style || (gp_style->flag & GP_STYLE_COLOR_HIDE) ||
+ (gp_style->flag & GP_STYLE_COLOR_LOCKED)) {
+ continue;
+ }
- switch (type) {
- case GP_STROKE_CYCLIC_CLOSE:
- /* Close all (enable) */
- gps->flag |= GP_STROKE_CYCLIC;
- break;
- case GP_STROKE_CYCLIC_OPEN:
- /* Open all (disable) */
- gps->flag &= ~GP_STROKE_CYCLIC;
- break;
- case GP_STROKE_CYCLIC_TOGGLE:
- /* Just toggle flag... */
- gps->flag ^= GP_STROKE_CYCLIC;
- break;
- default:
- BLI_assert(0);
+ switch (type) {
+ case GP_STROKE_CYCLIC_CLOSE:
+ /* Close all (enable) */
+ gps->flag |= GP_STROKE_CYCLIC;
+ break;
+ case GP_STROKE_CYCLIC_OPEN:
+ /* Open all (disable) */
+ gps->flag &= ~GP_STROKE_CYCLIC;
+ break;
+ case GP_STROKE_CYCLIC_TOGGLE:
+ /* Just toggle flag... */
+ gps->flag ^= GP_STROKE_CYCLIC;
+ break;
+ default:
+ BLI_assert(0);
+ break;
+ }
+
+ /* Create new geometry. */
+ if ((gps->flag & GP_STROKE_CYCLIC) && (geometry)) {
+ BKE_gpencil_close_stroke(gps);
+ }
+ }
+
+ /* if not multiedit, exit loop*/
+ if (!is_multiedit) {
break;
+ }
}
}
}
@@ -2863,6 +2882,8 @@ static int gp_stroke_cyclical_set_exec(bContext *C, wmOperator *op)
*/
void GPENCIL_OT_stroke_cyclical_set(wmOperatorType *ot)
{
+ PropertyRNA *prop;
+
static const EnumPropertyItem cyclic_type[] = {
{GP_STROKE_CYCLIC_CLOSE, "CLOSE", 0, "Close all", ""},
{GP_STROKE_CYCLIC_OPEN, "OPEN", 0, "Open all", ""},
@@ -2884,6 +2905,9 @@ void GPENCIL_OT_stroke_cyclical_set(wmOperatorType *ot)
/* properties */
ot->prop = RNA_def_enum(ot->srna, "type", cyclic_type, GP_STROKE_CYCLIC_TOGGLE, "Type", "");
+ prop = RNA_def_boolean(
+ ot->srna, "geometry", false, "Create Geometry", "Create new geometry for closing stroke");
+ RNA_def_property_flag(prop, PROP_SKIP_SAVE);
}
/* ******************* Flat Stroke Caps ************************** */
diff --git a/source/blender/editors/gpencil/gpencil_interpolate.c b/source/blender/editors/gpencil/gpencil_interpolate.c
index 8a9f7c1224a..4d5548dcdf3 100644
--- a/source/blender/editors/gpencil/gpencil_interpolate.c
+++ b/source/blender/editors/gpencil/gpencil_interpolate.c
@@ -996,8 +996,9 @@ static int gpencil_interpolate_seq_exec(bContext *C, wmOperator *op)
float factor;
/* get interpolation factor */
- factor = (float)(cframe - prevFrame->framenum) /
- (nextFrame->framenum - prevFrame->framenum + 1);
+ float framerange = nextFrame->framenum - prevFrame->framenum;
+ CLAMP_MIN(framerange, 1.0f);
+ factor = (float)(cframe - prevFrame->framenum) / framerange;
if (ipo_settings->type == GP_IPO_CURVEMAP) {
/* custom curvemap */
diff --git a/source/blender/editors/gpencil/gpencil_paint.c b/source/blender/editors/gpencil/gpencil_paint.c
index f6691f4813b..b49094c4fd6 100644
--- a/source/blender/editors/gpencil/gpencil_paint.c
+++ b/source/blender/editors/gpencil/gpencil_paint.c
@@ -3708,7 +3708,7 @@ static int gpencil_draw_modal(bContext *C, wmOperator *op, const wmEvent *event)
/* handle drawing event */
/* printf("\t\tGP - add point\n"); */
- if (((p->flags & GP_PAINTFLAG_FIRSTRUN) == 0)) {
+ if (((p->flags & GP_PAINTFLAG_FIRSTRUN) == 0) && (p->paintmode != GP_PAINTMODE_ERASER)) {
gpencil_add_missing_events(C, op, event, p);
}
diff --git a/source/blender/editors/gpencil/gpencil_primitive.c b/source/blender/editors/gpencil/gpencil_primitive.c
index 21bee0a9d4e..cca94925e6e 100644
--- a/source/blender/editors/gpencil/gpencil_primitive.c
+++ b/source/blender/editors/gpencil/gpencil_primitive.c
@@ -225,8 +225,8 @@ static void gp_primitive_update_cps(tGPDprimitive *tgpi)
}
else if (tgpi->type == GP_STROKE_CURVE) {
mid_v2_v2v2(tgpi->midpoint, tgpi->start, tgpi->end);
- copy_v2_v2(tgpi->cp1, tgpi->midpoint);
- copy_v2_v2(tgpi->cp2, tgpi->cp1);
+ interp_v2_v2v2(tgpi->cp1, tgpi->midpoint, tgpi->start, 0.33f);
+ interp_v2_v2v2(tgpi->cp2, tgpi->midpoint, tgpi->end, 0.33f);
}
else if (tgpi->type == GP_STROKE_ARC) {
if (tgpi->flip) {
@@ -1284,6 +1284,11 @@ static void gpencil_primitive_interaction_end(bContext *C,
}
}
+ /* Close stroke with geometry */
+ if ((tgpi->type == GP_STROKE_BOX) || (tgpi->type == GP_STROKE_CIRCLE)) {
+ BKE_gpencil_close_stroke(gps);
+ }
+
DEG_id_tag_update(&tgpi->gpd->id, ID_RECALC_COPY_ON_WRITE);
DEG_id_tag_update(&tgpi->gpd->id, ID_RECALC_TRANSFORM | ID_RECALC_GEOMETRY);
diff --git a/source/blender/editors/include/BIF_glutil.h b/source/blender/editors/include/BIF_glutil.h
index 7d4b6dbeea2..101a65d151a 100644
--- a/source/blender/editors/include/BIF_glutil.h
+++ b/source/blender/editors/include/BIF_glutil.h
@@ -172,8 +172,6 @@ int ED_draw_imbuf_method(struct ImBuf *ibuf);
/* OpenGL drawing utility functions. Do not use these in new code, these
* are intended to be moved or removed in the future. */
-void set_inverted_drawing(int enable);
-
/* own working polygon offset */
float bglPolygonOffsetCalc(const float winmat[16], float viewdist, float dist);
void bglPolygonOffset(float viewdist, float dist);
diff --git a/source/blender/editors/include/ED_armature.h b/source/blender/editors/include/ED_armature.h
index aca59e2868f..6629eed8328 100644
--- a/source/blender/editors/include/ED_armature.h
+++ b/source/blender/editors/include/ED_armature.h
@@ -170,6 +170,10 @@ bool ED_armature_pose_select_pick_with_buffer(struct ViewLayer *view_layer,
bool deselect,
bool toggle,
bool do_nearest);
+
+void ED_armature_pose_select_in_wpaint_mode(struct ViewLayer *view_layer,
+ struct Base *base_select);
+
bool ED_armature_edit_select_pick(
struct bContext *C, const int mval[2], bool extend, bool deselect, bool toggle);
@@ -184,6 +188,8 @@ EditBone *ED_armature_ebone_get_mirrored(const struct ListBase *edbo, EditBone *
void ED_armature_edit_sync_selection(struct ListBase *edbo);
void ED_armature_edit_validate_active(struct bArmature *arm);
+void ED_armature_edit_refresh_layer_used(struct bArmature *arm);
+
struct Base *ED_armature_base_and_ebone_from_select_buffer(struct Base **bases,
uint bases_len,
int hit,
diff --git a/source/blender/editors/include/ED_mesh.h b/source/blender/editors/include/ED_mesh.h
index 5d8038d0b28..d2613facd83 100644
--- a/source/blender/editors/include/ED_mesh.h
+++ b/source/blender/editors/include/ED_mesh.h
@@ -393,6 +393,9 @@ bool ED_mesh_color_remove_named(struct Mesh *me, const char *name);
void ED_mesh_report_mirror(struct wmOperator *op, int totmirr, int totfail);
void ED_mesh_report_mirror_ex(struct wmOperator *op, int totmirr, int totfail, char selectmode);
+/* Returns the pinned mesh, the mesh from the pinned object, or the mesh from the active object. */
+struct Mesh *ED_mesh_context(struct bContext *C);
+
/* mesh backup */
typedef struct BMBackup {
struct BMesh *bmcopy;
diff --git a/source/blender/editors/include/ED_object.h b/source/blender/editors/include/ED_object.h
index a4c68c2c5ad..038f1bf52a6 100644
--- a/source/blender/editors/include/ED_object.h
+++ b/source/blender/editors/include/ED_object.h
@@ -121,6 +121,9 @@ void ED_object_parent_clear(struct Object *ob, const int type);
void ED_object_base_select(struct Base *base, eObjectSelect_Mode mode);
void ED_object_base_activate(struct bContext *C, struct Base *base);
+void ED_object_base_active_refresh(struct Main *bmain,
+ struct Scene *scene,
+ struct ViewLayer *view_layer);
void ED_object_base_free_and_unlink(struct Main *bmain, struct Scene *scene, struct Object *ob);
bool ED_object_base_deselect_all_ex(struct ViewLayer *view_layer,
struct View3D *v3d,
diff --git a/source/blender/editors/include/ED_render.h b/source/blender/editors/include/ED_render.h
index 7689a9f97cd..d36d2559f26 100644
--- a/source/blender/editors/include/ED_render.h
+++ b/source/blender/editors/include/ED_render.h
@@ -93,7 +93,8 @@ void ED_preview_icon_job(const struct bContext *C,
struct ID *id,
unsigned int *rect,
int sizex,
- int sizey);
+ int sizey,
+ const bool delay);
void ED_preview_kill_jobs(struct wmWindowManager *wm, struct Main *bmain);
void ED_preview_draw(const struct bContext *C, void *idp, void *parentp, void *slot, rcti *rect);
diff --git a/source/blender/editors/include/ED_screen.h b/source/blender/editors/include/ED_screen.h
index fc43144417a..e67a3b003fc 100644
--- a/source/blender/editors/include/ED_screen.h
+++ b/source/blender/editors/include/ED_screen.h
@@ -337,6 +337,7 @@ bool ED_operator_object_active(struct bContext *C);
bool ED_operator_object_active_editable(struct bContext *C);
bool ED_operator_object_active_editable_mesh(struct bContext *C);
bool ED_operator_object_active_editable_font(struct bContext *C);
+bool ED_operator_editable_mesh(struct bContext *C);
bool ED_operator_editmesh(struct bContext *C);
bool ED_operator_editmesh_view3d(struct bContext *C);
bool ED_operator_editmesh_region_view3d(struct bContext *C);
diff --git a/source/blender/editors/include/ED_text.h b/source/blender/editors/include/ED_text.h
index 7638249d49a..ed71439bd37 100644
--- a/source/blender/editors/include/ED_text.h
+++ b/source/blender/editors/include/ED_text.h
@@ -26,7 +26,7 @@
struct ARegion;
struct SpaceText;
-struct TextUndoBuf;
+struct UndoStep;
struct UndoType;
bool ED_text_region_location_from_cursor(struct SpaceText *st,
@@ -37,6 +37,6 @@ bool ED_text_region_location_from_cursor(struct SpaceText *st,
/* text_undo.c */
void ED_text_undosys_type(struct UndoType *ut);
-struct TextUndoBuf *ED_text_undo_push_init(struct bContext *C);
+struct UndoStep *ED_text_undo_push_init(struct bContext *C);
#endif /* __ED_TEXT_H__ */
diff --git a/source/blender/editors/include/ED_transform_snap_object_context.h b/source/blender/editors/include/ED_transform_snap_object_context.h
index 75564ddd947..f27523bb1f8 100644
--- a/source/blender/editors/include/ED_transform_snap_object_context.h
+++ b/source/blender/editors/include/ED_transform_snap_object_context.h
@@ -121,16 +121,16 @@ bool ED_transform_snap_object_project_ray_all(SnapObjectContext *sctx,
bool sort,
struct ListBase *r_hit_list);
-bool ED_transform_snap_object_project_view3d_ex(struct SnapObjectContext *sctx,
- const unsigned short snap_to,
- const struct SnapObjectParams *params,
- const float mval[2],
- float *dist_px,
- float r_loc[3],
- float r_no[3],
- int *r_index,
- struct Object **r_ob,
- float r_obmat[4][4]);
+short ED_transform_snap_object_project_view3d_ex(struct SnapObjectContext *sctx,
+ const unsigned short snap_to,
+ const struct SnapObjectParams *params,
+ const float mval[2],
+ float *dist_px,
+ float r_loc[3],
+ float r_no[3],
+ int *r_index,
+ struct Object **r_ob,
+ float r_obmat[4][4]);
bool ED_transform_snap_object_project_view3d(struct SnapObjectContext *sctx,
const unsigned short snap_to,
const struct SnapObjectParams *params,
diff --git a/source/blender/editors/include/ED_undo.h b/source/blender/editors/include/ED_undo.h
index ebc50e186a2..fa2630ba726 100644
--- a/source/blender/editors/include/ED_undo.h
+++ b/source/blender/editors/include/ED_undo.h
@@ -54,6 +54,9 @@ bool ED_undo_is_valid(const struct bContext *C, const char *undoname);
bool ED_undo_is_memfile_compatible(const struct bContext *C);
+/* Unfortunate workaround for limits mixing undo systems. */
+bool ED_undo_is_legacy_compatible_for_property(struct bContext *C, struct ID *id);
+
void ED_undo_object_editmode_restore_helper(struct bContext *C,
struct Object **object_array,
uint object_array_len,
diff --git a/source/blender/editors/include/UI_icons.h b/source/blender/editors/include/UI_icons.h
index 3d2052f1fa9..47cf827ed66 100644
--- a/source/blender/editors/include/UI_icons.h
+++ b/source/blender/editors/include/UI_icons.h
@@ -45,6 +45,9 @@
#ifndef DEF_ICON_COLOR
# define DEF_ICON_COLOR DEF_ICON
#endif
+#ifndef DEF_ICON_FUND
+# define DEF_ICON_FUND DEF_ICON
+#endif
/* ICON_ prefix added */
DEF_ICON_COLOR(NONE)
@@ -289,7 +292,7 @@ DEF_ICON(DECORATE_LIBRARY_OVERRIDE)
DEF_ICON(DECORATE_UNLOCKED)
DEF_ICON(DECORATE_LOCKED)
DEF_ICON(DECORATE_OVERRIDE)
-DEF_ICON_BLANK(111)
+DEF_ICON_FUND(FUND)
DEF_ICON(TRACKER_DATA)
DEF_ICON(HEART)
DEF_ICON(ORPHAN_DATA)
@@ -1033,4 +1036,5 @@ DEF_ICON_COLOR(EVENT_RETURN)
#undef DEF_ICON_SHADING
#undef DEF_ICON_VECTOR
#undef DEF_ICON_COLOR
+#undef DEF_ICON_FUND
#undef DEF_ICON_BLANK
diff --git a/source/blender/editors/include/UI_interface.h b/source/blender/editors/include/UI_interface.h
index bf728ec7772..3b2a80c1e05 100644
--- a/source/blender/editors/include/UI_interface.h
+++ b/source/blender/editors/include/UI_interface.h
@@ -723,7 +723,7 @@ bool UI_block_active_only_flagged_buttons(const struct bContext *C,
struct ARegion *ar,
struct uiBlock *block);
-void UI_but_execute(const struct bContext *C, uiBut *but);
+void UI_but_execute(const struct bContext *C, struct ARegion *ar, uiBut *but);
bool UI_but_online_manual_id(const uiBut *but,
char *r_str,
diff --git a/source/blender/editors/include/UI_resources.h b/source/blender/editors/include/UI_resources.h
index db6bb35560d..3b080b6df95 100644
--- a/source/blender/editors/include/UI_resources.h
+++ b/source/blender/editors/include/UI_resources.h
@@ -272,6 +272,7 @@ typedef enum ThemeColorID {
TH_ICON_OBJECT_DATA,
TH_ICON_MODIFIER,
TH_ICON_SHADING,
+ TH_ICON_FUND,
TH_SCROLL_TEXT,
diff --git a/source/blender/editors/include/UI_view2d.h b/source/blender/editors/include/UI_view2d.h
index 137c431e3bf..0dbf3c710d6 100644
--- a/source/blender/editors/include/UI_view2d.h
+++ b/source/blender/editors/include/UI_view2d.h
@@ -71,7 +71,7 @@ enum eView2D_CommonViewTypes {
#define V2D_SCROLL_HANDLE_SIZE_HOTSPOT (0.6f * U.widget_unit)
/** Don't allow scroll thumb to show below this size (so it's never too small to click on). */
-#define V2D_SCROLL_THUMB_SIZE_MIN (50.0 * UI_DPI_FAC)
+#define V2D_SCROLL_THUMB_SIZE_MIN (30.0 * UI_DPI_FAC)
/* ------ Define for UI_view2d_sync ----- */
diff --git a/source/blender/editors/interface/interface.c b/source/blender/editors/interface/interface.c
index 697c289491a..a2138a1b3a5 100644
--- a/source/blender/editors/interface/interface.c
+++ b/source/blender/editors/interface/interface.c
@@ -896,9 +896,8 @@ bool UI_block_active_only_flagged_buttons(const bContext *C, ARegion *ar, uiBloc
}
/* simulate button click */
-void UI_but_execute(const bContext *C, uiBut *but)
+void UI_but_execute(const bContext *C, ARegion *ar, uiBut *but)
{
- ARegion *ar = CTX_wm_region(C);
void *active_back;
ui_but_execute_begin((bContext *)C, ar, but, &active_back);
/* Value is applied in begin. No further action required. */
diff --git a/source/blender/editors/interface/interface_align.c b/source/blender/editors/interface/interface_align.c
index be02def1693..cc68e303e4a 100644
--- a/source/blender/editors/interface/interface_align.c
+++ b/source/blender/editors/interface/interface_align.c
@@ -251,7 +251,7 @@ static void block_align_proximity_compute(ButAlign *butal, ButAlign *butal_other
}
}
/* We assume two buttons can only share one side at most - for until
- * we have sperical UI... */
+ * we have spherical UI. */
return;
}
}
diff --git a/source/blender/editors/interface/interface_context_menu.c b/source/blender/editors/interface/interface_context_menu.c
index 36e197a0591..7cec8af46de 100644
--- a/source/blender/editors/interface/interface_context_menu.c
+++ b/source/blender/editors/interface/interface_context_menu.c
@@ -1030,23 +1030,6 @@ bool ui_popup_context_menu_for_button(bContext *C, uiBut *but)
0,
"");
UI_but_func_set(but2, popup_change_shortcut_func, but, NULL);
-
- but2 = uiDefIconTextBut(block,
- UI_BTYPE_BUT,
- 0,
- ICON_BLANK1,
- CTX_IFACE_(BLT_I18NCONTEXT_OPERATOR_DEFAULT, "Remove Shortcut"),
- 0,
- 0,
- w,
- UI_UNIT_Y,
- NULL,
- 0,
- 0,
- 0,
- 0,
- "");
- UI_but_func_set(but2, remove_shortcut_func, but, NULL);
}
else {
but2 = uiDefIconTextBut(block,
@@ -1067,6 +1050,23 @@ bool ui_popup_context_menu_for_button(bContext *C, uiBut *but)
"please use User Preferences otherwise"));
UI_but_flag_enable(but2, UI_BUT_DISABLED);
}
+
+ but2 = uiDefIconTextBut(block,
+ UI_BTYPE_BUT,
+ 0,
+ ICON_BLANK1,
+ CTX_IFACE_(BLT_I18NCONTEXT_OPERATOR_DEFAULT, "Remove Shortcut"),
+ 0,
+ 0,
+ w,
+ UI_UNIT_Y,
+ NULL,
+ 0,
+ 0,
+ 0,
+ 0,
+ "");
+ UI_but_func_set(but2, remove_shortcut_func, but, NULL);
}
/* only show 'assign' if there's a suitable key map for it to go in */
else if (WM_keymap_guess_opname(C, idname)) {
diff --git a/source/blender/editors/interface/interface_eyedropper_colorband.c b/source/blender/editors/interface/interface_eyedropper_colorband.c
index 67e5a6c806c..ffe93e48936 100644
--- a/source/blender/editors/interface/interface_eyedropper_colorband.c
+++ b/source/blender/editors/interface/interface_eyedropper_colorband.c
@@ -84,22 +84,40 @@ static bool eyedropper_colorband_init(bContext *C, wmOperator *op)
uiBut *but = UI_context_active_but_get(C);
+ PointerRNA rna_update_ptr = PointerRNA_NULL;
+ PropertyRNA *rna_update_prop = NULL;
+ bool is_undo = true;
+
if (but == NULL) {
/* pass */
}
- else if (but->type == UI_BTYPE_COLORBAND) {
- /* When invoked with a hotkey, we can find the band in 'but->poin'. */
- band = (ColorBand *)but->poin;
- }
else {
- /* When invoked from a button it's in custom_data field. */
- band = (ColorBand *)but->custom_data;
+ if (but->type == UI_BTYPE_COLORBAND) {
+ /* When invoked with a hotkey, we can find the band in 'but->poin'. */
+ band = (ColorBand *)but->poin;
+ }
+ else {
+ /* When invoked from a button it's in custom_data field. */
+ band = (ColorBand *)but->custom_data;
+ }
+
+ if (band) {
+ rna_update_ptr = ((Colorband_RNAUpdateCb *)but->func_argN)->ptr;
+ rna_update_prop = ((Colorband_RNAUpdateCb *)but->func_argN)->prop;
+ is_undo = UI_but_flag_is_set(but, UI_BUT_UNDO);
+ }
}
if (!band) {
PointerRNA ptr = CTX_data_pointer_get_type(C, "color_ramp", &RNA_ColorRamp);
if (ptr.data != NULL) {
band = ptr.data;
+
+ /* Set this to a sub-member of the property to trigger an update. */
+ extern PropertyRNA rna_ColorRamp_color_mode;
+ rna_update_ptr = ptr;
+ rna_update_prop = &rna_ColorRamp_color_mode;
+ is_undo = RNA_struct_undo_check(ptr.type);
}
}
@@ -113,9 +131,9 @@ static bool eyedropper_colorband_init(bContext *C, wmOperator *op)
eye->color_buffer_len = 0;
eye->color_band = band;
eye->init_color_band = *eye->color_band;
- eye->ptr = ((Colorband_RNAUpdateCb *)but->func_argN)->ptr;
- eye->prop = ((Colorband_RNAUpdateCb *)but->func_argN)->prop;
- eye->is_undo = UI_but_flag_is_set(but, UI_BUT_UNDO);
+ eye->ptr = rna_update_ptr;
+ eye->prop = rna_update_prop;
+ eye->is_undo = is_undo;
op->customdata = eye;
@@ -186,7 +204,9 @@ static void eyedropper_colorband_apply(bContext *C, wmOperator *op)
BKE_colorband_init_from_table_rgba(
eye->color_band, eye->color_buffer, eye->color_buffer_len, filter_samples);
eye->is_set = true;
- RNA_property_update(C, &eye->ptr, eye->prop);
+ if (eye->prop) {
+ RNA_property_update(C, &eye->ptr, eye->prop);
+ }
}
static void eyedropper_colorband_cancel(bContext *C, wmOperator *op)
@@ -194,7 +214,9 @@ static void eyedropper_colorband_cancel(bContext *C, wmOperator *op)
EyedropperColorband *eye = op->customdata;
if (eye->is_set) {
*eye->color_band = eye->init_color_band;
- RNA_property_update(C, &eye->ptr, eye->prop);
+ if (eye->prop) {
+ RNA_property_update(C, &eye->ptr, eye->prop);
+ }
}
eyedropper_colorband_exit(C, op);
}
@@ -267,7 +289,9 @@ static int eyedropper_colorband_point_modal(bContext *C, wmOperator *op, const w
break;
case EYE_MODAL_SAMPLE_RESET:
*eye->color_band = eye->init_color_band;
- RNA_property_update(C, &eye->ptr, eye->prop);
+ if (eye->prop) {
+ RNA_property_update(C, &eye->ptr, eye->prop);
+ }
eye->color_buffer_len = 0;
break;
}
diff --git a/source/blender/editors/interface/interface_eyedropper_depth.c b/source/blender/editors/interface/interface_eyedropper_depth.c
index adb317f488c..fc60fc06ac0 100644
--- a/source/blender/editors/interface/interface_eyedropper_depth.c
+++ b/source/blender/editors/interface/interface_eyedropper_depth.c
@@ -31,6 +31,7 @@
#include "DNA_space_types.h"
#include "DNA_screen_types.h"
#include "DNA_object_types.h"
+#include "DNA_camera_types.h"
#include "DNA_view3d_types.h"
#include "BLI_string.h"
@@ -102,8 +103,9 @@ static int depthdropper_init(bContext *C, wmOperator *op)
if (rv3d && rv3d->persp == RV3D_CAMOB) {
View3D *v3d = CTX_wm_view3d(C);
if (v3d->camera && v3d->camera->data && !ID_IS_LINKED(v3d->camera->data)) {
- RNA_id_pointer_create(v3d->camera->data, &ddr->ptr);
- ddr->prop = RNA_struct_find_property(&ddr->ptr, "dof_distance");
+ Camera *camera = (Camera *)v3d->camera->data;
+ RNA_pointer_create(&camera->id, &RNA_CameraDOFSettings, &camera->dof, &ddr->ptr);
+ ddr->prop = RNA_struct_find_property(&ddr->ptr, "focus_distance");
ddr->is_undo = true;
}
}
diff --git a/source/blender/editors/interface/interface_handlers.c b/source/blender/editors/interface/interface_handlers.c
index e59431d265d..a7fc0cfec25 100644
--- a/source/blender/editors/interface/interface_handlers.c
+++ b/source/blender/editors/interface/interface_handlers.c
@@ -551,12 +551,15 @@ static bool ui_but_dragedit_update_mval(uiHandleButtonData *data, int mx)
return true;
}
-static void ui_but_update_preferences_dirty(uiBut *but)
+static void ui_rna_update_preferences_dirty(PointerRNA *ptr, PropertyRNA *prop)
{
/* 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 (prop && !(RNA_property_flag(prop) & PROP_NO_DEG_UPDATE)) {
+ StructRNA *base = RNA_struct_base(ptr->type);
+ if (base == NULL) {
+ base = ptr->type;
+ }
if (ELEM(base, &RNA_AddonPreferences, &RNA_KeyConfigPreferences, &RNA_KeyMapItem)) {
tag = true;
}
@@ -568,6 +571,16 @@ static void ui_but_update_preferences_dirty(uiBut *but)
}
}
+static void ui_but_update_preferences_dirty(uiBut *but)
+{
+ ui_rna_update_preferences_dirty(&but->rnapoin, but->rnaprop);
+}
+
+static void ui_afterfunc_update_preferences_dirty(uiAfterFunc *after)
+{
+ ui_rna_update_preferences_dirty(&after->rnapoin, after->rnaprop);
+}
+
/** \} */
/* -------------------------------------------------------------------- */
@@ -743,6 +756,22 @@ static void ui_apply_but_undo(uiBut *but)
str = "Unknown Action";
}
+ /* Optionally override undo when undo system doesn't support storing properties. */
+ if (but->rnapoin.id.data) {
+ /* Exception for renaming ID data, we always need undo pushes in this case,
+ * because undo systems track data by their ID, see: T67002. */
+ extern PropertyRNA rna_ID_name;
+ if (but->rnaprop == &rna_ID_name) {
+ /* pass */
+ }
+ else {
+ ID *id = but->rnapoin.id.data;
+ if (!ED_undo_is_legacy_compatible_for_property(but->block->evil_C, id)) {
+ str = "";
+ }
+ }
+ }
+
/* delayed, after all other funcs run, popups are closed, etc */
after = ui_afterfunc_new();
BLI_strncpy(after->undostr, str, sizeof(after->undostr));
@@ -843,6 +872,8 @@ static void ui_apply_but_funcs_after(bContext *C)
MEM_freeN(after.rename_orig);
}
+ ui_afterfunc_update_preferences_dirty(&after);
+
if (after.undostr[0]) {
ED_undo_push(C, after.undostr);
}
@@ -1347,7 +1378,7 @@ static bool ui_drag_toggle_set_xy_xy(
/* is it pressed? */
int pushed_state_but = ui_drag_toggle_but_pushed_state(C, but);
if (pushed_state_but != pushed_state) {
- UI_but_execute(C, but);
+ UI_but_execute(C, ar, but);
if (do_check) {
ui_but_update_edited(but);
}
@@ -7278,7 +7309,11 @@ static void button_activate_state(bContext *C, uiBut *but, uiHandleButtonState s
button_tooltip_timer_reset(C, but);
/* automatic open pulldown block timer */
- if (ELEM(but->type, UI_BTYPE_BLOCK, UI_BTYPE_PULLDOWN, UI_BTYPE_POPOVER)) {
+ if (ELEM(but->type, UI_BTYPE_BLOCK, UI_BTYPE_PULLDOWN, UI_BTYPE_POPOVER) ||
+ /* Menu button types may draw as popovers, check for this case
+ * ignoring other kinds of menus (mainly enums). (see T66538). */
+ ((but->type == UI_BTYPE_MENU) &&
+ (UI_but_paneltype_get(but) || ui_but_menu_draw_as_popover(but)))) {
if (data->used_mouse && !data->autoopentimer) {
int time;
@@ -7939,6 +7974,8 @@ void ui_but_execute_begin(struct bContext *UNUSED(C),
uiBut *but,
void **active_back)
{
+ BLI_assert(ar != NULL);
+ BLI_assert(BLI_findindex(&ar->uiblocks, but->block) != -1);
/* note: ideally we would not have to change 'but->active' however
* some functions we call don't use data (as they should be doing) */
uiHandleButtonData *data;
@@ -9269,7 +9306,7 @@ static int ui_handle_menu_event(bContext *C,
for (but = block->buttons.first; but; but = but->next) {
if (!(but->flag & UI_BUT_DISABLED) && but->menu_key == event->type) {
if (but->type == UI_BTYPE_BUT) {
- UI_but_execute(C, but);
+ UI_but_execute(C, ar, but);
}
else {
ui_handle_button_activate_by_type(C, ar, but);
@@ -9350,7 +9387,7 @@ static int ui_handle_menu_event(bContext *C,
ar, UI_BUT_ACTIVE_DEFAULT, UI_HIDDEN);
if ((but_default != NULL) && (but_default->active == NULL)) {
if (but_default->type == UI_BTYPE_BUT) {
- UI_but_execute(C, but_default);
+ UI_but_execute(C, ar, but_default);
}
else {
ui_handle_button_activate_by_type(C, ar, but_default);
@@ -10100,9 +10137,10 @@ static int ui_handler_region_menu(bContext *C, const wmEvent *event, void *UNUSE
if ((data->state == BUTTON_STATE_MENU_OPEN) &&
/* make sure mouse isn't inside another menu (see T43247) */
- (is_inside_menu == false) && (ELEM(but->type, UI_BTYPE_PULLDOWN, UI_BTYPE_POPOVER)) &&
+ (is_inside_menu == false) &&
+ (ELEM(but->type, UI_BTYPE_PULLDOWN, UI_BTYPE_POPOVER, UI_BTYPE_MENU)) &&
(but_other = ui_but_find_mouse_over(ar, event)) && (but != but_other) &&
- (ELEM(but_other->type, UI_BTYPE_PULLDOWN, UI_BTYPE_POPOVER))) {
+ (ELEM(but_other->type, UI_BTYPE_PULLDOWN, UI_BTYPE_POPOVER, UI_BTYPE_MENU))) {
/* if mouse moves to a different root-level menu button,
* open it to replace the current menu */
if ((but_other->flag & UI_BUT_DISABLED) == 0) {
diff --git a/source/blender/editors/interface/interface_icons.c b/source/blender/editors/interface/interface_icons.c
index 6f1f4dde1ab..ea5ef94d90d 100644
--- a/source/blender/editors/interface/interface_icons.c
+++ b/source/blender/editors/interface/interface_icons.c
@@ -169,6 +169,7 @@ static const IconType icontypes[] = {
# define DEF_ICON_OBJECT_DATA(name) {ICON_TYPE_MONO_TEXTURE, TH_ICON_OBJECT_DATA},
# define DEF_ICON_MODIFIER(name) {ICON_TYPE_MONO_TEXTURE, TH_ICON_MODIFIER},
# define DEF_ICON_SHADING(name) {ICON_TYPE_MONO_TEXTURE, TH_ICON_SHADING},
+# define DEF_ICON_FUND(name) {ICON_TYPE_MONO_TEXTURE, TH_ICON_FUND},
# define DEF_ICON_VECTOR(name) {ICON_TYPE_VECTOR, 0},
# define DEF_ICON_COLOR(name) {ICON_TYPE_COLOR_TEXTURE, 0},
# define DEF_ICON_BLANK(name) {ICON_TYPE_BLANK, 0},
@@ -1417,11 +1418,13 @@ static void icon_set_image(const bContext *C,
return;
}
+ const bool delay = prv_img->rect[size] != NULL;
icon_create_rect(prv_img, size);
if (use_job) {
/* Job (background) version */
- ED_preview_icon_job(C, prv_img, id, prv_img->rect[size], prv_img->w[size], prv_img->h[size]);
+ ED_preview_icon_job(
+ C, prv_img, id, prv_img->rect[size], prv_img->w[size], prv_img->h[size], delay);
}
else {
if (!scene) {
diff --git a/source/blender/editors/interface/interface_ops.c b/source/blender/editors/interface/interface_ops.c
index aa7e7f97478..f2b2a478ba9 100644
--- a/source/blender/editors/interface/interface_ops.c
+++ b/source/blender/editors/interface/interface_ops.c
@@ -1052,8 +1052,7 @@ static int reports_to_text_exec(bContext *C, wmOperator *UNUSED(op))
str = BKE_reports_string(reports, (G.debug & G_DEBUG) ? RPT_DEBUG : RPT_INFO);
if (str) {
- TextUndoBuf *utxt = NULL; // FIXME
- BKE_text_write(txt, utxt, str);
+ BKE_text_write(txt, str);
MEM_freeN(str);
return OPERATOR_FINISHED;
@@ -1507,29 +1506,21 @@ static void UI_OT_reloadtranslation(wmOperatorType *ot)
/** \name Press Button Operator
* \{ */
-static ARegion *region_event_inside_for_screen(bContext *C, const int xy[2])
-{
- bScreen *sc = CTX_wm_screen(C);
- if (sc) {
- for (ARegion *ar = sc->regionbase.first; ar; ar = ar->next) {
- if (BLI_rcti_isect_pt_v(&ar->winrct, xy)) {
- return ar;
- }
- }
- }
- return NULL;
-}
-
static int ui_button_press_invoke(bContext *C, wmOperator *op, const wmEvent *event)
{
+ bScreen *sc = CTX_wm_screen(C);
const bool skip_depressed = RNA_boolean_get(op->ptr, "skip_depressed");
ARegion *ar_prev = CTX_wm_region(C);
- ARegion *ar = region_event_inside_for_screen(C, &event->x);
+ ARegion *ar = sc ? BKE_screen_find_region_xy(sc, RGN_TYPE_ANY, event->x, event->y) : NULL;
if (ar == NULL) {
ar = ar_prev;
}
+ if (ar == NULL) {
+ return OPERATOR_PASS_THROUGH;
+ }
+
CTX_wm_region_set(C, ar);
uiBut *but = UI_context_active_but_get(C);
CTX_wm_region_set(C, ar_prev);
@@ -1545,7 +1536,7 @@ static int ui_button_press_invoke(bContext *C, wmOperator *op, const wmEvent *ev
* having this avoids a minor drawing glitch. */
void *but_optype = but->optype;
- UI_but_execute(C, but);
+ UI_but_execute(C, ar, but);
but->optype = but_optype;
diff --git a/source/blender/editors/interface/interface_region_color_picker.c b/source/blender/editors/interface/interface_region_color_picker.c
index 5c231f5e51a..917c35f0135 100644
--- a/source/blender/editors/interface/interface_region_color_picker.c
+++ b/source/blender/editors/interface/interface_region_color_picker.c
@@ -63,6 +63,21 @@ enum ePickerType {
/** \name Color Conversion
* \{ */
+static void ui_color_picker_rgb_round(float rgb[3])
+{
+ /* Handle small rounding errors in color space conversions. Doing these for
+ * all color space conversions would be expensive, but for the color picker
+ * we can do the extra work. */
+ for (int i = 0; i < 3; i++) {
+ if (fabsf(rgb[i]) < 1e-6f) {
+ rgb[i] = 0.0f;
+ }
+ else if (fabsf(1.0f - rgb[i]) < 1e-6f) {
+ rgb[i] = 1.0f;
+ }
+ }
+}
+
void ui_rgb_to_color_picker_compat_v(const float rgb[3], float r_cp[3])
{
switch (U.color_picker_type) {
@@ -131,6 +146,7 @@ void ui_scene_linear_to_color_picker_space(uiBut *but, float rgb[3])
* space for intuitive color picking. */
if (!ui_but_is_color_gamma(but)) {
IMB_colormanagement_scene_linear_to_color_picking_v3(rgb);
+ ui_color_picker_rgb_round(rgb);
}
}
@@ -138,6 +154,7 @@ void ui_color_picker_to_scene_linear_space(uiBut *but, float rgb[3])
{
if (!ui_but_is_color_gamma(but)) {
IMB_colormanagement_color_picking_to_scene_linear_v3(rgb);
+ ui_color_picker_rgb_round(rgb);
}
}
@@ -201,6 +218,7 @@ static void ui_update_color_picker_buts_rgb(uiBut *from_but,
copy_v3_v3(rgb_hex, rgb);
if (from_but && !ui_but_is_color_gamma(from_but)) {
IMB_colormanagement_scene_linear_to_srgb_v3(rgb_hex);
+ ui_color_picker_rgb_round(rgb_hex);
}
rgb_float_to_uchar(rgb_hex_uchar, rgb_hex);
@@ -287,6 +305,7 @@ static void ui_colorpicker_hex_rna_cb(bContext *UNUSED(C), void *bt1, void *hexc
/* Hex code is assumed to be in sRGB space (coming from other applications, web, etc) */
if (!ui_but_is_color_gamma(but)) {
IMB_colormanagement_srgb_to_scene_linear_v3(rgb);
+ ui_color_picker_rgb_round(rgb);
}
ui_update_color_picker_buts_rgb(but, but->block, cpicker, rgb);
@@ -765,6 +784,7 @@ static void ui_block_colorpicker(uiBlock *block, uiBut *from_but, float rgba[4],
if (!ui_but_is_color_gamma(from_but)) {
IMB_colormanagement_scene_linear_to_srgb_v3(rgb_hex);
+ ui_color_picker_rgb_round(rgb_hex);
}
rgb_float_to_uchar(rgb_hex_uchar, rgb_hex);
diff --git a/source/blender/editors/interface/interface_region_hud.c b/source/blender/editors/interface/interface_region_hud.c
index 6d1b2baeff9..43afdc534ad 100644
--- a/source/blender/editors/interface/interface_region_hud.c
+++ b/source/blender/editors/interface/interface_region_hud.c
@@ -27,6 +27,7 @@
#include "MEM_guardedalloc.h"
+#include "DNA_screen_types.h"
#include "DNA_userdef_types.h"
#include "BLI_string.h"
@@ -231,6 +232,11 @@ ARegionType *ED_area_type_hud(int space_type)
art->init = hud_region_init;
art->free = hud_region_free;
+ /* We need to indicate a preferred size to avoid false `RGN_FLAG_TOO_SMALL`
+ * the first time the region is created. */
+ art->prefsizex = AREAMINX;
+ art->prefsizey = HEADERY;
+
hud_panels_register(art, space_type, art->regionid);
art->lock = 1; /* can become flag, see BKE_spacedata_draw_locks */
diff --git a/source/blender/editors/interface/interface_region_popover.c b/source/blender/editors/interface/interface_region_popover.c
index 22c62ecd6f7..53c96fb72a7 100644
--- a/source/blender/editors/interface/interface_region_popover.c
+++ b/source/blender/editors/interface/interface_region_popover.c
@@ -355,7 +355,7 @@ uiPopover *UI_popover_begin(bContext *C, int ui_size_x)
}
pup->ui_size_x = ui_size_x;
- /* Opertor context default same as menus, change if needed. */
+ /* Operator context default same as menus, change if needed. */
ui_popover_create_block(C, pup, WM_OP_EXEC_REGION_WIN);
/* create in advance so we can let buttons point to retval already */
@@ -404,7 +404,7 @@ void UI_popover_end(bContext *C, uiPopover *pup, wmKeyMap *keymap)
/* TODO(campbell): we may want to make this configurable.
* The begin/end stype of calling popups doesn't allow to 'can_refresh' to be set.
- * For now close this style of popvers when accessed. */
+ * For now close this style of popovers when accessed. */
UI_block_flag_disable(pup->block, UI_BLOCK_KEEP_OPEN);
/* panels are created flipped (from event handling pov) */
diff --git a/source/blender/editors/interface/interface_templates.c b/source/blender/editors/interface/interface_templates.c
index 5d3ef5c625e..1fc1af9815f 100644
--- a/source/blender/editors/interface/interface_templates.c
+++ b/source/blender/editors/interface/interface_templates.c
@@ -952,7 +952,7 @@ static void template_ID(bContext *C,
/* Due to space limit in UI - skip the "open" icon for packed data, and allow to unpack.
* Only for images, sound and fonts */
- if (id && BKE_pack_check(id)) {
+ if (id && BKE_packedfile_id_check(id)) {
but = uiDefIconButO(block,
UI_BTYPE_BUT,
"FILE_OT_unpack_item",
diff --git a/source/blender/editors/interface/interface_widgets.c b/source/blender/editors/interface/interface_widgets.c
index ec0b01d4341..0bf8247dc17 100644
--- a/source/blender/editors/interface/interface_widgets.c
+++ b/source/blender/editors/interface/interface_widgets.c
@@ -2636,7 +2636,7 @@ static void widget_state_numslider(uiWidgetType *wt, int state, int drawflag)
wt->wcol.item[0] = wt->wcol.item[1] = wt->wcol.item[2] = rgb_to_grayscale_byte(
(const uchar *)wt->wcol.item);
widget_state_blend(wt->wcol.item, color_blend, wcol_state->blend);
- rgb_ensure_contrast(wt->wcol.item, wt->wcol.inner, 20);
+ rgb_ensure_contrast(wt->wcol.item, wt->wcol.inner, 30);
}
if (state & UI_SELECT) {
diff --git a/source/blender/editors/interface/resources.c b/source/blender/editors/interface/resources.c
index e281c6c9e9c..25116934b06 100644
--- a/source/blender/editors/interface/resources.c
+++ b/source/blender/editors/interface/resources.c
@@ -901,6 +901,12 @@ const uchar *UI_ThemeGetColorPtr(bTheme *btheme, int spacetype, int colorid)
case TH_ICON_SHADING:
cp = btheme->tui.icon_shading;
break;
+ case TH_ICON_FUND: {
+ /* Development fund icon color is not part of theme. */
+ static const char red[4] = {204, 48, 72, 255};
+ cp = red;
+ break;
+ }
case TH_SCROLL_TEXT:
cp = btheme->tui.wcol_scroll.text;
@@ -1377,12 +1383,14 @@ bool UI_GetIconThemeColor4ubv(int colorid, uchar col[4])
if (colorid == 0) {
return false;
}
-
- /* 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_WINDOW) ||
- (theme_spacetype == SPACE_PROPERTIES && theme_regionid == RGN_TYPE_NAV_BAR))) {
+ else if (colorid == TH_ICON_FUND) {
+ /* Always color development fund icon. */
+ }
+ else if (!((theme_spacetype == SPACE_OUTLINER && theme_regionid == RGN_TYPE_WINDOW) ||
+ (theme_spacetype == SPACE_PROPERTIES && theme_regionid == RGN_TYPE_NAV_BAR))) {
+ /* 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. */
return false;
}
diff --git a/source/blender/editors/io/io_collada.c b/source/blender/editors/io/io_collada.c
index 1f844961d19..dad84c87fd7 100644
--- a/source/blender/editors/io/io_collada.c
+++ b/source/blender/editors/io/io_collada.c
@@ -593,8 +593,8 @@ void WM_OT_collada_export(wmOperatorType *ot)
"apply_global_orientation",
false,
"Apply Global Orientation",
- "enabled: Rotate all root objects to match the global orientation "
- "settings.\ndisabled: set global orientation in Collada assets");
+ "Rotate all root objects to match the global orientation settings "
+ "otherwise set the global orientation per Collada asset");
RNA_def_boolean(func, "selected", false, "Selection Only", "Export only selected elements");
@@ -726,8 +726,8 @@ void WM_OT_collada_export(wmOperatorType *ot)
INT_MIN,
INT_MAX,
"Transform",
- "Transformation type for translation, scale and rotation\n"
- "Note: The Animation transformation type in the Anim Tab\n"
+ "Transformation type for translation, scale and rotation. "
+ "Note: The Animation transformation type in the Anim Tab "
"is always equal to the Object transformation type in the Geom tab",
INT_MIN,
INT_MAX);
@@ -737,8 +737,8 @@ void WM_OT_collada_export(wmOperatorType *ot)
prop_bc_export_transformation_type,
0,
"Transform",
- "Transformation type for translation, scale and rotation\n"
- "Note: The Animation transformation type in the Anim Tab\n"
+ "Transformation type for translation, scale and rotation. "
+ "Note: The Animation transformation type in the Anim Tab "
"is always equal to the Object transformation type in the Geom tab");
RNA_def_boolean(func,
diff --git a/source/blender/editors/lattice/editlattice_undo.c b/source/blender/editors/lattice/editlattice_undo.c
index 166201adc15..abc5224c4d6 100644
--- a/source/blender/editors/lattice/editlattice_undo.c
+++ b/source/blender/editors/lattice/editlattice_undo.c
@@ -68,9 +68,19 @@ typedef struct UndoLattice {
static void undolatt_to_editlatt(UndoLattice *ult, EditLatt *editlatt)
{
- int len = editlatt->latt->pntsu * editlatt->latt->pntsv * editlatt->latt->pntsw;
+ const int len_src = ult->pntsu * ult->pntsv * ult->pntsw;
+ const int len_dst = editlatt->latt->pntsu * editlatt->latt->pntsv * editlatt->latt->pntsw;
+ if (len_src != len_dst) {
+ MEM_freeN(editlatt->latt->def);
+ editlatt->latt->def = MEM_dupallocN(ult->def);
+ }
+ else {
+ memcpy(editlatt->latt->def, ult->def, sizeof(BPoint) * len_src);
+ }
- memcpy(editlatt->latt->def, ult->def, sizeof(BPoint) * len);
+ editlatt->latt->pntsu = ult->pntsu;
+ editlatt->latt->pntsv = ult->pntsv;
+ editlatt->latt->pntsw = ult->pntsw;
editlatt->latt->actbp = ult->actbp;
}
@@ -176,7 +186,8 @@ static bool lattice_undosys_step_encode(struct bContext *C,
static void lattice_undosys_step_decode(struct bContext *C,
struct Main *UNUSED(bmain),
UndoStep *us_p,
- int UNUSED(dir))
+ int UNUSED(dir),
+ bool UNUSED(is_final))
{
LatticeUndoStep *us = (LatticeUndoStep *)us_p;
diff --git a/source/blender/editors/mask/mask_add.c b/source/blender/editors/mask/mask_add.c
index fc85eab6e66..883dfe9ad7c 100644
--- a/source/blender/editors/mask/mask_add.c
+++ b/source/blender/editors/mask/mask_add.c
@@ -869,7 +869,7 @@ static int primitive_add_invoke(bContext *C, wmOperator *op, const wmEvent *UNUS
return op->type->exec(C, op);
}
-static void define_prinitive_add_properties(wmOperatorType *ot)
+static void define_primitive_add_properties(wmOperatorType *ot)
{
RNA_def_float(
ot->srna, "size", 100, -FLT_MAX, FLT_MAX, "Size", "Size of new circle", -FLT_MAX, FLT_MAX);
@@ -913,7 +913,7 @@ void MASK_OT_primitive_circle_add(wmOperatorType *ot)
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
/* properties */
- define_prinitive_add_properties(ot);
+ define_primitive_add_properties(ot);
}
/******************** primitive add suqare *********************/
@@ -944,5 +944,5 @@ void MASK_OT_primitive_square_add(wmOperatorType *ot)
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
/* properties */
- define_prinitive_add_properties(ot);
+ define_primitive_add_properties(ot);
}
diff --git a/source/blender/editors/mask/mask_ops.c b/source/blender/editors/mask/mask_ops.c
index a205f6878e3..8e4efddd8a7 100644
--- a/source/blender/editors/mask/mask_ops.c
+++ b/source/blender/editors/mask/mask_ops.c
@@ -441,6 +441,7 @@ static int masklay_new_exec(bContext *C, wmOperator *op)
mask->masklay_act = mask->masklay_tot - 1;
WM_event_add_notifier(C, NC_MASK | NA_EDITED, mask);
+ DEG_id_tag_update(&mask->id, ID_RECALC_COPY_ON_WRITE);
return OPERATOR_FINISHED;
}
@@ -474,6 +475,7 @@ static int masklay_remove_exec(bContext *C, wmOperator *UNUSED(op))
BKE_mask_layer_remove(mask, masklay);
WM_event_add_notifier(C, NC_MASK | NA_EDITED, mask);
+ DEG_id_tag_update(&mask->id, ID_RECALC_COPY_ON_WRITE);
}
return OPERATOR_FINISHED;
@@ -2206,6 +2208,7 @@ static int mask_layer_move_exec(bContext *C, wmOperator *op)
}
WM_event_add_notifier(C, NC_MASK | NA_EDITED, mask);
+ DEG_id_tag_update(&mask->id, ID_RECALC_COPY_ON_WRITE);
return OPERATOR_FINISHED;
}
diff --git a/source/blender/editors/mesh/editmesh_bevel.c b/source/blender/editors/mesh/editmesh_bevel.c
index 78b4cfe38d4..b4ef2620895 100644
--- a/source/blender/editors/mesh/editmesh_bevel.c
+++ b/source/blender/editors/mesh/editmesh_bevel.c
@@ -263,14 +263,14 @@ static bool edbm_bevel_init(bContext *C, wmOperator *op, const bool is_modal)
initNumInput(&opdata->num_input[i]);
opdata->num_input[i].idx_max = 0;
opdata->num_input[i].val_flag[0] |= NUM_NO_NEGATIVE;
+ opdata->num_input[i].unit_type[0] = B_UNIT_NONE;
if (i == SEGMENTS_VALUE) {
opdata->num_input[i].val_flag[0] |= NUM_NO_FRACTION | NUM_NO_ZERO;
}
if (i == OFFSET_VALUE) {
opdata->num_input[i].unit_sys = scene->unit.system;
+ opdata->num_input[i].unit_type[0] = B_UNIT_LENGTH;
}
- /* Not sure this is a factor or a unit? */
- opdata->num_input[i].unit_type[0] = B_UNIT_NONE;
}
/* avoid the cost of allocating a bm copy */
diff --git a/source/blender/editors/mesh/editmesh_tools.c b/source/blender/editors/mesh/editmesh_tools.c
index 26d830ccaec..919de4cdb20 100644
--- a/source/blender/editors/mesh/editmesh_tools.c
+++ b/source/blender/editors/mesh/editmesh_tools.c
@@ -534,6 +534,9 @@ static int edbm_delete_exec(bContext *C, wmOperator *op)
EDBM_flag_disable_all(em, BM_ELEM_SELECT);
EDBM_update_generic(em, true, true);
+
+ DEG_id_tag_update(obedit->data, ID_RECALC_SELECT);
+ WM_event_add_notifier(C, NC_GEOM | ND_SELECT, obedit->data);
}
MEM_freeN(objects);
@@ -7415,7 +7418,7 @@ void MESH_OT_symmetry_snap(struct wmOperatorType *ot)
#ifdef WITH_FREESTYLE
/* -------------------------------------------------------------------- */
-/** \name Mark Edge (FreeStyle) Operator
+/** \name Mark Edge (Freestyle) Operator
* \{ */
static int edbm_mark_freestyle_edge_exec(bContext *C, wmOperator *op)
@@ -7495,7 +7498,7 @@ void MESH_OT_mark_freestyle_edge(wmOperatorType *ot)
/** \} */
/* -------------------------------------------------------------------- */
-/** \name Mark Face (FreeStyle) Operator
+/** \name Mark Face (Freestyle) Operator
* \{ */
static int edbm_mark_freestyle_face_exec(bContext *C, wmOperator *op)
@@ -8015,6 +8018,7 @@ static int edbm_point_normals_invoke(bContext *C, wmOperator *op, const wmEvent
return OPERATOR_RUNNING_MODAL;
}
+/* TODO: make this work on multiple objects at once */
static int edbm_point_normals_exec(bContext *C, wmOperator *op)
{
Object *obedit = CTX_data_edit_object(C);
@@ -8237,44 +8241,54 @@ static void normals_split(BMesh *bm)
static int normals_split_merge(bContext *C, const bool do_merge)
{
- Object *obedit = CTX_data_edit_object(C);
- BMEditMesh *em = BKE_editmesh_from_object(obedit);
- BMesh *bm = em->bm;
- BMEdge *e;
- BMIter eiter;
+ ViewLayer *view_layer = CTX_data_view_layer(C);
+ uint objects_len = 0;
+ Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data(
+ view_layer, CTX_wm_view3d(C), &objects_len);
- BKE_editmesh_ensure_autosmooth(em);
- BKE_editmesh_lnorspace_update(em);
+ for (uint ob_index = 0; ob_index < objects_len; ob_index++) {
+ Object *obedit = objects[ob_index];
+ BMEditMesh *em = BKE_editmesh_from_object(obedit);
+ BMesh *bm = em->bm;
+ BMEdge *e;
+ BMIter eiter;
- /* Note that we need temp lnor editing data for all loops of all affected vertices, since by
- * setting some faces/edges as smooth we are going to change clnors spaces... See also T65809. */
- BMLoopNorEditDataArray *lnors_ed_arr = do_merge ? BM_loop_normal_editdata_array_init(bm, true) :
- NULL;
+ BKE_editmesh_ensure_autosmooth(em);
+ BKE_editmesh_lnorspace_update(em);
- mesh_set_smooth_faces(em, do_merge);
+ /* Note that we need temp lnor editing data for all loops of all affected vertices, since by
+ * setting some faces/edges as smooth we are going to change clnors spaces... See also T65809.
+ */
+ BMLoopNorEditDataArray *lnors_ed_arr = do_merge ?
+ BM_loop_normal_editdata_array_init(bm, true) :
+ NULL;
- BM_ITER_MESH (e, &eiter, bm, BM_EDGES_OF_MESH) {
- if (BM_elem_flag_test(e, BM_ELEM_SELECT)) {
- BM_elem_flag_set(e, BM_ELEM_SMOOTH, do_merge);
+ mesh_set_smooth_faces(em, do_merge);
+
+ BM_ITER_MESH (e, &eiter, bm, BM_EDGES_OF_MESH) {
+ if (BM_elem_flag_test(e, BM_ELEM_SELECT)) {
+ BM_elem_flag_set(e, BM_ELEM_SMOOTH, do_merge);
+ }
}
- }
- bm->spacearr_dirty |= BM_SPACEARR_DIRTY_ALL;
- BKE_editmesh_lnorspace_update(em);
+ bm->spacearr_dirty |= BM_SPACEARR_DIRTY_ALL;
+ BKE_editmesh_lnorspace_update(em);
- if (do_merge) {
- normals_merge(bm, lnors_ed_arr);
- }
- else {
- normals_split(bm);
- }
+ if (do_merge) {
+ normals_merge(bm, lnors_ed_arr);
+ }
+ else {
+ normals_split(bm);
+ }
- if (lnors_ed_arr) {
- BM_loop_normal_editdata_array_free(lnors_ed_arr);
- }
+ if (lnors_ed_arr) {
+ BM_loop_normal_editdata_array_free(lnors_ed_arr);
+ }
- EDBM_update_generic(em, true, false);
+ EDBM_update_generic(em, true, false);
+ }
+ MEM_freeN(objects);
return OPERATOR_FINISHED;
}
@@ -8343,131 +8357,140 @@ static EnumPropertyItem average_method_items[] = {
static int edbm_average_normals_exec(bContext *C, wmOperator *op)
{
- Object *obedit = CTX_data_edit_object(C);
- BMEditMesh *em = BKE_editmesh_from_object(obedit);
- BMesh *bm = em->bm;
- BMFace *f;
- 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);
-
+ ViewLayer *view_layer = CTX_data_view_layer(C);
+ uint objects_len = 0;
+ Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data(
+ view_layer, CTX_wm_view3d(C), &objects_len);
const int average_type = RNA_enum_get(op->ptr, "average_type");
- const int cd_clnors_offset = CustomData_get_offset(&bm->ldata, CD_CUSTOMLOOPNORMAL);
const float absweight = (float)RNA_int_get(op->ptr, "weight");
const float threshold = RNA_float_get(op->ptr, "threshold");
- float weight = absweight / 50.0f;
- if (absweight == 100.0f) {
- weight = (float)SHRT_MAX;
- }
- else if (absweight == 1.0f) {
- weight = 1 / (float)SHRT_MAX;
- }
- else if ((weight - 1) * 25 > 1) {
- weight = (weight - 1) * 25;
- }
+ for (uint ob_index = 0; ob_index < objects_len; ob_index++) {
+ Object *obedit = objects[ob_index];
+ BMEditMesh *em = BKE_editmesh_from_object(obedit);
+ BMesh *bm = em->bm;
+ BMFace *f;
+ BMLoop *l, *l_curr, *l_first;
+ BMIter fiter;
- BM_normals_loops_edges_tag(bm, true);
+ BKE_editmesh_ensure_autosmooth(em);
+ bm->spacearr_dirty |= BM_SPACEARR_DIRTY_ALL;
+ BKE_editmesh_lnorspace_update(em);
- HeapSimple *loop_weight = BLI_heapsimple_new();
+ const int cd_clnors_offset = CustomData_get_offset(&bm->ldata, CD_CUSTOMLOOPNORMAL);
- BM_ITER_MESH (f, &fiter, bm, BM_FACES_OF_MESH) {
- l_curr = l_first = BM_FACE_FIRST_LOOP(f);
- do {
- if (BM_elem_flag_test(l_curr->v, BM_ELEM_SELECT) &&
- (!BM_elem_flag_test(l_curr->e, BM_ELEM_TAG) ||
- (!BM_elem_flag_test(l_curr, BM_ELEM_TAG) && BM_loop_check_cyclic_smooth_fan(l_curr)))) {
- if (!BM_elem_flag_test(l_curr->e, BM_ELEM_TAG) &&
- !BM_elem_flag_test(l_curr->prev->e, BM_ELEM_TAG)) {
- const int loop_index = BM_elem_index_get(l_curr);
- short *clnors = BM_ELEM_CD_GET_VOID_P(l_curr, cd_clnors_offset);
- BKE_lnor_space_custom_normal_to_data(
- bm->lnor_spacearr->lspacearr[loop_index], f->no, clnors);
- }
- else {
- BMVert *v_pivot = l_curr->v;
- UNUSED_VARS_NDEBUG(v_pivot);
- BMEdge *e_next;
- const BMEdge *e_org = l_curr->e;
- BMLoop *lfan_pivot, *lfan_pivot_next;
+ float weight = absweight / 50.0f;
+ if (absweight == 100.0f) {
+ weight = (float)SHRT_MAX;
+ }
+ else if (absweight == 1.0f) {
+ weight = 1 / (float)SHRT_MAX;
+ }
+ else if ((weight - 1) * 25 > 1) {
+ weight = (weight - 1) * 25;
+ }
- lfan_pivot = l_curr;
- e_next = lfan_pivot->e;
+ BM_normals_loops_edges_tag(bm, true);
- while (true) {
- lfan_pivot_next = BM_vert_step_fan_loop(lfan_pivot, &e_next);
- if (lfan_pivot_next) {
- BLI_assert(lfan_pivot_next->v == v_pivot);
- }
- else {
- e_next = (lfan_pivot->e == e_next) ? lfan_pivot->prev->e : lfan_pivot->e;
- }
+ HeapSimple *loop_weight = BLI_heapsimple_new();
- float val = 1.0f;
- if (average_type == EDBM_CLNOR_AVERAGE_FACE_AREA) {
- val = 1.0f / BM_face_calc_area(lfan_pivot->f);
- }
- else if (average_type == EDBM_CLNOR_AVERAGE_ANGLE) {
- val = 1.0f / BM_loop_calc_face_angle(lfan_pivot);
- }
+ BM_ITER_MESH (f, &fiter, bm, BM_FACES_OF_MESH) {
+ l_curr = l_first = BM_FACE_FIRST_LOOP(f);
+ do {
+ if (BM_elem_flag_test(l_curr->v, BM_ELEM_SELECT) &&
+ (!BM_elem_flag_test(l_curr->e, BM_ELEM_TAG) ||
+ (!BM_elem_flag_test(l_curr, BM_ELEM_TAG) &&
+ BM_loop_check_cyclic_smooth_fan(l_curr)))) {
+ if (!BM_elem_flag_test(l_curr->e, BM_ELEM_TAG) &&
+ !BM_elem_flag_test(l_curr->prev->e, BM_ELEM_TAG)) {
+ const int loop_index = BM_elem_index_get(l_curr);
+ short *clnors = BM_ELEM_CD_GET_VOID_P(l_curr, cd_clnors_offset);
+ BKE_lnor_space_custom_normal_to_data(
+ bm->lnor_spacearr->lspacearr[loop_index], f->no, clnors);
+ }
+ else {
+ BMVert *v_pivot = l_curr->v;
+ UNUSED_VARS_NDEBUG(v_pivot);
+ BMEdge *e_next;
+ const BMEdge *e_org = l_curr->e;
+ BMLoop *lfan_pivot, *lfan_pivot_next;
+
+ lfan_pivot = l_curr;
+ e_next = lfan_pivot->e;
+
+ while (true) {
+ lfan_pivot_next = BM_vert_step_fan_loop(lfan_pivot, &e_next);
+ if (lfan_pivot_next) {
+ BLI_assert(lfan_pivot_next->v == v_pivot);
+ }
+ else {
+ e_next = (lfan_pivot->e == e_next) ? lfan_pivot->prev->e : lfan_pivot->e;
+ }
- BLI_heapsimple_insert(loop_weight, val, lfan_pivot);
+ float val = 1.0f;
+ if (average_type == EDBM_CLNOR_AVERAGE_FACE_AREA) {
+ val = 1.0f / BM_face_calc_area(lfan_pivot->f);
+ }
+ else if (average_type == EDBM_CLNOR_AVERAGE_ANGLE) {
+ val = 1.0f / BM_loop_calc_face_angle(lfan_pivot);
+ }
- if (!BM_elem_flag_test(e_next, BM_ELEM_TAG) || (e_next == e_org)) {
- break;
- }
- lfan_pivot = lfan_pivot_next;
- }
+ BLI_heapsimple_insert(loop_weight, val, lfan_pivot);
- BLI_SMALLSTACK_DECLARE(loops, BMLoop *);
- float wnor[3], avg_normal[3] = {0.0f}, count = 0;
- float val = BLI_heapsimple_top_value(loop_weight);
-
- while (!BLI_heapsimple_is_empty(loop_weight)) {
- const float cur_val = BLI_heapsimple_top_value(loop_weight);
- if (!compare_ff(val, cur_val, threshold)) {
- count++;
- val = cur_val;
+ if (!BM_elem_flag_test(e_next, BM_ELEM_TAG) || (e_next == e_org)) {
+ break;
+ }
+ lfan_pivot = lfan_pivot_next;
}
- l = BLI_heapsimple_pop_min(loop_weight);
- BLI_SMALLSTACK_PUSH(loops, l);
- const float n_weight = pow(weight, count);
+ BLI_SMALLSTACK_DECLARE(loops, BMLoop *);
+ float wnor[3], avg_normal[3] = {0.0f}, count = 0;
+ float val = BLI_heapsimple_top_value(loop_weight);
+
+ while (!BLI_heapsimple_is_empty(loop_weight)) {
+ const float cur_val = BLI_heapsimple_top_value(loop_weight);
+ if (!compare_ff(val, cur_val, threshold)) {
+ count++;
+ val = cur_val;
+ }
+ l = BLI_heapsimple_pop_min(loop_weight);
+ BLI_SMALLSTACK_PUSH(loops, l);
+
+ const float n_weight = pow(weight, count);
+
+ if (average_type == EDBM_CLNOR_AVERAGE_LOOP) {
+ const int l_index = BM_elem_index_get(l);
+ short *clnors = BM_ELEM_CD_GET_VOID_P(l, cd_clnors_offset);
+ BKE_lnor_space_custom_data_to_normal(
+ bm->lnor_spacearr->lspacearr[l_index], clnors, wnor);
+ }
+ else {
+ copy_v3_v3(wnor, l->f->no);
+ }
+ mul_v3_fl(wnor, (1.0f / cur_val) * (1.0f / n_weight));
+ add_v3_v3(avg_normal, wnor);
+ }
- if (average_type == EDBM_CLNOR_AVERAGE_LOOP) {
+ if (normalize_v3(avg_normal) < CLNORS_VALID_VEC_LEN) {
+ /* If avg normal is nearly 0, set clnor to default value. */
+ zero_v3(avg_normal);
+ }
+ while ((l = BLI_SMALLSTACK_POP(loops))) {
const int l_index = BM_elem_index_get(l);
short *clnors = BM_ELEM_CD_GET_VOID_P(l, cd_clnors_offset);
- BKE_lnor_space_custom_data_to_normal(
- bm->lnor_spacearr->lspacearr[l_index], clnors, wnor);
- }
- else {
- copy_v3_v3(wnor, l->f->no);
+ BKE_lnor_space_custom_normal_to_data(
+ bm->lnor_spacearr->lspacearr[l_index], avg_normal, clnors);
}
- mul_v3_fl(wnor, (1.0f / cur_val) * (1.0f / n_weight));
- add_v3_v3(avg_normal, wnor);
- }
-
- if (normalize_v3(avg_normal) < CLNORS_VALID_VEC_LEN) {
- /* If avg normal is nearly 0, set clnor to default value. */
- zero_v3(avg_normal);
- }
- while ((l = BLI_SMALLSTACK_POP(loops))) {
- const int l_index = BM_elem_index_get(l);
- short *clnors = BM_ELEM_CD_GET_VOID_P(l, cd_clnors_offset);
- BKE_lnor_space_custom_normal_to_data(
- bm->lnor_spacearr->lspacearr[l_index], avg_normal, clnors);
}
}
- }
- } while ((l_curr = l_curr->next) != l_first);
- }
+ } while ((l_curr = l_curr->next) != l_first);
+ }
- BLI_heapsimple_free(loop_weight, NULL);
- EDBM_update_generic(em, true, false);
+ BLI_heapsimple_free(loop_weight, NULL);
+ EDBM_update_generic(em, true, false);
+ }
+ MEM_freeN(objects);
return OPERATOR_FINISHED;
}
@@ -8566,135 +8589,151 @@ static EnumPropertyItem normal_vector_tool_items[] = {
static int edbm_normals_tools_exec(bContext *C, wmOperator *op)
{
- Object *obedit = CTX_data_edit_object(C);
Scene *scene = CTX_data_scene(C);
- BMEditMesh *em = BKE_editmesh_from_object(obedit);
- BMesh *bm = em->bm;
-
- if (bm->totloop == 0) {
- return OPERATOR_CANCELLED;
- }
-
+ ViewLayer *view_layer = CTX_data_view_layer(C);
+ uint objects_len = 0;
+ Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data(
+ view_layer, CTX_wm_view3d(C), &objects_len);
const int mode = RNA_enum_get(op->ptr, "mode");
const bool absolute = RNA_boolean_get(op->ptr, "absolute");
+ float *normal_vector = scene->toolsettings->normal_vector;
+ bool done_copy = false;
- BKE_editmesh_ensure_autosmooth(em);
- BKE_editmesh_lnorspace_update(em);
- BMLoopNorEditDataArray *lnors_ed_arr = BM_loop_normal_editdata_array_init(bm, false);
- BMLoopNorEditData *lnor_ed = lnors_ed_arr->lnor_editdata;
+ for (uint ob_index = 0; ob_index < objects_len; ob_index++) {
+ Object *obedit = objects[ob_index];
+ BMEditMesh *em = BKE_editmesh_from_object(obedit);
+ BMesh *bm = em->bm;
- float *normal_vector = scene->toolsettings->normal_vector;
+ if (bm->totloop == 0) {
+ continue;
+ }
- switch (mode) {
- case EDBM_CLNOR_TOOLS_COPY:
- if (bm->totfacesel != 1 && lnors_ed_arr->totloop != 1 && bm->totvertsel != 1) {
- BKE_report(op->reports,
- RPT_ERROR,
- "Can only copy one custom normal, vertex normal or face normal");
- BM_loop_normal_editdata_array_free(lnors_ed_arr);
- return OPERATOR_CANCELLED;
- }
- if (lnors_ed_arr->totloop == 1) {
- copy_v3_v3(scene->toolsettings->normal_vector, lnors_ed_arr->lnor_editdata->nloc);
- }
- else if (bm->totfacesel == 1) {
- BMFace *f;
- BMIter fiter;
- BM_ITER_MESH (f, &fiter, bm, BM_FACES_OF_MESH) {
- if (BM_elem_flag_test(f, BM_ELEM_SELECT)) {
- copy_v3_v3(scene->toolsettings->normal_vector, f->no);
- }
+ BKE_editmesh_ensure_autosmooth(em);
+ BKE_editmesh_lnorspace_update(em);
+ BMLoopNorEditDataArray *lnors_ed_arr = BM_loop_normal_editdata_array_init(bm, false);
+ BMLoopNorEditData *lnor_ed = lnors_ed_arr->lnor_editdata;
+
+ switch (mode) {
+ case EDBM_CLNOR_TOOLS_COPY:
+ if (bm->totfacesel == 0 || bm->totvertsel == 0) {
+ BM_loop_normal_editdata_array_free(lnors_ed_arr);
+ continue;
}
- }
- else {
- /* 'Vertex' normal, i.e. common set of loop normals on the same vertex,
- * only if they are all the same. */
- bool are_same_lnors = true;
- for (int i = 0; i < lnors_ed_arr->totloop; i++, lnor_ed++) {
- if (!compare_v3v3(lnors_ed_arr->lnor_editdata->nloc, lnor_ed->nloc, 1e-4f)) {
- are_same_lnors = false;
- }
+
+ if (done_copy ||
+ (bm->totfacesel != 1 && lnors_ed_arr->totloop != 1 && bm->totvertsel != 1)) {
+ BKE_report(op->reports,
+ RPT_ERROR,
+ "Can only copy one custom normal, vertex normal or face normal");
+ BM_loop_normal_editdata_array_free(lnors_ed_arr);
+ continue;
}
- if (are_same_lnors) {
+ if (lnors_ed_arr->totloop == 1) {
copy_v3_v3(scene->toolsettings->normal_vector, lnors_ed_arr->lnor_editdata->nloc);
}
- }
- break;
+ else if (bm->totfacesel == 1) {
+ BMFace *f;
+ BMIter fiter;
+ BM_ITER_MESH (f, &fiter, bm, BM_FACES_OF_MESH) {
+ if (BM_elem_flag_test(f, BM_ELEM_SELECT)) {
+ copy_v3_v3(scene->toolsettings->normal_vector, f->no);
+ }
+ }
+ }
+ else {
+ /* 'Vertex' normal, i.e. common set of loop normals on the same vertex,
+ * only if they are all the same. */
+ bool are_same_lnors = true;
+ for (int i = 0; i < lnors_ed_arr->totloop; i++, lnor_ed++) {
+ if (!compare_v3v3(lnors_ed_arr->lnor_editdata->nloc, lnor_ed->nloc, 1e-4f)) {
+ are_same_lnors = false;
+ }
+ }
+ if (are_same_lnors) {
+ copy_v3_v3(scene->toolsettings->normal_vector, lnors_ed_arr->lnor_editdata->nloc);
+ }
+ }
+ done_copy = true;
+ break;
- case EDBM_CLNOR_TOOLS_PASTE:
- if (!absolute) {
- if (normalize_v3(normal_vector) < CLNORS_VALID_VEC_LEN) {
- /* If normal is nearly 0, do nothing. */
- break;
+ case EDBM_CLNOR_TOOLS_PASTE:
+ if (!absolute) {
+ if (normalize_v3(normal_vector) < CLNORS_VALID_VEC_LEN) {
+ /* If normal is nearly 0, do nothing. */
+ break;
+ }
}
- }
- for (int i = 0; i < lnors_ed_arr->totloop; i++, lnor_ed++) {
- if (absolute) {
- float abs_normal[3];
- copy_v3_v3(abs_normal, lnor_ed->loc);
- negate_v3(abs_normal);
- add_v3_v3(abs_normal, normal_vector);
+ for (int i = 0; i < lnors_ed_arr->totloop; i++, lnor_ed++) {
+ if (absolute) {
+ float abs_normal[3];
+ copy_v3_v3(abs_normal, lnor_ed->loc);
+ negate_v3(abs_normal);
+ add_v3_v3(abs_normal, normal_vector);
+
+ if (normalize_v3(abs_normal) < CLNORS_VALID_VEC_LEN) {
+ /* If abs normal is nearly 0, set clnor to initial value. */
+ copy_v3_v3(abs_normal, lnor_ed->niloc);
+ }
+ BKE_lnor_space_custom_normal_to_data(bm->lnor_spacearr->lspacearr[lnor_ed->loop_index],
+ abs_normal,
+ lnor_ed->clnors_data);
+ }
+ else {
+ BKE_lnor_space_custom_normal_to_data(bm->lnor_spacearr->lspacearr[lnor_ed->loop_index],
+ normal_vector,
+ lnor_ed->clnors_data);
+ }
+ }
+ break;
- if (normalize_v3(abs_normal) < CLNORS_VALID_VEC_LEN) {
+ case EDBM_CLNOR_TOOLS_MULTIPLY:
+ for (int i = 0; i < lnors_ed_arr->totloop; i++, lnor_ed++) {
+ mul_v3_v3(lnor_ed->nloc, normal_vector);
+
+ if (normalize_v3(lnor_ed->nloc) < CLNORS_VALID_VEC_LEN) {
/* If abs normal is nearly 0, set clnor to initial value. */
- copy_v3_v3(abs_normal, lnor_ed->niloc);
+ copy_v3_v3(lnor_ed->nloc, lnor_ed->niloc);
}
- BKE_lnor_space_custom_normal_to_data(
- bm->lnor_spacearr->lspacearr[lnor_ed->loop_index], abs_normal, lnor_ed->clnors_data);
- }
- else {
BKE_lnor_space_custom_normal_to_data(bm->lnor_spacearr->lspacearr[lnor_ed->loop_index],
- normal_vector,
+ lnor_ed->nloc,
lnor_ed->clnors_data);
}
- }
- break;
+ break;
- case EDBM_CLNOR_TOOLS_MULTIPLY:
- for (int i = 0; i < lnors_ed_arr->totloop; i++, lnor_ed++) {
- mul_v3_v3(lnor_ed->nloc, normal_vector);
+ case EDBM_CLNOR_TOOLS_ADD:
+ for (int i = 0; i < lnors_ed_arr->totloop; i++, lnor_ed++) {
+ add_v3_v3(lnor_ed->nloc, normal_vector);
- if (normalize_v3(lnor_ed->nloc) < CLNORS_VALID_VEC_LEN) {
- /* If abs normal is nearly 0, set clnor to initial value. */
- copy_v3_v3(lnor_ed->nloc, lnor_ed->niloc);
+ if (normalize_v3(lnor_ed->nloc) < CLNORS_VALID_VEC_LEN) {
+ /* If abs normal is nearly 0, set clnor to initial value. */
+ copy_v3_v3(lnor_ed->nloc, lnor_ed->niloc);
+ }
+ BKE_lnor_space_custom_normal_to_data(bm->lnor_spacearr->lspacearr[lnor_ed->loop_index],
+ lnor_ed->nloc,
+ lnor_ed->clnors_data);
}
- BKE_lnor_space_custom_normal_to_data(bm->lnor_spacearr->lspacearr[lnor_ed->loop_index],
- lnor_ed->nloc,
- lnor_ed->clnors_data);
- }
- break;
-
- case EDBM_CLNOR_TOOLS_ADD:
- for (int i = 0; i < lnors_ed_arr->totloop; i++, lnor_ed++) {
- add_v3_v3(lnor_ed->nloc, normal_vector);
+ break;
- if (normalize_v3(lnor_ed->nloc) < CLNORS_VALID_VEC_LEN) {
- /* If abs normal is nearly 0, set clnor to initial value. */
- copy_v3_v3(lnor_ed->nloc, lnor_ed->niloc);
+ case EDBM_CLNOR_TOOLS_RESET:
+ zero_v3(normal_vector);
+ for (int i = 0; i < lnors_ed_arr->totloop; i++, lnor_ed++) {
+ BKE_lnor_space_custom_normal_to_data(bm->lnor_spacearr->lspacearr[lnor_ed->loop_index],
+ normal_vector,
+ lnor_ed->clnors_data);
}
- BKE_lnor_space_custom_normal_to_data(bm->lnor_spacearr->lspacearr[lnor_ed->loop_index],
- lnor_ed->nloc,
- lnor_ed->clnors_data);
- }
- break;
+ break;
- case EDBM_CLNOR_TOOLS_RESET:
- zero_v3(normal_vector);
- for (int i = 0; i < lnors_ed_arr->totloop; i++, lnor_ed++) {
- BKE_lnor_space_custom_normal_to_data(bm->lnor_spacearr->lspacearr[lnor_ed->loop_index],
- normal_vector,
- lnor_ed->clnors_data);
- }
- break;
+ default:
+ BLI_assert(0);
+ break;
+ }
- default:
- BLI_assert(0);
- break;
- }
+ BM_loop_normal_editdata_array_free(lnors_ed_arr);
- BM_loop_normal_editdata_array_free(lnors_ed_arr);
+ EDBM_update_generic(em, true, false);
+ }
- EDBM_update_generic(em, true, false);
+ MEM_freeN(objects);
return OPERATOR_FINISHED;
}
@@ -8841,8 +8880,8 @@ static int edbm_set_normals_from_faces_exec(bContext *C, wmOperator *op)
MEM_freeN(vnors);
EDBM_update_generic(em, true, false);
}
- MEM_freeN(objects);
+ MEM_freeN(objects);
return OPERATOR_FINISHED;
}
@@ -8865,77 +8904,86 @@ void MESH_OT_set_normals_from_faces(struct wmOperatorType *ot)
static int edbm_smoothen_normals_exec(bContext *C, wmOperator *op)
{
- Object *obedit = CTX_data_edit_object(C);
- BMEditMesh *em = BKE_editmesh_from_object(obedit);
- BMesh *bm = em->bm;
- BMFace *f;
- 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, false);
-
- float(*smooth_normal)[3] = MEM_callocN(sizeof(*smooth_normal) * lnors_ed_arr->totloop, __func__);
+ ViewLayer *view_layer = CTX_data_view_layer(C);
+ uint objects_len = 0;
+ Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data(
+ view_layer, CTX_wm_view3d(C), &objects_len);
- /* This is weird choice of operation, taking all loops of faces of current vertex.
- * Could lead to some rather far away loops weighting as much as very close ones
- * (topologically speaking), with complex polygons.
- * Using topological distance here (rather than geometrical one)
- * makes sense imho, but would rather go with a more consistent and flexible code,
- * we could even add max topological distance to take into account, * and a weighting curve.
- * Would do that later though, think for now we can live with that choice. --mont29. */
- BMLoopNorEditData *lnor_ed = lnors_ed_arr->lnor_editdata;
- for (int i = 0; i < lnors_ed_arr->totloop; i++, lnor_ed++) {
- l = lnor_ed->loop;
- float loop_normal[3];
+ for (uint ob_index = 0; ob_index < objects_len; ob_index++) {
+ Object *obedit = objects[ob_index];
+ BMEditMesh *em = BKE_editmesh_from_object(obedit);
+ BMesh *bm = em->bm;
+ BMFace *f;
+ BMLoop *l;
+ BMIter fiter, liter;
- BM_ITER_ELEM (f, &fiter, l->v, BM_FACES_OF_VERT) {
- BMLoop *l_other;
- BM_ITER_ELEM (l_other, &liter, f, BM_LOOPS_OF_FACE) {
- const int l_index_other = BM_elem_index_get(l_other);
- short *clnors = BM_ELEM_CD_GET_VOID_P(l_other, lnors_ed_arr->cd_custom_normal_offset);
- BKE_lnor_space_custom_data_to_normal(
- bm->lnor_spacearr->lspacearr[l_index_other], clnors, loop_normal);
- add_v3_v3(smooth_normal[i], loop_normal);
+ BKE_editmesh_ensure_autosmooth(em);
+ BKE_editmesh_lnorspace_update(em);
+ BMLoopNorEditDataArray *lnors_ed_arr = BM_loop_normal_editdata_array_init(bm, false);
+
+ float(*smooth_normal)[3] = MEM_callocN(sizeof(*smooth_normal) * lnors_ed_arr->totloop,
+ __func__);
+
+ /* This is weird choice of operation, taking all loops of faces of current vertex.
+ * Could lead to some rather far away loops weighting as much as very close ones
+ * (topologically speaking), with complex polygons.
+ * Using topological distance here (rather than geometrical one)
+ * makes sense imho, but would rather go with a more consistent and flexible code,
+ * we could even add max topological distance to take into account, * and a weighting curve.
+ * Would do that later though, think for now we can live with that choice. --mont29. */
+ BMLoopNorEditData *lnor_ed = lnors_ed_arr->lnor_editdata;
+ for (int i = 0; i < lnors_ed_arr->totloop; i++, lnor_ed++) {
+ l = lnor_ed->loop;
+ float loop_normal[3];
+
+ BM_ITER_ELEM (f, &fiter, l->v, BM_FACES_OF_VERT) {
+ BMLoop *l_other;
+ BM_ITER_ELEM (l_other, &liter, f, BM_LOOPS_OF_FACE) {
+ const int l_index_other = BM_elem_index_get(l_other);
+ short *clnors = BM_ELEM_CD_GET_VOID_P(l_other, lnors_ed_arr->cd_custom_normal_offset);
+ BKE_lnor_space_custom_data_to_normal(
+ bm->lnor_spacearr->lspacearr[l_index_other], clnors, loop_normal);
+ add_v3_v3(smooth_normal[i], loop_normal);
+ }
}
}
- }
- const float factor = RNA_float_get(op->ptr, "factor");
+ const float factor = RNA_float_get(op->ptr, "factor");
- lnor_ed = lnors_ed_arr->lnor_editdata;
- for (int i = 0; i < lnors_ed_arr->totloop; i++, lnor_ed++) {
- float current_normal[3];
+ lnor_ed = lnors_ed_arr->lnor_editdata;
+ for (int i = 0; i < lnors_ed_arr->totloop; i++, lnor_ed++) {
+ float current_normal[3];
- if (normalize_v3(smooth_normal[i]) < CLNORS_VALID_VEC_LEN) {
- /* Skip in case smoothen normal is invalid... */
- continue;
- }
+ if (normalize_v3(smooth_normal[i]) < CLNORS_VALID_VEC_LEN) {
+ /* Skip in case smoothen normal is invalid... */
+ continue;
+ }
- BKE_lnor_space_custom_data_to_normal(
- bm->lnor_spacearr->lspacearr[lnor_ed->loop_index], lnor_ed->clnors_data, current_normal);
+ BKE_lnor_space_custom_data_to_normal(
+ bm->lnor_spacearr->lspacearr[lnor_ed->loop_index], lnor_ed->clnors_data, current_normal);
- /* Note: again, this is not true spherical interpolation that normals would need...
- * But it's probably good enough for now. */
- mul_v3_fl(current_normal, 1.0f - factor);
- mul_v3_fl(smooth_normal[i], factor);
- add_v3_v3(current_normal, smooth_normal[i]);
+ /* Note: again, this is not true spherical interpolation that normals would need...
+ * But it's probably good enough for now. */
+ mul_v3_fl(current_normal, 1.0f - factor);
+ mul_v3_fl(smooth_normal[i], factor);
+ add_v3_v3(current_normal, smooth_normal[i]);
- if (normalize_v3(current_normal) < CLNORS_VALID_VEC_LEN) {
- /* Skip in case smoothen normal is invalid... */
- continue;
- }
+ if (normalize_v3(current_normal) < CLNORS_VALID_VEC_LEN) {
+ /* Skip in case smoothen normal is invalid... */
+ continue;
+ }
- BKE_lnor_space_custom_normal_to_data(
- bm->lnor_spacearr->lspacearr[lnor_ed->loop_index], current_normal, lnor_ed->clnors_data);
- }
+ BKE_lnor_space_custom_normal_to_data(
+ bm->lnor_spacearr->lspacearr[lnor_ed->loop_index], current_normal, lnor_ed->clnors_data);
+ }
- BM_loop_normal_editdata_array_free(lnors_ed_arr);
- MEM_freeN(smooth_normal);
+ BM_loop_normal_editdata_array_free(lnors_ed_arr);
+ MEM_freeN(smooth_normal);
- EDBM_update_generic(em, true, false);
+ EDBM_update_generic(em, true, false);
+ }
+ MEM_freeN(objects);
return OPERATOR_FINISHED;
}
@@ -8968,50 +9016,59 @@ void MESH_OT_smoothen_normals(struct wmOperatorType *ot)
static int edbm_mod_weighted_strength_exec(bContext *C, wmOperator *op)
{
- Object *obedit = CTX_data_edit_object(C);
- BMEditMesh *em = BKE_editmesh_from_object(obedit);
- BMesh *bm = em->bm;
- BMFace *f;
- BMIter fiter;
+ ViewLayer *view_layer = CTX_data_view_layer(C);
+ uint objects_len = 0;
+ Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data(
+ view_layer, CTX_wm_view3d(C), &objects_len);
- BM_select_history_clear(bm);
+ for (uint ob_index = 0; ob_index < objects_len; ob_index++) {
+ Object *obedit = objects[ob_index];
+ BMEditMesh *em = BKE_editmesh_from_object(obedit);
+ BMesh *bm = em->bm;
+ BMFace *f;
+ BMIter fiter;
+ const int face_strength = RNA_enum_get(op->ptr, "face_strength");
+ const bool set = RNA_boolean_get(op->ptr, "set");
- const char *layer_id = MOD_WEIGHTEDNORMALS_FACEWEIGHT_CDLAYER_ID;
- int cd_prop_int_index = CustomData_get_named_layer_index(&bm->pdata, CD_PROP_INT, layer_id);
- if (cd_prop_int_index == -1) {
- BM_data_layer_add_named(bm, &bm->pdata, CD_PROP_INT, layer_id);
- cd_prop_int_index = CustomData_get_named_layer_index(&bm->pdata, CD_PROP_INT, layer_id);
- }
- cd_prop_int_index -= CustomData_get_layer_index(&bm->pdata, CD_PROP_INT);
- const int cd_prop_int_offset = CustomData_get_n_offset(
- &bm->pdata, CD_PROP_INT, cd_prop_int_index);
+ BM_select_history_clear(bm);
- 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);
+ const char *layer_id = MOD_WEIGHTEDNORMALS_FACEWEIGHT_CDLAYER_ID;
+ int cd_prop_int_index = CustomData_get_named_layer_index(&bm->pdata, CD_PROP_INT, layer_id);
+ if (cd_prop_int_index == -1) {
+ BM_data_layer_add_named(bm, &bm->pdata, CD_PROP_INT, layer_id);
+ cd_prop_int_index = CustomData_get_named_layer_index(&bm->pdata, CD_PROP_INT, layer_id);
+ }
+ cd_prop_int_index -= CustomData_get_layer_index(&bm->pdata, CD_PROP_INT);
+ const int cd_prop_int_offset = CustomData_get_n_offset(
+ &bm->pdata, CD_PROP_INT, cd_prop_int_index);
- if (set) {
- BM_ITER_MESH (f, &fiter, bm, BM_FACES_OF_MESH) {
- if (BM_elem_flag_test(f, BM_ELEM_SELECT)) {
- int *strength = BM_ELEM_CD_GET_VOID_P(f, cd_prop_int_offset);
- *strength = face_strength;
+ BM_mesh_elem_index_ensure(bm, BM_FACE);
+
+ if (set) {
+ BM_ITER_MESH (f, &fiter, bm, BM_FACES_OF_MESH) {
+ if (BM_elem_flag_test(f, BM_ELEM_SELECT)) {
+ int *strength = BM_ELEM_CD_GET_VOID_P(f, cd_prop_int_offset);
+ *strength = face_strength;
+ }
}
}
- }
- else {
- BM_ITER_MESH (f, &fiter, bm, BM_FACES_OF_MESH) {
- int *strength = BM_ELEM_CD_GET_VOID_P(f, cd_prop_int_offset);
- if (*strength == face_strength) {
- BM_face_select_set(bm, f, true);
- BM_select_history_store(bm, f);
- }
- else {
- BM_face_select_set(bm, f, false);
+ else {
+ BM_ITER_MESH (f, &fiter, bm, BM_FACES_OF_MESH) {
+ int *strength = BM_ELEM_CD_GET_VOID_P(f, cd_prop_int_offset);
+ if (*strength == face_strength) {
+ BM_face_select_set(bm, f, true);
+ BM_select_history_store(bm, f);
+ }
+ else {
+ BM_face_select_set(bm, f, false);
+ }
}
}
+
+ EDBM_update_generic(em, false, false);
}
- EDBM_update_generic(em, false, false);
+ MEM_freeN(objects);
return OPERATOR_FINISHED;
}
diff --git a/source/blender/editors/mesh/editmesh_undo.c b/source/blender/editors/mesh/editmesh_undo.c
index 28b14b0060d..e823fb46140 100644
--- a/source/blender/editors/mesh/editmesh_undo.c
+++ b/source/blender/editors/mesh/editmesh_undo.c
@@ -741,7 +741,8 @@ static bool mesh_undosys_step_encode(struct bContext *C,
static void mesh_undosys_step_decode(struct bContext *C,
struct Main *UNUSED(bmain),
UndoStep *us_p,
- int UNUSED(dir))
+ int UNUSED(dir),
+ bool UNUSED(is_final))
{
MeshUndoStep *us = (MeshUndoStep *)us_p;
diff --git a/source/blender/editors/mesh/mesh_data.c b/source/blender/editors/mesh/mesh_data.c
index a6934326d68..ee8de9d8ea9 100644
--- a/source/blender/editors/mesh/mesh_data.c
+++ b/source/blender/editors/mesh/mesh_data.c
@@ -41,6 +41,7 @@
#include "DEG_depsgraph.h"
+#include "RNA_access.h"
#include "RNA_define.h"
#include "WM_api.h"
@@ -629,8 +630,7 @@ void MESH_OT_vertex_color_remove(wmOperatorType *ot)
static int mesh_customdata_clear_exec__internal(bContext *C, char htype, int type)
{
- Object *obedit = ED_object_context(C);
- Mesh *me = obedit->data;
+ Mesh *me = ED_mesh_context(C);
int tot;
CustomData *data = mesh_customdata_get_type(me, htype, &tot);
@@ -788,8 +788,7 @@ void MESH_OT_customdata_skin_clear(wmOperatorType *ot)
/* Clear custom loop normals */
static int mesh_customdata_custom_splitnormals_add_exec(bContext *C, wmOperator *UNUSED(op))
{
- Object *ob = ED_object_context(C);
- Mesh *me = ob->data;
+ Mesh *me = ED_mesh_context(C);
if (!BKE_mesh_has_custom_loop_normals(me)) {
CustomData *data = GET_CD_DATA(me, ldata);
@@ -853,7 +852,7 @@ void MESH_OT_customdata_custom_splitnormals_add(wmOperatorType *ot)
/* api callbacks */
ot->exec = mesh_customdata_custom_splitnormals_add_exec;
- ot->poll = ED_operator_object_active_editable_mesh;
+ ot->poll = ED_operator_editable_mesh;
/* flags */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
@@ -861,8 +860,7 @@ void MESH_OT_customdata_custom_splitnormals_add(wmOperatorType *ot)
static int mesh_customdata_custom_splitnormals_clear_exec(bContext *C, wmOperator *UNUSED(op))
{
- Object *ob = ED_object_context(C);
- Mesh *me = ob->data;
+ Mesh *me = ED_mesh_context(C);
if (BKE_mesh_has_custom_loop_normals(me)) {
return mesh_customdata_clear_exec__internal(C, BM_LOOP, CD_CUSTOMLOOPNORMAL);
@@ -879,7 +877,7 @@ void MESH_OT_customdata_custom_splitnormals_clear(wmOperatorType *ot)
/* api callbacks */
ot->exec = mesh_customdata_custom_splitnormals_clear_exec;
- ot->poll = ED_operator_object_active_editable_mesh;
+ ot->poll = ED_operator_editable_mesh;
/* flags */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
@@ -1289,3 +1287,23 @@ void ED_mesh_report_mirror(wmOperator *op, int totmirr, int totfail)
{
ED_mesh_report_mirror_ex(op, totmirr, totfail, SCE_SELECT_VERTEX);
}
+
+Mesh *ED_mesh_context(struct bContext *C)
+{
+ Mesh *mesh = CTX_data_pointer_get_type(C, "mesh", &RNA_Mesh).data;
+ if (mesh != NULL) {
+ return mesh;
+ }
+
+ Object *ob = ED_object_active_context(C);
+ if (ob == NULL) {
+ return NULL;
+ }
+
+ ID *data = (ID *)ob->data;
+ if (data == NULL || GS(data->name) != ID_ME) {
+ return NULL;
+ }
+
+ return (Mesh *)data;
+}
diff --git a/source/blender/editors/metaball/editmball_undo.c b/source/blender/editors/metaball/editmball_undo.c
index d255fac26ad..9a95560ccdd 100644
--- a/source/blender/editors/metaball/editmball_undo.c
+++ b/source/blender/editors/metaball/editmball_undo.c
@@ -185,7 +185,8 @@ static bool mball_undosys_step_encode(struct bContext *C,
static void mball_undosys_step_decode(struct bContext *C,
struct Main *UNUSED(bmain),
UndoStep *us_p,
- int UNUSED(dir))
+ int UNUSED(dir),
+ bool UNUSED(is_final))
{
MBallUndoStep *us = (MBallUndoStep *)us_p;
diff --git a/source/blender/editors/object/object_add.c b/source/blender/editors/object/object_add.c
index 0fdb1cec16f..f8cf55933aa 100644
--- a/source/blender/editors/object/object_add.c
+++ b/source/blender/editors/object/object_add.c
@@ -1658,54 +1658,80 @@ static void copy_object_set_idnew(bContext *C)
/** \name Make Instanced Objects Real Operator
* \{ */
+/* XXX TODO That whole hierarchy handling based on persistent_id tricks is
+ * very confusing and convoluted, and it will fail in many cases besides basic ones.
+ * Think this should be replaced by a proper tree-like representation of the instantiations,
+ * should help a lot in both readability, and precise consistent rebuilding of hierarchy.
+ */
+
/**
- * \note regarding hashing dupli-objects when using OB_DUPLICOLLECTION,
+ * \note regarding hashing dupli-objects which come from OB_DUPLICOLLECTION,
* skip the first member of #DupliObject.persistent_id
* since its a unique index and we only want to know if the group objects are from the same
* dupli-group instance.
+ *
+ * \note regarding hashing dupli-objects which come from non-OB_DUPLICOLLECTION,
+ * include the first member of #DupliObject.persistent_id
+ * since its the index of the vertex/face the object is instantiated on and we want to identify
+ * objects on the same vertex/face.
+ * In other words, we consider each group of objects from a same item as being
+ * the 'local group' where to check for parents.
*/
-static unsigned int dupliobject_group_hash(const void *ptr)
+static unsigned int dupliobject_hash(const void *ptr)
{
const DupliObject *dob = ptr;
unsigned int hash = BLI_ghashutil_ptrhash(dob->ob);
- unsigned int i;
- for (i = 1; (i < MAX_DUPLI_RECUR) && dob->persistent_id[i] != INT_MAX; i++) {
- hash ^= (dob->persistent_id[i] ^ i);
+
+ if (dob->type == OB_DUPLICOLLECTION) {
+ for (int i = 1; (i < MAX_DUPLI_RECUR) && dob->persistent_id[i] != INT_MAX; i++) {
+ hash ^= (dob->persistent_id[i] ^ i);
+ }
+ }
+ else {
+ hash ^= (dob->persistent_id[0] ^ 0);
}
return hash;
}
/**
- * \note regarding hashing dupli-objects when NOT using OB_DUPLICOLLECTION,
- * include the first member of #DupliObject.persistent_id
- * since its the index of the vertex/face the object is instantiated on and we want to identify
- * objects on the same vertex/face.
+ * \note regarding hashing dupli-objects when using OB_DUPLICOLLECTION,
+ * skip the first member of #DupliObject.persistent_id
+ * since its a unique index and we only want to know if the group objects are from the same
+ * dupli-group instance.
*/
-static unsigned int dupliobject_hash(const void *ptr)
+static unsigned int dupliobject_instancer_hash(const void *ptr)
{
const DupliObject *dob = ptr;
- unsigned int hash = BLI_ghashutil_ptrhash(dob->ob);
- hash ^= (dob->persistent_id[0] ^ 0);
+ unsigned int hash = BLI_ghashutil_inthash(dob->persistent_id[0]);
+ for (int i = 1; (i < MAX_DUPLI_RECUR) && dob->persistent_id[i] != INT_MAX; i++) {
+ hash ^= (dob->persistent_id[i] ^ i);
+ }
return hash;
}
-/* Compare function that matches dupliobject_group_hash */
-static bool dupliobject_group_cmp(const void *a_, const void *b_)
+/* Compare function that matches dupliobject_hash */
+static bool dupliobject_cmp(const void *a_, const void *b_)
{
const DupliObject *a = a_;
const DupliObject *b = b_;
- unsigned int i;
if (a->ob != b->ob) {
return true;
}
- for (i = 1; (i < MAX_DUPLI_RECUR); i++) {
- if (a->persistent_id[i] != b->persistent_id[i]) {
- return true;
+ if (ELEM(a->type, b->type, OB_DUPLICOLLECTION)) {
+ for (int i = 1; (i < MAX_DUPLI_RECUR); i++) {
+ if (a->persistent_id[i] != b->persistent_id[i]) {
+ return true;
+ }
+ else if (a->persistent_id[i] == INT_MAX) {
+ break;
+ }
}
- else if (a->persistent_id[i] == INT_MAX) {
- break;
+ }
+ else {
+ if (a->persistent_id[0] != b->persistent_id[0]) {
+ return true;
}
}
@@ -1713,18 +1739,19 @@ static bool dupliobject_group_cmp(const void *a_, const void *b_)
return false;
}
-/* Compare function that matches dupliobject_hash */
-static bool dupliobject_cmp(const void *a_, const void *b_)
+/* Compare function that matches dupliobject_instancer_hash. */
+static bool dupliobject_instancer_cmp(const void *a_, const void *b_)
{
const DupliObject *a = a_;
const DupliObject *b = b_;
- if (a->ob != b->ob) {
- return true;
- }
-
- if (a->persistent_id[0] != b->persistent_id[0]) {
- return true;
+ for (int i = 0; (i < MAX_DUPLI_RECUR); i++) {
+ if (a->persistent_id[i] != b->persistent_id[i]) {
+ return true;
+ }
+ else if (a->persistent_id[i] == INT_MAX) {
+ break;
+ }
}
/* matching */
@@ -1739,7 +1766,7 @@ static void make_object_duplilist_real(
Depsgraph *depsgraph = CTX_data_depsgraph(C);
ListBase *lb_duplis;
DupliObject *dob;
- GHash *dupli_gh, *parent_gh = NULL;
+ GHash *dupli_gh, *parent_gh = NULL, *instancer_gh = NULL;
if (!(base->object->transflag & OB_DUPLI)) {
return;
@@ -1750,11 +1777,11 @@ static void make_object_duplilist_real(
dupli_gh = BLI_ghash_ptr_new(__func__);
if (use_hierarchy) {
- if (base->object->transflag & OB_DUPLICOLLECTION) {
- parent_gh = BLI_ghash_new(dupliobject_group_hash, dupliobject_group_cmp, __func__);
- }
- else {
- parent_gh = BLI_ghash_new(dupliobject_hash, dupliobject_cmp, __func__);
+ parent_gh = BLI_ghash_new(dupliobject_hash, dupliobject_cmp, __func__);
+
+ if (use_base_parent) {
+ instancer_gh = BLI_ghash_new(
+ dupliobject_instancer_hash, dupliobject_instancer_cmp, __func__);
}
}
@@ -1788,7 +1815,12 @@ static void make_object_duplilist_real(
ob_dst->parent = NULL;
BKE_constraints_free(&ob_dst->constraints);
ob_dst->runtime.curve_cache = NULL;
+ const bool is_dupli_instancer = (ob_dst->transflag & OB_DUPLI) != 0;
ob_dst->transflag &= ~OB_DUPLI;
+ /* Remove instantiated collection, it's annoying to keep it here
+ * (and get potentially a lot of usages of it then...). */
+ id_us_min((ID *)ob_dst->instance_collection);
+ ob_dst->instance_collection = NULL;
copy_m4_m4(ob_dst->obmat, dob->mat);
BKE_object_apply_mat4(ob_dst, ob_dst->obmat, false, false);
@@ -1802,6 +1834,13 @@ static void make_object_duplilist_real(
if (!BLI_ghash_ensure_p(parent_gh, dob, &val)) {
*val = ob_dst;
}
+
+ if (is_dupli_instancer && instancer_gh) {
+ /* Same as above, we may have several 'hits'. */
+ if (!BLI_ghash_ensure_p(instancer_gh, dob, &val)) {
+ *val = ob_dst;
+ }
+ }
}
}
@@ -1825,7 +1864,8 @@ static void make_object_duplilist_real(
* they won't be read, this is simply for a hash lookup. */
DupliObject dob_key;
dob_key.ob = ob_src_par;
- if (base->object->transflag & OB_DUPLICOLLECTION) {
+ dob_key.type = dob->type;
+ if (dob->type == OB_DUPLICOLLECTION) {
memcpy(&dob_key.persistent_id[1],
&dob->persistent_id[1],
sizeof(dob->persistent_id[1]) * (MAX_DUPLI_RECUR - 1));
@@ -1848,15 +1888,30 @@ static void make_object_duplilist_real(
ob_dst->parent = ob_dst_par;
}
- else if (use_base_parent) {
- ob_dst->parent = base->object;
- ob_dst->partype = PAROBJECT;
- }
}
- else if (use_base_parent) {
- /* since we are ignoring the internal hierarchy - parent all to the
- * base object */
- ob_dst->parent = base->object;
+ if (use_base_parent && ob_dst->parent == NULL) {
+ Object *ob_dst_par = NULL;
+
+ if (instancer_gh != NULL) {
+ /* OK to keep most of the members uninitialized,
+ * they won't be read, this is simply for a hash lookup. */
+ DupliObject dob_key;
+ /* We are looking one step upper in hierarchy, so we need to 'shift' the persitent_id,
+ * ignoring the first item.
+ * We only check on persistent_id here, since we have no idea what object it might be. */
+ memcpy(&dob_key.persistent_id[0],
+ &dob->persistent_id[1],
+ sizeof(dob_key.persistent_id[0]) * (MAX_DUPLI_RECUR - 1));
+ ob_dst_par = BLI_ghash_lookup(instancer_gh, &dob_key);
+ }
+
+ if (ob_dst_par == NULL) {
+ /* Default to parenting to root object...
+ * Always the case when use_hierarchy is false. */
+ ob_dst_par = base->object;
+ }
+
+ ob_dst->parent = ob_dst_par;
ob_dst->partype = PAROBJECT;
}
@@ -1878,12 +1933,16 @@ static void make_object_duplilist_real(
DEG_id_tag_update(&ob->id, ID_RECALC_TRANSFORM);
}
}
+ base->object->instance_collection = NULL;
}
BLI_ghash_free(dupli_gh, NULL, NULL);
if (parent_gh) {
BLI_ghash_free(parent_gh, NULL, NULL);
}
+ if (instancer_gh) {
+ BLI_ghash_free(instancer_gh, NULL, NULL);
+ }
free_object_duplilist(lb_duplis);
@@ -1977,7 +2036,13 @@ static void curvetomesh(Main *bmain, Depsgraph *depsgraph, Object *ob)
{
Object *object_eval = DEG_get_evaluated_object(depsgraph, ob);
Curve *curve = ob->data;
+
Mesh *mesh = BKE_mesh_new_from_object_to_bmain(bmain, depsgraph, object_eval, true);
+ if (mesh == NULL) {
+ /* Unable to convert the curve to a mesh. */
+ return;
+ }
+
BKE_object_free_modifiers(ob, 0);
/* Replace curve used by the object itself. */
ob->data = mesh;
@@ -2066,7 +2131,7 @@ static Base *duplibase_for_convert(
static int convert_exec(bContext *C, wmOperator *op)
{
Main *bmain = CTX_data_main(C);
- Depsgraph *depsgraph = CTX_data_depsgraph(C);
+ Depsgraph *depsgraph = CTX_data_evaluated_depsgraph(C);
Scene *scene = CTX_data_scene(C);
ViewLayer *view_layer = CTX_data_view_layer(C);
Base *basen = NULL, *basact = NULL;
@@ -2285,8 +2350,9 @@ static int convert_exec(bContext *C, wmOperator *op)
BKE_curve_curve_dimension_update(cu);
if (target == OB_MESH) {
+ /* No assumption should be made that the resulting objects is a mesh, as conversion can
+ * fail. */
curvetomesh(bmain, depsgraph, newob);
-
/* meshes doesn't use displist */
BKE_object_free_curve_cache(newob);
}
@@ -2309,8 +2375,9 @@ static int convert_exec(bContext *C, wmOperator *op)
newob = ob;
}
+ /* No assumption should be made that the resulting objects is a mesh, as conversion can
+ * fail. */
curvetomesh(bmain, depsgraph, newob);
-
/* meshes doesn't use displist */
BKE_object_free_curve_cache(newob);
}
@@ -2826,7 +2893,7 @@ void OBJECT_OT_join_shapes(wmOperatorType *ot)
{
/* identifiers */
ot->name = "Join as Shapes";
- ot->description = "Merge selected objects to shapes of active object";
+ ot->description = "Copy the current resulting shape of another selected object to this one";
ot->idname = "OBJECT_OT_join_shapes";
/* api callbacks */
diff --git a/source/blender/editors/object/object_bake_api.c b/source/blender/editors/object/object_bake_api.c
index 6164958bf2c..410ccccbd0d 100644
--- a/source/blender/editors/object/object_bake_api.c
+++ b/source/blender/editors/object/object_bake_api.c
@@ -707,7 +707,7 @@ static size_t initialize_internal_images(BakeImages *bake_images, ReportList *re
/* create new mesh with edit mode changes and modifiers applied */
static Mesh *bake_mesh_new_from_object(Object *object)
{
- Mesh *me = BKE_object_to_mesh(NULL, object, false);
+ Mesh *me = BKE_mesh_new_from_object(NULL, object, false);
if (me->flag & ME_AUTOSMOOTH) {
BKE_mesh_split_faces(me, true);
@@ -927,7 +927,7 @@ static int bake(Render *re,
}
}
else if (is_cage) {
- BKE_object_eval_reset(ob_low_eval);
+ bool is_changed = false;
ModifierData *md = ob_low_eval->modifiers.first;
while (md) {
@@ -942,11 +942,23 @@ static int bake(Render *re,
if (md->type == eModifierType_EdgeSplit) {
BLI_remlink(&ob_low_eval->modifiers, md);
modifier_free(md);
+ is_changed = true;
}
md = md_next;
}
- me_cage = BKE_object_to_mesh(NULL, ob_low_eval, false);
+ if (is_changed) {
+ /* Make sure object is evaluated with the new modifier settings.
+ *
+ * NOTE: Since the dependency graph was fully evaluated prior to bake, and we only made
+ * single modification to this object all the possible dependencies for evaluation are
+ * already up to date. This means we can do a cheap single object update
+ * (as an opposite of full depsgraph update). */
+ BKE_object_eval_reset(ob_low_eval);
+ BKE_object_handle_data_update(depsgraph, scene, ob_low_eval);
+ }
+
+ me_cage = BKE_mesh_new_from_object(NULL, ob_low_eval, false);
RE_bake_pixels_populate(me_cage, pixel_array_low, num_pixels, &bake_images, uv_layer);
}
@@ -965,7 +977,7 @@ static int bake(Render *re,
highpoly[i].ob_eval = DEG_get_evaluated_object(depsgraph, ob_iter);
highpoly[i].ob_eval->restrictflag &= ~OB_RESTRICT_RENDER;
highpoly[i].ob_eval->base_flag |= (BASE_VISIBLE | BASE_ENABLED_RENDER);
- highpoly[i].me = BKE_object_to_mesh(NULL, highpoly[i].ob_eval, false);
+ highpoly[i].me = BKE_mesh_new_from_object(NULL, highpoly[i].ob_eval, false);
/* lowpoly to highpoly transformation matrix */
copy_m4_m4(highpoly[i].obmat, highpoly[i].ob->obmat);
@@ -1088,7 +1100,7 @@ static int bake(Render *re,
}
/* Evaluate modifiers again. */
- me_nores = BKE_object_to_mesh(NULL, ob_low_eval, false);
+ me_nores = BKE_mesh_new_from_object(NULL, ob_low_eval, false);
RE_bake_pixels_populate(me_nores, pixel_array_low, num_pixels, &bake_images, uv_layer);
RE_bake_normal_world_to_tangent(pixel_array_low,
@@ -1098,7 +1110,7 @@ static int bake(Render *re,
me_nores,
normal_swizzle,
ob_low_eval->obmat);
- BKE_object_to_mesh_clear(ob_low_eval);
+ BKE_id_free(NULL, &me_nores->id);
if (md) {
md->mode = mode;
@@ -1221,8 +1233,8 @@ cleanup:
if (highpoly) {
int i;
for (i = 0; i < tot_highpoly; i++) {
- if (highpoly[i].ob_eval) {
- BKE_object_to_mesh_clear(highpoly[i].ob_eval);
+ if (highpoly[i].me != NULL) {
+ BKE_id_free(NULL, &highpoly[i].me->id);
}
}
MEM_freeN(highpoly);
@@ -1252,12 +1264,12 @@ cleanup:
MEM_freeN(result);
}
- if (ob_low_eval) {
- BKE_object_to_mesh_clear(ob_low_eval);
+ if (me_low != NULL) {
+ BKE_id_free(NULL, &me_low->id);
}
- if (ob_cage_eval) {
- BKE_object_to_mesh_clear(ob_cage_eval);
+ if (me_cage != NULL) {
+ BKE_id_free(NULL, &me_cage->id);
}
DEG_graph_free(depsgraph);
diff --git a/source/blender/editors/object/object_constraint.c b/source/blender/editors/object/object_constraint.c
index 53bc037c736..5ef133e87de 100644
--- a/source/blender/editors/object/object_constraint.c
+++ b/source/blender/editors/object/object_constraint.c
@@ -34,6 +34,7 @@
#include "BLT_translation.h"
#include "DNA_anim_types.h"
+#include "DNA_armature_types.h"
#include "DNA_constraint_types.h"
#include "DNA_curve_types.h"
#include "DNA_scene_types.h"
@@ -53,6 +54,7 @@
#include "DEG_depsgraph.h"
#include "DEG_depsgraph_build.h"
+#include "DEG_depsgraph_query.h"
#ifdef WITH_PYTHON
# include "BPY_extern.h"
@@ -861,94 +863,107 @@ void CONSTRAINT_OT_limitdistance_reset(wmOperatorType *ot)
/* ------------- Child-Of Constraint ------------------ */
-static void child_get_inverse_matrix(const bContext *C,
- Scene *scene,
- Object *ob,
- bConstraint *con,
- float invmat[4][4],
- const int owner)
+static void child_get_inverse_matrix_owner_bone(
+ const bContext *C, wmOperator *op, Scene *scene, Object *ob, float invmat[4][4])
{
+ /* For bone owner we want to do this in evaluated domain.
+ * BKE_pose_where_is / BKE_pose_where_is_bone relies on (re)evaluating parts of the scene
+ * and copying new evaluated stuff back to original.
+ */
Depsgraph *depsgraph = CTX_data_depsgraph(C);
+ Object *ob_eval = DEG_get_evaluated_object(depsgraph, ob);
+ bConstraint *con_eval = edit_constraint_property_get(op, ob_eval, CONSTRAINT_TYPE_CHILDOF);
/* nullify inverse matrix first */
unit_m4(invmat);
- if (owner == EDIT_CONSTRAINT_OWNER_BONE) {
- bPoseChannel *pchan;
- /* try to find a pose channel - assume that this is the constraint owner */
- /* TODO: get from context instead? */
- if (ob && ob->pose && (pchan = BKE_pose_channel_active(ob))) {
- bConstraint *con_last;
- /* calculate/set inverse matrix:
- * We just calculate all transform-stack eval up to but not including this constraint.
- * This is because inverse should just inverse correct for just the constraint's influence
- * when it gets applied; that is, at the time of application, we don't know anything about
- * what follows.
- */
- float imat[4][4], tmat[4][4];
- float pmat[4][4];
+ bPoseChannel *pchan_eval = BKE_pose_channel_active(ob_eval);
- /* make sure we passed the correct constraint */
- BLI_assert(BLI_findindex(&pchan->constraints, con) != -1);
+ /* try to find a pose channel - assume that this is the constraint owner */
+ /* TODO: get from context instead? */
+ if (ob_eval && ob_eval->pose && pchan_eval) {
+ bConstraint *con_last;
- /* 1. calculate posemat where inverse doesn't exist yet (inverse was cleared above),
- * to use as baseline ("pmat") to derive delta from. This extra calc saves users
- * from having pressing "Clear Inverse" first
- */
- BKE_pose_where_is(depsgraph, scene, ob);
- copy_m4_m4(pmat, pchan->pose_mat);
+ /* calculate/set inverse matrix:
+ * We just calculate all transform-stack eval up to but not including this constraint.
+ * This is because inverse should just inverse correct for just the constraint's influence
+ * when it gets applied; that is, at the time of application, we don't know anything about
+ * what follows.
+ */
+ float imat[4][4], tmat[4][4];
+ float pmat[4][4];
- /* 2. knock out constraints starting from this one */
- con_last = pchan->constraints.last;
- pchan->constraints.last = con->prev;
+ /* make sure we passed the correct constraint */
+ BLI_assert(BLI_findindex(&pchan_eval->constraints, con_eval) != -1);
- if (con->prev) {
- /* new end must not point to this one, else this chain cutting is useless */
- con->prev->next = NULL;
- }
- else {
- /* constraint was first */
- pchan->constraints.first = NULL;
- }
+ /* 1. calculate posemat where inverse doesn't exist yet (inverse was cleared above),
+ * to use as baseline ("pmat") to derive delta from. This extra calc saves users
+ * from having pressing "Clear Inverse" first
+ */
+ BKE_pose_where_is(depsgraph, scene, ob_eval);
+ copy_m4_m4(pmat, pchan_eval->pose_mat);
- /* 3. solve pose without disabled constraints */
- BKE_pose_where_is(depsgraph, scene, ob);
+ /* 2. knock out constraints starting from this one */
+ con_last = pchan_eval->constraints.last;
+ pchan_eval->constraints.last = con_eval->prev;
- /* 4. determine effect of constraint by removing the newly calculated
- * pchan->pose_mat from the original pchan->pose_mat, thus determining
- * the effect of the constraint
- */
- invert_m4_m4(imat, pchan->pose_mat);
- mul_m4_m4m4(tmat, pmat, imat);
- invert_m4_m4(invmat, tmat);
+ if (con_eval->prev) {
+ /* new end must not point to this one, else this chain cutting is useless */
+ con_eval->prev->next = NULL;
+ }
+ else {
+ /* constraint was first */
+ pchan_eval->constraints.first = NULL;
+ }
- /* 5. restore constraints */
- pchan->constraints.last = con_last;
+ /* 3. solve pose without disabled constraints */
+ BKE_pose_where_is(depsgraph, scene, ob_eval);
- if (con->prev) {
- /* hook up prev to this one again */
- con->prev->next = con;
- }
- else {
- /* set as first again */
- pchan->constraints.first = con;
- }
+ /* 4. determine effect of constraint by removing the newly calculated
+ * pchan->pose_mat from the original pchan->pose_mat, thus determining
+ * the effect of the constraint
+ */
+ invert_m4_m4(imat, pchan_eval->pose_mat);
+ mul_m4_m4m4(tmat, pmat, imat);
+ invert_m4_m4(invmat, tmat);
+
+ /* 5. restore constraints */
+ pchan_eval->constraints.last = con_last;
- /* 6. recalculate pose with new inv-mat applied */
- BKE_pose_where_is(depsgraph, scene, ob);
+ if (con_eval->prev) {
+ /* hook up prev to this one again */
+ con_eval->prev->next = con_eval;
}
+ else {
+ /* set as first again */
+ pchan_eval->constraints.first = con_eval;
+ }
+
+ /* 6. recalculate pose with new inv-mat applied */
+ /* this one is unnecessary? (DEG seems to update correctly without)
+ + if we leave this in, we have to click "Set Inverse" twice to see updates...
+ BKE_pose_where_is(depsgraph, scene, ob_eval); */
}
- if (owner == EDIT_CONSTRAINT_OWNER_OBJECT) {
- if (ob) {
- Object workob;
+}
- /* make sure we passed the correct constraint */
- BLI_assert(BLI_findindex(&ob->constraints, con) != -1);
+static void child_get_inverse_matrix_owner_object(
+ const bContext *C, Scene *scene, Object *ob, bConstraint *con, float invmat[4][4])
+{
+ Depsgraph *depsgraph = CTX_data_depsgraph(C);
- /* use BKE_object_workob_calc_parent to find inverse - just like for normal parenting */
- BKE_object_workob_calc_parent(depsgraph, scene, ob, &workob);
- invert_m4_m4(invmat, workob.obmat);
- }
+ /* nullify inverse matrix first */
+ unit_m4(invmat);
+
+ if (ob) {
+ Object workob;
+
+ /* make sure we passed the correct constraint */
+ BLI_assert(BLI_findindex(&ob->constraints, con) != -1);
+ UNUSED_VARS_NDEBUG(con);
+
+ /* use BKE_object_workob_calc_parent to find inverse - just like for normal parenting */
+ BKE_object_workob_calc_parent(depsgraph, scene, ob, &workob);
+ invert_m4_m4(invmat, workob.obmat);
}
}
@@ -969,7 +984,12 @@ static int childof_set_inverse_exec(bContext *C, wmOperator *op)
return OPERATOR_CANCELLED;
}
- child_get_inverse_matrix(C, scene, ob, con, data->invmat, owner);
+ if (owner == EDIT_CONSTRAINT_OWNER_OBJECT) {
+ child_get_inverse_matrix_owner_object(C, scene, ob, con, data->invmat);
+ }
+ else if (owner == EDIT_CONSTRAINT_OWNER_BONE) {
+ child_get_inverse_matrix_owner_bone(C, op, scene, ob, data->invmat);
+ }
ED_object_constraint_update(bmain, ob);
WM_event_add_notifier(C, NC_OBJECT | ND_CONSTRAINT, ob);
@@ -1203,6 +1223,7 @@ void CONSTRAINT_OT_followpath_path_animate(wmOperatorType *ot)
static int objectsolver_set_inverse_exec(bContext *C, wmOperator *op)
{
+ Main *bmain = CTX_data_main(C);
Scene *scene = CTX_data_scene(C);
Object *ob = ED_object_active_context(C);
bConstraint *con = edit_constraint_property_get(op, ob, CONSTRAINT_TYPE_OBJECTSOLVER);
@@ -1216,8 +1237,14 @@ static int objectsolver_set_inverse_exec(bContext *C, wmOperator *op)
return OPERATOR_CANCELLED;
}
- child_get_inverse_matrix(C, scene, ob, con, data->invmat, owner);
+ if (owner == EDIT_CONSTRAINT_OWNER_OBJECT) {
+ child_get_inverse_matrix_owner_object(C, scene, ob, con, data->invmat);
+ }
+ else if (owner == EDIT_CONSTRAINT_OWNER_BONE) {
+ child_get_inverse_matrix_owner_bone(C, op, scene, ob, data->invmat);
+ }
+ ED_object_constraint_update(bmain, ob);
WM_event_add_notifier(C, NC_OBJECT | ND_CONSTRAINT, ob);
return OPERATOR_FINISHED;
@@ -1789,10 +1816,15 @@ static bool get_new_constraint_target(
*/
if ((ob->type == OB_ARMATURE) && (ob->mode & OB_MODE_POSE) &&
(!only_curve && !only_mesh)) {
- /* just use the active bone, and assume that it is visible + usable */
- *tar_ob = ob;
- *tar_pchan = BKE_pose_channel_active(ob);
- found = true;
+
+ /* Only use the object & bone if the bone is visible & selected
+ * since we may have multiple objects in pose mode at once. */
+ bPoseChannel *pchan = BKE_pose_channel_active_or_first_selected(ob);
+ if (pchan != NULL) {
+ *tar_pchan = pchan;
+ *tar_ob = ob;
+ found = true;
+ }
break;
}
diff --git a/source/blender/editors/object/object_select.c b/source/blender/editors/object/object_select.c
index afdda8d6b7f..da06707ebac 100644
--- a/source/blender/editors/object/object_select.c
+++ b/source/blender/editors/object/object_select.c
@@ -119,18 +119,27 @@ void ED_object_base_select(Base *base, eObjectSelect_Mode mode)
}
/**
+ * Call when the active base has changed.
+ */
+void ED_object_base_active_refresh(Main *bmain, Scene *scene, ViewLayer *view_layer)
+{
+ WM_main_add_notifier(NC_SCENE | ND_OB_ACTIVE, scene);
+ DEG_id_tag_update(&scene->id, ID_RECALC_SELECT);
+ struct wmMsgBus *mbus = ((wmWindowManager *)bmain->wm.first)->message_bus;
+ if (mbus != NULL) {
+ WM_msg_publish_rna_prop(mbus, &scene->id, view_layer, LayerObjects, active);
+ }
+}
+
+/**
* Change active base, it includes the notifier
*/
void ED_object_base_activate(bContext *C, Base *base)
{
- struct wmMsgBus *mbus = CTX_wm_message_bus(C);
Scene *scene = CTX_data_scene(C);
ViewLayer *view_layer = CTX_data_view_layer(C);
view_layer->basact = base;
-
- WM_event_add_notifier(C, NC_SCENE | ND_OB_ACTIVE, scene);
- WM_msg_publish_rna_prop(mbus, &scene->id, view_layer, LayerObjects, active);
- DEG_id_tag_update(&CTX_data_scene(C)->id, ID_RECALC_SELECT);
+ ED_object_base_active_refresh(CTX_data_main(C), scene, view_layer);
}
bool ED_object_base_deselect_all_ex(ViewLayer *view_layer,
diff --git a/source/blender/editors/object/object_transform.c b/source/blender/editors/object/object_transform.c
index 394fea2cf27..9c98fdc2a2e 100644
--- a/source/blender/editors/object/object_transform.c
+++ b/source/blender/editors/object/object_transform.c
@@ -466,6 +466,8 @@ static void ignore_parent_tx(Main *bmain, Depsgraph *depsgraph, Scene *scene, Ob
Object workob;
Object *ob_child;
+ Scene *scene_eval = DEG_get_evaluated_scene(depsgraph);
+
/* a change was made, adjust the children to compensate */
for (ob_child = bmain->objects.first; ob_child; ob_child = ob_child->id.next) {
if (ob_child->parent == ob) {
@@ -475,6 +477,14 @@ static void ignore_parent_tx(Main *bmain, Depsgraph *depsgraph, Scene *scene, Ob
invert_m4_m4(ob_child->parentinv, workob.obmat);
/* Copy result of BKE_object_apply_mat4(). */
BKE_object_transform_copy(ob_child, ob_child_eval);
+ /* Make sure evaluated object is in a consistent state with the original one.
+ * It might be needed for applying transform on its children. */
+ copy_m4_m4(ob_child_eval->parentinv, ob_child->parentinv);
+ BKE_object_eval_transform_all(depsgraph, scene_eval, ob_child_eval);
+ /* Tag for update.
+ * This is because parent matrix did change, so in theory the child object might now be
+ * evaluated to a different location in another editing context. */
+ DEG_id_tag_update(&ob_child->id, ID_RECALC_TRANSFORM);
}
}
}
@@ -537,7 +547,7 @@ static int apply_objects_internal(bContext *C,
{
Main *bmain = CTX_data_main(C);
Scene *scene = CTX_data_scene(C);
- Depsgraph *depsgraph = CTX_data_depsgraph(C);
+ Depsgraph *depsgraph = CTX_data_evaluated_depsgraph(C);
float rsmat[3][3], obmat[3][3], iobmat[3][3], mat[4][4], scale;
bool changed = true;
@@ -965,7 +975,7 @@ static int object_origin_set_exec(bContext *C, wmOperator *op)
Scene *scene = CTX_data_scene(C);
Object *obact = CTX_data_active_object(C);
Object *obedit = CTX_data_edit_object(C);
- Depsgraph *depsgraph = CTX_data_depsgraph(C);
+ Depsgraph *depsgraph = CTX_data_evaluated_depsgraph(C);
Object *tob;
float cent[3], cent_neg[3], centn[3];
const float *cursor = scene->cursor.location;
@@ -1052,7 +1062,7 @@ static int object_origin_set_exec(bContext *C, wmOperator *op)
/* move active first */
if (ob == obact) {
- memmove(&objects[1], objects, object_index);
+ memmove(&objects[1], objects, object_index * sizeof(Object *));
objects[0] = ob;
}
}
@@ -1217,8 +1227,10 @@ static int object_origin_set_exec(bContext *C, wmOperator *op)
arm->id.tag |= LIB_TAG_DOIT;
/* do_inverse_offset = true; */ /* docenter_armature() handles this */
- BKE_object_where_is_calc(depsgraph, scene, ob);
- BKE_pose_where_is(depsgraph, scene, ob); /* needed for bone parents */
+ Object *ob_eval = DEG_get_evaluated_object(depsgraph, ob);
+ BKE_object_transform_copy(ob_eval, ob);
+ BKE_object_where_is_calc(depsgraph, scene, ob_eval);
+ BKE_pose_where_is(depsgraph, scene, ob_eval); /* needed for bone parents */
ignore_parent_tx(bmain, depsgraph, scene, ob);
@@ -1353,9 +1365,12 @@ static int object_origin_set_exec(bContext *C, wmOperator *op)
add_v3_v3(ob->loc, centn);
- BKE_object_where_is_calc(depsgraph, scene, ob);
+ Object *ob_eval = DEG_get_evaluated_object(depsgraph, ob);
+ BKE_object_transform_copy(ob_eval, ob);
+ BKE_object_where_is_calc(depsgraph, scene, ob_eval);
if (ob->type == OB_ARMATURE) {
- BKE_pose_where_is(depsgraph, scene, ob); /* needed for bone parents */
+ /* needed for bone parents */
+ BKE_pose_where_is(depsgraph, scene, ob_eval);
}
ignore_parent_tx(bmain, depsgraph, scene, ob);
@@ -1378,10 +1393,12 @@ static int object_origin_set_exec(bContext *C, wmOperator *op)
mul_v3_mat3_m4v3(centn, ob_other->obmat, cent); /* omit translation part */
add_v3_v3(ob_other->loc, centn);
- BKE_object_where_is_calc(depsgraph, scene, ob_other);
+ Object *ob_other_eval = DEG_get_evaluated_object(depsgraph, ob_other);
+ BKE_object_transform_copy(ob_other_eval, ob_other);
+ BKE_object_where_is_calc(depsgraph, scene, ob_other_eval);
if (ob_other->type == OB_ARMATURE) {
/* needed for bone parents */
- BKE_pose_where_is(depsgraph, scene, ob_other);
+ BKE_pose_where_is(depsgraph, scene, ob_other_eval);
}
ignore_parent_tx(bmain, depsgraph, scene, ob_other);
}
@@ -1490,7 +1507,7 @@ void OBJECT_OT_origin_set(wmOperatorType *ot)
/* -------------------------------------------------------------------- */
/** \name Transform Axis Target
*
- * Note this is an experemental operator to point lights/cameras at objects.
+ * Note this is an experimental operator to point lights/cameras at objects.
* We may re-work how this behaves based on user feedback.
* - campbell.
* \{ */
diff --git a/source/blender/editors/object/object_vgroup.c b/source/blender/editors/object/object_vgroup.c
index 678f6f50096..4f61443ac54 100644
--- a/source/blender/editors/object/object_vgroup.c
+++ b/source/blender/editors/object/object_vgroup.c
@@ -3278,9 +3278,18 @@ static int vertex_group_smooth_exec(bContext *C, wmOperator *op)
ViewLayer *view_layer = CTX_data_view_layer(C);
Object *ob_ctx = ED_object_context(C);
- uint objects_len = 0;
- Object **objects = BKE_view_layer_array_from_objects_in_mode_unique_data(
- view_layer, CTX_wm_view3d(C), &objects_len, ob_ctx->mode);
+ uint objects_len;
+ Object **objects;
+ if (ob_ctx->mode == OB_MODE_WEIGHT_PAINT) {
+ /* Until weight paint supports multi-edit, use only the active. */
+ objects_len = 1;
+ objects = &ob_ctx;
+ }
+ else {
+ objects = BKE_view_layer_array_from_objects_in_mode_unique_data(
+ view_layer, CTX_wm_view3d(C), &objects_len, ob_ctx->mode);
+ }
+
for (uint ob_index = 0; ob_index < objects_len; ob_index++) {
Object *ob = objects[ob_index];
@@ -3296,7 +3305,9 @@ static int vertex_group_smooth_exec(bContext *C, wmOperator *op)
WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, ob);
WM_event_add_notifier(C, NC_GEOM | ND_DATA, ob->data);
}
- MEM_freeN(objects);
+ if (objects != &ob_ctx) {
+ MEM_freeN(objects);
+ }
return OPERATOR_FINISHED;
}
diff --git a/source/blender/editors/physics/particle_edit.c b/source/blender/editors/physics/particle_edit.c
index dc634865a0a..4e6022cf18c 100644
--- a/source/blender/editors/physics/particle_edit.c
+++ b/source/blender/editors/physics/particle_edit.c
@@ -97,23 +97,38 @@ bool PE_poll(bContext *C)
Object *ob = CTX_data_active_object(C);
if (!scene || !ob || !(ob->mode & OB_MODE_PARTICLE_EDIT)) {
- return 0;
+ return false;
+ }
+
+ PTCacheEdit *edit = PE_get_current(scene, ob);
+ if (edit == NULL) {
+ return false;
}
- return (PE_get_current(scene, ob) != NULL);
+ if (edit->psmd_eval == NULL || edit->psmd_eval->mesh_final == NULL) {
+ return false;
+ }
+
+ return true;
}
bool PE_hair_poll(bContext *C)
{
Scene *scene = CTX_data_scene(C);
Object *ob = CTX_data_active_object(C);
- PTCacheEdit *edit;
if (!scene || !ob || !(ob->mode & OB_MODE_PARTICLE_EDIT)) {
- return 0;
+ return false;
}
- edit = PE_get_current(scene, ob);
- return (edit && edit->psys);
+ PTCacheEdit *edit = PE_get_current(scene, ob);
+ if (edit == NULL || edit->psys == NULL) {
+ return false;
+ }
+ if (edit->psmd_eval == NULL || edit->psmd_eval->mesh_final == NULL) {
+ return false;
+ }
+
+ return true;
}
bool PE_poll_view3d(bContext *C)
@@ -322,10 +337,13 @@ static PTCacheEdit *pe_get_current(Depsgraph *depsgraph, Scene *scene, Object *o
}
}
- if (edit) {
+ /* Don't consider inactive or render dependency graphs, since they might be evaluated for a
+ * different number of childrem. or have different pointer to evaluated particle system or
+ * modifier which will also cause troubles. */
+ if (edit && DEG_is_active(depsgraph)) {
edit->pid = *pid;
if (edit->flags & PT_CACHE_EDIT_UPDATE_PARTICLE_FROM_EVAL) {
- if (edit->psys != NULL) {
+ if (edit->psys != NULL && edit->psys_eval != NULL) {
psys_copy_particles(edit->psys, edit->psys_eval);
pe_update_hair_particle_edit_pointers(edit);
}
@@ -1085,7 +1103,7 @@ static void PE_apply_mirror(Object *ob, ParticleSystem *psys)
edit = psys->edit;
psmd_eval = edit->psmd_eval;
- if (!psmd_eval->mesh_final) {
+ if (psmd_eval == NULL || psmd_eval->mesh_final == NULL) {
return;
}
@@ -1217,7 +1235,7 @@ static void pe_deflect_emitter(Scene *scene, Object *ob, PTCacheEdit *edit)
psys = edit->psys;
- if (!edit->psmd_eval->mesh_final) {
+ if (edit->psmd_eval == NULL || edit->psmd_eval->mesh_final == NULL) {
return;
}
@@ -1489,7 +1507,7 @@ void update_world_cos(Depsgraph *UNUSED(depsgraph), Object *ob, PTCacheEdit *edi
KEY_K;
float hairmat[4][4];
- if (psys == 0 || psys->edit == 0 || psmd_eval->mesh_final == NULL) {
+ if (psys == 0 || psys->edit == 0 || psmd_eval == NULL || psmd_eval->mesh_final == NULL) {
return;
}
diff --git a/source/blender/editors/physics/particle_edit_undo.c b/source/blender/editors/physics/particle_edit_undo.c
index be625eb939f..40d90676487 100644
--- a/source/blender/editors/physics/particle_edit_undo.c
+++ b/source/blender/editors/physics/particle_edit_undo.c
@@ -252,7 +252,8 @@ static bool particle_undosys_step_encode(struct bContext *C,
static void particle_undosys_step_decode(struct bContext *C,
struct Main *UNUSED(bmain),
UndoStep *us_p,
- int UNUSED(dir))
+ int UNUSED(dir),
+ bool UNUSED(is_final))
{
/* TODO(campbell): undo_system: use low-level API to set mode. */
ED_object_mode_set(C, OB_MODE_PARTICLE_EDIT);
diff --git a/source/blender/editors/physics/physics_fluid.c b/source/blender/editors/physics/physics_fluid.c
index dc4ce138d9d..dc3673c972f 100644
--- a/source/blender/editors/physics/physics_fluid.c
+++ b/source/blender/editors/physics/physics_fluid.c
@@ -46,6 +46,7 @@
#include "DEG_depsgraph.h"
#include "ED_screen.h"
+#include "ED_object.h"
#include "WM_types.h"
#include "WM_api.h"
@@ -1216,7 +1217,7 @@ static int fluid_bake_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(
return OPERATOR_CANCELLED;
}
- if (!fluidsimBake(C, op->reports, CTX_data_active_object(C), true)) {
+ if (!fluidsimBake(C, op->reports, ED_object_context(C), true)) {
return OPERATOR_CANCELLED;
}
diff --git a/source/blender/editors/render/render_internal.c b/source/blender/editors/render/render_internal.c
index 352593a15ad..9ac93f07300 100644
--- a/source/blender/editors/render/render_internal.c
+++ b/source/blender/editors/render/render_internal.c
@@ -914,7 +914,6 @@ static int screen_render_invoke(bContext *C, wmOperator *op, const wmEvent *even
wmJob *wm_job;
RenderJob *rj;
Image *ima;
- int jobflag;
const bool is_animation = RNA_boolean_get(op->ptr, "animation");
const bool is_write_still = RNA_boolean_get(op->ptr, "write_still");
const bool use_viewport = RNA_boolean_get(op->ptr, "use_viewport");
@@ -973,12 +972,6 @@ static int screen_render_invoke(bContext *C, wmOperator *op, const wmEvent *even
/* ensure at least 1 area shows result */
sa = render_view_open(C, event->x, event->y, op->reports);
- jobflag = WM_JOB_EXCL_RENDER | WM_JOB_PRIORITY | WM_JOB_PROGRESS;
-
- if (RNA_struct_property_is_set(op->ptr, "layer")) {
- jobflag |= WM_JOB_SUSPEND;
- }
-
/* job custom data */
rj = MEM_callocN(sizeof(RenderJob), "render job");
rj->main = bmain;
@@ -1038,12 +1031,20 @@ static int screen_render_invoke(bContext *C, wmOperator *op, const wmEvent *even
name = "Render";
}
- wm_job = WM_jobs_get(
- CTX_wm_manager(C), CTX_wm_window(C), scene, name, jobflag, WM_JOB_TYPE_RENDER);
+ wm_job = WM_jobs_get(CTX_wm_manager(C),
+ CTX_wm_window(C),
+ scene,
+ name,
+ WM_JOB_EXCL_RENDER | WM_JOB_PRIORITY | WM_JOB_PROGRESS,
+ WM_JOB_TYPE_RENDER);
WM_jobs_customdata_set(wm_job, rj, render_freejob);
WM_jobs_timer(wm_job, 0.2, NC_SCENE | ND_RENDER_RESULT, 0);
WM_jobs_callbacks(wm_job, render_startjob, NULL, NULL, render_endjob);
+ if (RNA_struct_property_is_set(op->ptr, "layer")) {
+ WM_jobs_delay_start(wm_job, 0.2);
+ }
+
/* get a render result image, and make sure it is empty */
ima = BKE_image_verify_viewer(bmain, IMA_TYPE_R_RESULT, "Render Result");
BKE_image_signal(rj->main, ima, NULL, IMA_SIGNAL_FREE);
diff --git a/source/blender/editors/render/render_preview.c b/source/blender/editors/render/render_preview.c
index 35130988aba..fbabdc2f3c1 100644
--- a/source/blender/editors/render/render_preview.c
+++ b/source/blender/editors/render/render_preview.c
@@ -1208,19 +1208,13 @@ static void icon_preview_startjob_all_sizes(void *customdata,
IconPreview *ip = (IconPreview *)customdata;
IconPreviewSize *cur_size;
- /* Wait 2s to start rendering icon previews, to not bog down user interaction.
- * Particularly important for heavy scenes and Eevee using OpenGL that blocks
- * the user interface drawing. */
- for (int i = 0; i < 20; i++) {
- PIL_sleep_ms(100);
- if (*stop) {
- return;
- }
- }
-
for (cur_size = ip->sizes.first; cur_size; cur_size = cur_size->next) {
PreviewImage *prv = ip->owner;
+ if (*stop) {
+ break;
+ }
+
if (prv->tag & PRV_TAG_DEFFERED_DELETE) {
/* Non-thread-protected reading is not an issue here. */
continue;
@@ -1265,10 +1259,6 @@ static void icon_preview_startjob_all_sizes(void *customdata,
common_preview_startjob(sp, stop, do_update, progress);
shader_preview_free(sp);
-
- if (*stop) {
- break;
- }
}
}
@@ -1350,8 +1340,13 @@ void ED_preview_icon_render(
BLI_freelistN(&ip.sizes);
}
-void ED_preview_icon_job(
- const bContext *C, void *owner, ID *id, unsigned int *rect, int sizex, int sizey)
+void ED_preview_icon_job(const bContext *C,
+ void *owner,
+ ID *id,
+ unsigned int *rect,
+ int sizex,
+ int sizey,
+ const bool delay)
{
wmJob *wm_job;
IconPreview *ip, *old_ip;
@@ -1363,7 +1358,7 @@ void ED_preview_icon_job(
CTX_wm_window(C),
owner,
"Icon Preview",
- WM_JOB_EXCL_RENDER | WM_JOB_SUSPEND,
+ WM_JOB_EXCL_RENDER,
WM_JOB_TYPE_RENDER_PREVIEW);
ip = MEM_callocN(sizeof(IconPreview), "icon preview");
@@ -1396,6 +1391,10 @@ void ED_preview_icon_job(
/* setup job */
WM_jobs_customdata_set(wm_job, ip, icon_preview_free);
WM_jobs_timer(wm_job, 0.1, NC_WINDOW, NC_WINDOW);
+ /* Wait 2s to start rendering icon previews, to not bog down user interaction.
+ * Particularly important for heavy scenes and Eevee using OpenGL that blocks
+ * the user interface drawing. */
+ WM_jobs_delay_start(wm_job, (delay) ? 2.0 : 0.0);
WM_jobs_callbacks(wm_job, icon_preview_startjob_all_sizes, NULL, NULL, icon_preview_endjob);
WM_jobs_start(CTX_wm_manager(C), wm_job);
diff --git a/source/blender/editors/screen/glutil.c b/source/blender/editors/screen/glutil.c
index fc771e0db77..af1e0eeed79 100644
--- a/source/blender/editors/screen/glutil.c
+++ b/source/blender/editors/screen/glutil.c
@@ -47,17 +47,6 @@
/* ******************************************** */
-/* Invert line handling */
-
-#define GL_TOGGLE(mode, onoff) (((onoff) ? glEnable : glDisable)(mode))
-
-void set_inverted_drawing(int enable)
-{
- glLogicOp(enable ? GL_INVERT : GL_COPY);
- GL_TOGGLE(GL_COLOR_LOGIC_OP, enable);
- GL_TOGGLE(GL_DITHER, !enable);
-}
-
static int get_cached_work_texture(int *r_w, int *r_h)
{
static GLint texid = -1;
@@ -486,6 +475,9 @@ void immDrawPixelsTex_clipping(IMMDrawPixelsTexState *state,
float bglPolygonOffsetCalc(const float winmat[16], float viewdist, float dist)
{
+ /* Seems like we have a factor of 2 more offset than 2.79 for some reason. Correct for this. */
+ dist *= 0.5f;
+
if (winmat[15] > 0.5f) {
#if 1
return 0.00001f * dist * viewdist; // ortho tweaking
diff --git a/source/blender/editors/screen/screen_ops.c b/source/blender/editors/screen/screen_ops.c
index ef99d39f990..c9a45728bc2 100644
--- a/source/blender/editors/screen/screen_ops.c
+++ b/source/blender/editors/screen/screen_ops.c
@@ -74,6 +74,7 @@
#include "ED_clip.h"
#include "ED_image.h"
#include "ED_keyframes_draw.h"
+#include "ED_mesh.h"
#include "ED_object.h"
#include "ED_screen.h"
#include "ED_screen_types.h"
@@ -371,6 +372,12 @@ bool ED_operator_object_active_editable_font(bContext *C)
return ((ob != NULL) && !ID_IS_LINKED(ob) && !ed_object_hidden(ob) && (ob->type == OB_FONT));
}
+bool ED_operator_editable_mesh(bContext *C)
+{
+ Mesh *mesh = ED_mesh_context(C);
+ return (mesh != NULL) && !ID_IS_LINKED(mesh);
+}
+
bool ED_operator_editmesh(bContext *C)
{
Object *obedit = CTX_data_edit_object(C);
@@ -4200,6 +4207,7 @@ static int match_region_with_redraws(int spacetype,
static int screen_animation_step(bContext *C, wmOperator *UNUSED(op), const wmEvent *event)
{
bScreen *screen = CTX_wm_screen(C);
+ wmWindow *win = CTX_wm_window(C);
#ifdef PROFILE_AUDIO_SYNCH
static int old_frame = 0;
@@ -4209,8 +4217,9 @@ static int screen_animation_step(bContext *C, wmOperator *UNUSED(op), const wmEv
if (screen->animtimer && screen->animtimer == event->customdata) {
Main *bmain = CTX_data_main(C);
Scene *scene = CTX_data_scene(C);
- Depsgraph *depsgraph = CTX_data_depsgraph(C);
- Scene *scene_eval = DEG_get_evaluated_scene(depsgraph);
+ ViewLayer *view_layer = WM_window_get_active_view_layer(win);
+ Depsgraph *depsgraph = BKE_scene_get_depsgraph(scene, view_layer, false);
+ Scene *scene_eval = (depsgraph != NULL) ? DEG_get_evaluated_scene(depsgraph) : NULL;
wmTimer *wt = screen->animtimer;
ScreenAnimData *sad = wt->customdata;
wmWindowManager *wm = CTX_wm_manager(C);
@@ -4230,7 +4239,11 @@ static int screen_animation_step(bContext *C, wmOperator *UNUSED(op), const wmEv
sync = (scene->flag & SCE_FRAME_DROP);
}
- if (scene_eval->id.recalc & ID_RECALC_AUDIO_SEEK) {
+ if (scene_eval == NULL) {
+ /* Happens when undo/redo system is used during playback, nothing meaningful we can do here.
+ */
+ }
+ else if (scene_eval->id.recalc & ID_RECALC_AUDIO_SEEK) {
/* Ignore seek here, the audio will be updated to the scene frame after jump during next
* dependency graph update. */
}
@@ -4335,7 +4348,9 @@ static int screen_animation_step(bContext *C, wmOperator *UNUSED(op), const wmEv
}
/* since we follow drawflags, we can't send notifier but tag regions ourselves */
- ED_update_for_newframe(bmain, depsgraph);
+ if (depsgraph != NULL) {
+ ED_update_for_newframe(bmain, depsgraph);
+ }
for (window = wm->windows.first; window; window = window->next) {
const bScreen *win_screen = WM_window_get_active_screen(window);
diff --git a/source/blender/editors/screen/screen_user_menu.c b/source/blender/editors/screen/screen_user_menu.c
index 86be939d41b..26849edeb44 100644
--- a/source/blender/editors/screen/screen_user_menu.c
+++ b/source/blender/editors/screen/screen_user_menu.c
@@ -298,7 +298,7 @@ void ED_screen_user_menu_register(void)
{
MenuType *mt = MEM_callocN(sizeof(MenuType), __func__);
strcpy(mt->idname, "SCREEN_MT_user_menu");
- strcpy(mt->label, "Quick Favorites");
+ strcpy(mt->label, N_("Quick Favorites"));
strcpy(mt->translation_context, BLT_I18NCONTEXT_DEFAULT_BPYRNA);
mt->draw = screen_user_menu_draw;
WM_menutype_add(mt);
diff --git a/source/blender/editors/screen/screendump.c b/source/blender/editors/screen/screendump.c
index e5552314a6e..005c76d26b0 100644
--- a/source/blender/editors/screen/screendump.c
+++ b/source/blender/editors/screen/screendump.c
@@ -110,24 +110,6 @@ static void screenshot_data_free(wmOperator *op)
}
}
-static void screenshot_crop(ImBuf *ibuf, rcti crop)
-{
- unsigned int *to = ibuf->rect;
- unsigned int *from = ibuf->rect + crop.ymin * ibuf->x + crop.xmin;
- int crop_x = BLI_rcti_size_x(&crop);
- int crop_y = BLI_rcti_size_y(&crop);
- int y;
-
- if (crop_x > 0 && crop_y > 0) {
- for (y = 0; y < crop_y; y++, to += crop_x, from += ibuf->x) {
- memmove(to, from, sizeof(unsigned int) * crop_x);
- }
-
- ibuf->x = crop_x;
- ibuf->y = crop_y;
- }
-}
-
static int screenshot_exec(bContext *C, wmOperator *op)
{
ScreenshotData *scd = op->customdata;
@@ -153,7 +135,8 @@ static int screenshot_exec(bContext *C, wmOperator *op)
/* crop to show only single editor */
if (!RNA_boolean_get(op->ptr, "full")) {
- screenshot_crop(ibuf, scd->crop);
+ IMB_rect_crop(ibuf, &scd->crop);
+ scd->dumprect = ibuf->rect;
}
if (scd->im_format.planes == R_IMF_PLANES_BW) {
diff --git a/source/blender/editors/screen/workspace_edit.c b/source/blender/editors/screen/workspace_edit.c
index f4138dd7847..61b737589c8 100644
--- a/source/blender/editors/screen/workspace_edit.c
+++ b/source/blender/editors/screen/workspace_edit.c
@@ -331,30 +331,6 @@ static void WORKSPACE_OT_delete(wmOperatorType *ot)
ot->exec = workspace_delete_exec;
}
-static bool workspace_append_activate_poll(bContext *C)
-{
- wmOperatorType *ot = WM_operatortype_find("WM_OT_append", false);
- return WM_operator_poll(C, ot);
-}
-
-static int workspace_append(bContext *C, const char *directory, const char *idname)
-{
- wmOperatorType *ot = WM_operatortype_find("WM_OT_append", false);
- PointerRNA opptr;
- int retval;
-
- WM_operator_properties_create_ptr(&opptr, ot);
- RNA_string_set(&opptr, "directory", directory);
- RNA_string_set(&opptr, "filename", idname);
- RNA_boolean_set(&opptr, "autoselect", false);
-
- retval = WM_operator_name_call_ptr(C, ot, WM_OP_EXEC_DEFAULT, &opptr);
-
- WM_operator_properties_free(&opptr);
-
- return retval;
-}
-
static int workspace_append_activate_exec(bContext *C, wmOperator *op)
{
Main *bmain = CTX_data_main(C);
@@ -367,23 +343,20 @@ static int workspace_append_activate_exec(bContext *C, wmOperator *op)
RNA_string_get(op->ptr, "idname", idname);
RNA_string_get(op->ptr, "filepath", filepath);
- if (workspace_append(C, filepath, idname) != OPERATOR_CANCELLED) {
- WorkSpace *appended_workspace = BLI_findstring(
- &bmain->workspaces, idname, offsetof(ID, name) + 2);
- BLI_assert(appended_workspace != NULL);
+ WorkSpace *appended_workspace = (WorkSpace *)WM_file_append_datablock(
+ C, filepath, ID_WS, idname);
- if (appended_workspace) {
- /* Set defaults. */
- BLO_update_defaults_workspace(appended_workspace, NULL);
+ if (appended_workspace) {
+ /* Set defaults. */
+ BLO_update_defaults_workspace(appended_workspace, NULL);
- /* Reorder to last position. */
- BKE_id_reorder(&bmain->workspaces, &appended_workspace->id, NULL, true);
+ /* 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;
@@ -398,7 +371,6 @@ static void WORKSPACE_OT_append_activate(wmOperatorType *ot)
/* api callbacks */
ot->exec = workspace_append_activate_exec;
- ot->poll = workspace_append_activate_poll;
RNA_def_string(ot->srna,
"idname",
@@ -449,25 +421,21 @@ static void workspace_append_button(uiLayout *layout,
{
const ID *id = (ID *)workspace;
PointerRNA opptr;
- char lib_path[FILE_MAX_LIBEXTRA];
const char *filepath = from_main->name;
if (strlen(filepath) == 0) {
filepath = BLO_EMBEDDED_STARTUP_BLEND;
}
- BLI_path_join(lib_path, sizeof(lib_path), filepath, BKE_idcode_to_name(GS(id->name)), NULL);
-
BLI_assert(STREQ(ot_append->idname, "WORKSPACE_OT_append_activate"));
uiItemFullO_ptr(
layout, ot_append, workspace->id.name + 2, ICON_NONE, NULL, WM_OP_EXEC_DEFAULT, 0, &opptr);
RNA_string_set(&opptr, "idname", id->name + 2);
- RNA_string_set(&opptr, "filepath", lib_path);
+ RNA_string_set(&opptr, "filepath", filepath);
}
-static void workspace_add_menu(bContext *C, uiLayout *layout, void *template_v)
+static void workspace_add_menu(bContext *UNUSED(C), uiLayout *layout, void *template_v)
{
- Main *bmain = CTX_data_main(C);
const char *app_template = template_v;
bool has_startup_items = false;
@@ -479,10 +447,6 @@ static void workspace_add_menu(bContext *C, uiLayout *layout, void *template_v)
for (WorkSpace *workspace = startup_config->workspaces.first; workspace;
workspace = workspace->id.next) {
uiLayout *row = uiLayoutRow(layout, false);
- if (BLI_findstring(&bmain->workspaces, workspace->id.name, offsetof(ID, name))) {
- uiLayoutSetActive(row, false);
- }
-
workspace_append_button(row, ot_append, workspace, startup_config->main);
has_startup_items = true;
}
@@ -506,10 +470,6 @@ static void workspace_add_menu(bContext *C, uiLayout *layout, void *template_v)
}
uiLayout *row = uiLayoutRow(layout, false);
- if (BLI_findstring(&bmain->workspaces, workspace->id.name, offsetof(ID, name))) {
- uiLayoutSetActive(row, false);
- }
-
workspace_append_button(row, ot_append, workspace, builtin_config->main);
}
}
diff --git a/source/blender/editors/sculpt_paint/paint_cursor.c b/source/blender/editors/sculpt_paint/paint_cursor.c
index 65e24cecf82..ac74afce79e 100644
--- a/source/blender/editors/sculpt_paint/paint_cursor.c
+++ b/source/blender/editors/sculpt_paint/paint_cursor.c
@@ -964,9 +964,9 @@ static void paint_draw_curve_cursor(Brush *brush, ViewContext *vc)
immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
float selec_col[4], handle_col[4], pivot_col[4];
- UI_GetThemeColor4fv(TH_VERTEX_SELECT, selec_col);
- UI_GetThemeColor4fv(TH_PAINT_CURVE_HANDLE, handle_col);
- UI_GetThemeColor4fv(TH_PAINT_CURVE_PIVOT, pivot_col);
+ UI_GetThemeColorType4fv(TH_VERTEX_SELECT, SPACE_VIEW3D, selec_col);
+ UI_GetThemeColorType4fv(TH_PAINT_CURVE_HANDLE, SPACE_VIEW3D, handle_col);
+ UI_GetThemeColorType4fv(TH_PAINT_CURVE_PIVOT, SPACE_VIEW3D, pivot_col);
for (i = 0; i < pc->tot_points - 1; i++, cp++) {
int j;
diff --git a/source/blender/editors/sculpt_paint/paint_curve_undo.c b/source/blender/editors/sculpt_paint/paint_curve_undo.c
index c03cb69df88..7e283274383 100644
--- a/source/blender/editors/sculpt_paint/paint_curve_undo.c
+++ b/source/blender/editors/sculpt_paint/paint_curve_undo.c
@@ -122,7 +122,8 @@ static bool paintcurve_undosys_step_encode(struct bContext *C,
static void paintcurve_undosys_step_decode(struct bContext *UNUSED(C),
struct Main *UNUSED(bmain),
UndoStep *us_p,
- int UNUSED(dir))
+ int UNUSED(dir),
+ bool UNUSED(is_final))
{
PaintCurveUndoStep *us = (PaintCurveUndoStep *)us_p;
undocurve_to_paintcurve(&us->data, us->pc);
diff --git a/source/blender/editors/sculpt_paint/paint_hide.c b/source/blender/editors/sculpt_paint/paint_hide.c
index dded9fcf45a..d7e1b47d973 100644
--- a/source/blender/editors/sculpt_paint/paint_hide.c
+++ b/source/blender/editors/sculpt_paint/paint_hide.c
@@ -126,7 +126,8 @@ static void partialvis_update_mesh(Object *ob,
/* Hide or show elements in multires grids with a special GridFlags
* customdata layer. */
-static void partialvis_update_grids(Object *ob,
+static void partialvis_update_grids(Depsgraph *depsgraph,
+ Object *ob,
PBVH *pbvh,
PBVHNode *node,
PartialVisAction action,
@@ -208,7 +209,7 @@ static void partialvis_update_grids(Object *ob,
if (any_changed) {
BKE_pbvh_node_mark_rebuild_draw(node);
BKE_pbvh_node_fully_hidden_set(node, !any_visible);
- multires_mark_as_modified(ob, MULTIRES_HIDDEN_MODIFIED);
+ multires_mark_as_modified(depsgraph, ob, MULTIRES_HIDDEN_MODIFIED);
}
}
@@ -378,7 +379,7 @@ static int hide_show_exec(bContext *C, wmOperator *op)
partialvis_update_mesh(ob, pbvh, nodes[i], action, area, clip_planes);
break;
case PBVH_GRIDS:
- partialvis_update_grids(ob, pbvh, nodes[i], action, area, clip_planes);
+ partialvis_update_grids(depsgraph, ob, pbvh, nodes[i], action, area, clip_planes);
break;
case PBVH_BMESH:
partialvis_update_bmesh(ob, pbvh, nodes[i], action, area, clip_planes);
diff --git a/source/blender/editors/sculpt_paint/paint_image_proj.c b/source/blender/editors/sculpt_paint/paint_image_proj.c
index 79731a6752d..22de22e8e59 100644
--- a/source/blender/editors/sculpt_paint/paint_image_proj.c
+++ b/source/blender/editors/sculpt_paint/paint_image_proj.c
@@ -1554,9 +1554,8 @@ static void screen_px_from_persp(const float uv[2],
w_int[2] *= wtot_inv;
}
else {
- w[0] = w[1] = w[2] =
- /* dummy values for zero area face */
- w_int[0] = w_int[1] = w_int[2] = 1.0f / 3.0f;
+ /* Dummy values for zero area face. */
+ w[0] = w[1] = w[2] = w_int[0] = w_int[1] = w_int[2] = 1.0f / 3.0f;
}
/* done re-weighting */
diff --git a/source/blender/editors/sculpt_paint/paint_image_undo.c b/source/blender/editors/sculpt_paint/paint_image_undo.c
index bb73d424152..e7f100ebacb 100644
--- a/source/blender/editors/sculpt_paint/paint_image_undo.c
+++ b/source/blender/editors/sculpt_paint/paint_image_undo.c
@@ -540,10 +540,8 @@ static void image_undosys_step_decode_redo(ImageUndoStep *us)
}
}
-static void image_undosys_step_decode(struct bContext *C,
- struct Main *bmain,
- UndoStep *us_p,
- int dir)
+static void image_undosys_step_decode(
+ struct bContext *C, struct Main *bmain, UndoStep *us_p, int dir, bool UNUSED(is_final))
{
ImageUndoStep *us = (ImageUndoStep *)us_p;
#if 0
diff --git a/source/blender/editors/sculpt_paint/paint_mask.c b/source/blender/editors/sculpt_paint/paint_mask.c
index 0dd2e8ee968..f60ea8410ef 100644
--- a/source/blender/editors/sculpt_paint/paint_mask.c
+++ b/source/blender/editors/sculpt_paint/paint_mask.c
@@ -167,7 +167,7 @@ static int mask_flood_fill_exec(bContext *C, wmOperator *op)
0, totnode, &data, mask_flood_fill_task_cb, &settings);
if (multires) {
- multires_mark_as_modified(ob, MULTIRES_COORDS_MODIFIED);
+ multires_mark_as_modified(depsgraph, ob, MULTIRES_COORDS_MODIFIED);
}
sculpt_undo_push_end();
@@ -341,7 +341,7 @@ bool ED_sculpt_mask_box_select(struct bContext *C, ViewContext *vc, const rcti *
}
if (multires) {
- multires_mark_as_modified(ob, MULTIRES_COORDS_MODIFIED);
+ multires_mark_as_modified(depsgraph, ob, MULTIRES_COORDS_MODIFIED);
}
sculpt_undo_push_end();
@@ -528,7 +528,7 @@ static int paint_mask_gesture_lasso_exec(bContext *C, wmOperator *op)
}
if (multires) {
- multires_mark_as_modified(ob, MULTIRES_COORDS_MODIFIED);
+ multires_mark_as_modified(depsgraph, ob, MULTIRES_COORDS_MODIFIED);
}
sculpt_undo_push_end();
diff --git a/source/blender/editors/sculpt_paint/paint_vertex.c b/source/blender/editors/sculpt_paint/paint_vertex.c
index 316ae6189f0..980b043bf8b 100644
--- a/source/blender/editors/sculpt_paint/paint_vertex.c
+++ b/source/blender/editors/sculpt_paint/paint_vertex.c
@@ -56,6 +56,7 @@
#include "BKE_paint.h"
#include "BKE_report.h"
#include "BKE_subsurf.h"
+#include "BKE_layer.h"
#include "DEG_depsgraph.h"
@@ -1305,18 +1306,47 @@ static int wpaint_mode_toggle_exec(bContext *C, wmOperator *op)
BKE_paint_toolslots_brush_validate(bmain, &ts->wpaint->paint);
}
- /* When locked, it's almost impossible to select the pose
- * then the object to enter weight paint mode.
+ /* When locked, it's almost impossible to select the pose-object
+ * then the mesh-object to enter weight paint mode.
+ * Even when the object mode is not locked this is inconvenient - so allow in either case.
+ *
* In this case move our pose object in/out of pose mode.
- * This is in fits with the convention of selecting multiple objects and entering a mode. */
- if (scene->toolsettings->object_flag & SCE_OBJECT_MODE_LOCK) {
- Object *ob_arm = modifiers_isDeformedByArmature(ob);
- if (ob_arm && (ob_arm->base_flag & BASE_SELECTED)) {
- if (ob_arm->mode & OB_MODE_POSE) {
- ED_object_posemode_exit_ex(bmain, ob_arm);
- }
- else {
- ED_object_posemode_enter_ex(bmain, ob_arm);
+ * This is in fits with the convention of selecting multiple objects and entering a mode.
+ */
+ {
+ VirtualModifierData virtualModifierData;
+ ModifierData *md = modifiers_getVirtualModifierList(ob, &virtualModifierData);
+ if (md != NULL) {
+ /* Can be NULL. */
+ View3D *v3d = CTX_wm_view3d(C);
+ ViewLayer *view_layer = CTX_data_view_layer(C);
+ for (; md; md = md->next) {
+ if (md->type == eModifierType_Armature) {
+ ArmatureModifierData *amd = (ArmatureModifierData *)md;
+ Object *ob_arm = amd->object;
+ if (ob_arm != NULL) {
+ const Base *base_arm = BKE_view_layer_base_find(view_layer, ob_arm);
+ if (base_arm && BASE_VISIBLE(v3d, base_arm)) {
+ if (is_mode_set) {
+ if ((ob_arm->mode & OB_MODE_POSE) != 0) {
+ ED_object_posemode_exit_ex(bmain, ob_arm);
+ }
+ }
+ else {
+ /* Only check selected status when entering weight-paint mode
+ * because we may have multiple armature objects.
+ * Selecting one will de-select the other, which would leave it in pose-mode
+ * when exiting weight paint mode. While usable, this looks like inconsistent
+ * behavior from a user perspective. */
+ if (base_arm->flag & BASE_SELECTED) {
+ if ((ob_arm->mode & OB_MODE_POSE) == 0) {
+ ED_object_posemode_enter_ex(bmain, ob_arm);
+ }
+ }
+ }
+ }
+ }
+ }
}
}
}
@@ -2271,7 +2301,6 @@ static void wpaint_stroke_update_step(bContext *C, struct PaintStroke *stroke, P
vwpaint_update_cache_variants(C, wp, ob, itemptr);
float mat[4][4];
- float mval[2];
const float brush_alpha_value = BKE_brush_alpha_get(scene, brush);
@@ -2321,7 +2350,7 @@ static void wpaint_stroke_update_step(bContext *C, struct PaintStroke *stroke, P
/* calculate pivot for rotation around seletion if needed */
/* also needed for "View Selected" on last stroke */
- paint_last_stroke_update(scene, vc->ar, mval);
+ paint_last_stroke_update(scene, vc->ar, ss->cache->mouse);
BKE_mesh_batch_cache_dirty_tag(ob->data, BKE_MESH_BATCH_DIRTY_ALL);
@@ -3273,12 +3302,12 @@ static void vpaint_stroke_update_step(bContext *C, struct PaintStroke *stroke, P
VPaint *vp = ts->vpaint;
ViewContext *vc = &vpd->vc;
Object *ob = vc->obact;
+ SculptSession *ss = ob->sculpt;
Sculpt *sd = CTX_data_tool_settings(C)->sculpt;
vwpaint_update_cache_variants(C, vp, ob, itemptr);
float mat[4][4];
- float mval[2];
ED_view3d_init_mats_rv3d(ob, vc->rv3d);
@@ -3300,7 +3329,7 @@ static void vpaint_stroke_update_step(bContext *C, struct PaintStroke *stroke, P
/* calculate pivot for rotation around seletion if needed */
/* also needed for "View Selected" on last stroke */
- paint_last_stroke_update(scene, vc->ar, mval);
+ paint_last_stroke_update(scene, vc->ar, ss->cache->mouse);
ED_region_tag_redraw(vc->ar);
diff --git a/source/blender/editors/sculpt_paint/sculpt.c b/source/blender/editors/sculpt_paint/sculpt.c
index ec7cb410f2c..173d6ed5085 100644
--- a/source/blender/editors/sculpt_paint/sculpt.c
+++ b/source/blender/editors/sculpt_paint/sculpt.c
@@ -5186,15 +5186,13 @@ static void sculpt_flush_update_step(bContext *C)
{
Depsgraph *depsgraph = CTX_data_depsgraph(C);
Object *ob = CTX_data_active_object(C);
- Object *ob_eval = DEG_get_evaluated_object(depsgraph, ob);
SculptSession *ss = ob->sculpt;
ARegion *ar = CTX_wm_region(C);
MultiresModifierData *mmd = ss->multires;
View3D *v3d = CTX_wm_view3d(C);
if (mmd != NULL) {
- /* NOTE: SubdivCCG is living in the evaluated object. */
- multires_mark_as_modified(ob_eval, MULTIRES_COORDS_MODIFIED);
+ multires_mark_as_modified(depsgraph, ob, MULTIRES_COORDS_MODIFIED);
}
DEG_id_tag_update(&ob->id, ID_RECALC_SHADING);
diff --git a/source/blender/editors/sculpt_paint/sculpt_undo.c b/source/blender/editors/sculpt_paint/sculpt_undo.c
index 8c8d4487ada..81bb9c35817 100644
--- a/source/blender/editors/sculpt_paint/sculpt_undo.c
+++ b/source/blender/editors/sculpt_paint/sculpt_undo.c
@@ -554,10 +554,10 @@ static void sculpt_undo_restore_list(bContext *C, ListBase *lb)
if (BKE_sculpt_multires_active(scene, ob)) {
if (rebuild) {
- multires_mark_as_modified(ob, MULTIRES_HIDDEN_MODIFIED);
+ multires_mark_as_modified(depsgraph, ob, MULTIRES_HIDDEN_MODIFIED);
}
else {
- multires_mark_as_modified(ob, MULTIRES_COORDS_MODIFIED);
+ multires_mark_as_modified(depsgraph, ob, MULTIRES_COORDS_MODIFIED);
}
}
@@ -1109,10 +1109,8 @@ static void sculpt_undosys_step_decode_redo(struct bContext *C, SculptUndoStep *
}
}
-static void sculpt_undosys_step_decode(struct bContext *C,
- struct Main *bmain,
- UndoStep *us_p,
- int dir)
+static void sculpt_undosys_step_decode(
+ struct bContext *C, struct Main *bmain, UndoStep *us_p, int dir, bool UNUSED(is_final))
{
/* Ensure sculpt mode. */
{
diff --git a/source/blender/editors/sound/sound_ops.c b/source/blender/editors/sound/sound_ops.c
index 30ddd8c7d33..0241a2fbe88 100644
--- a/source/blender/editors/sound/sound_ops.c
+++ b/source/blender/editors/sound/sound_ops.c
@@ -104,7 +104,7 @@ static int sound_open_exec(bContext *C, wmOperator *op)
}
if (RNA_boolean_get(op->ptr, "cache")) {
- BKE_sound_cache(sound);
+ sound->flags |= SOUND_FLAGS_CACHING;
}
/* hook into UI */
@@ -765,7 +765,8 @@ static int sound_pack_exec(bContext *C, wmOperator *op)
return OPERATOR_CANCELLED;
}
- sound->packedfile = newPackedFile(op->reports, sound->name, ID_BLEND_PATH(bmain, &sound->id));
+ sound->packedfile = BKE_packedfile_new(
+ op->reports, sound->name, ID_BLEND_PATH(bmain, &sound->id));
BKE_sound_load(bmain, sound);
return OPERATOR_FINISHED;
@@ -811,7 +812,7 @@ static int sound_unpack_exec(bContext *C, wmOperator *op)
"AutoPack is enabled, so image will be packed again on file save");
}
- unpackSound(bmain, op->reports, sound, method);
+ BKE_packedfile_unpack_sound(bmain, op->reports, sound, method);
return OPERATOR_FINISHED;
}
diff --git a/source/blender/editors/space_clip/clip_draw.c b/source/blender/editors/space_clip/clip_draw.c
index 99f9a91775e..e3fa8edd714 100644
--- a/source/blender/editors/space_clip/clip_draw.c
+++ b/source/blender/editors/space_clip/clip_draw.c
@@ -1378,10 +1378,11 @@ static void draw_plane_marker_ex(SpaceClip *sc,
immEnd();
}
}
+ immUnbindProgram();
/* Draw sliders. */
if (is_selected_track) {
- immUniform1f("dash_factor", 2.0f); /* Solid line */
+ immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
if (draw_outline) {
immUniformThemeColor(TH_MARKER_OUTLINE);
@@ -1400,9 +1401,8 @@ static void draw_plane_marker_ex(SpaceClip *sc,
px,
shdr_pos);
}
+ immUnbindProgram();
}
-
- immUnbindProgram();
}
}
diff --git a/source/blender/editors/space_clip/clip_ops.c b/source/blender/editors/space_clip/clip_ops.c
index 83d8133a99e..45479c4253d 100644
--- a/source/blender/editors/space_clip/clip_ops.c
+++ b/source/blender/editors/space_clip/clip_ops.c
@@ -1515,6 +1515,11 @@ static int mode_set_exec(bContext *C, wmOperator *op)
sc->mode = mode;
+ if (sc->mode == SC_MODE_MASKEDIT && sc->view != SC_VIEW_CLIP) {
+ /* Make sure we are in the right view for mask editing */
+ sc->view = SC_VIEW_CLIP;
+ }
+
WM_event_add_notifier(C, NC_SPACE | ND_SPACE_CLIP, NULL);
return OPERATOR_FINISHED;
diff --git a/source/blender/editors/space_clip/space_clip.c b/source/blender/editors/space_clip/space_clip.c
index c290e3a21d1..7e19ac255f0 100644
--- a/source/blender/editors/space_clip/space_clip.c
+++ b/source/blender/editors/space_clip/space_clip.c
@@ -420,6 +420,14 @@ static void clip_listener(wmWindow *UNUSED(win), ScrArea *sa, wmNotifier *wmn, S
ED_area_tag_redraw(sa);
}
break;
+ case NC_WM:
+ switch (wmn->data) {
+ case ND_FILEREAD:
+ case ND_UNDO:
+ clip_area_sync_frame_from_scene(sa, scene);
+ break;
+ }
+ break;
}
}
diff --git a/source/blender/editors/space_clip/tracking_ops_plane.c b/source/blender/editors/space_clip/tracking_ops_plane.c
index 89478375658..b1bf88634bc 100644
--- a/source/blender/editors/space_clip/tracking_ops_plane.c
+++ b/source/blender/editors/space_clip/tracking_ops_plane.c
@@ -74,6 +74,7 @@ static int create_plane_track_tracks_exec(bContext *C, wmOperator *op)
BKE_tracking_track_plane_from_existing_motion(plane_track, framenr);
}
+ DEG_id_tag_update(&clip->id, ID_RECALC_COPY_ON_WRITE);
WM_event_add_notifier(C, NC_MOVIECLIP | NA_EDITED, clip);
return OPERATOR_FINISHED;
@@ -337,8 +338,7 @@ static int slide_plane_marker_modal(bContext *C, wmOperator *op, const wmEvent *
data->previous_mval[1] = event->mval[1];
copy_v2_v2(data->previous_corner, data->corner);
- DEG_id_tag_update(&sc->clip->id, 0);
-
+ DEG_id_tag_update(&clip->id, ID_RECALC_COPY_ON_WRITE);
WM_event_add_notifier(C, NC_MOVIECLIP | NA_EDITED, NULL);
break;
@@ -355,7 +355,7 @@ static int slide_plane_marker_modal(bContext *C, wmOperator *op, const wmEvent *
clip_tracking_show_cursor(C);
- DEG_id_tag_update(&sc->clip->id, 0);
+ DEG_id_tag_update(&clip->id, ID_RECALC_COPY_ON_WRITE);
WM_event_add_notifier(C, NC_MOVIECLIP | NA_EDITED, clip);
return OPERATOR_FINISHED;
diff --git a/source/blender/editors/space_file/file_ops.c b/source/blender/editors/space_file/file_ops.c
index 15f87235c0d..4e50413513a 100644
--- a/source/blender/editors/space_file/file_ops.c
+++ b/source/blender/editors/space_file/file_ops.c
@@ -1736,7 +1736,7 @@ static int file_smoothscroll_invoke(bContext *C, wmOperator *UNUSED(op), const w
((numfiles % items_block_size) != 0 ? items_block_size : 0)) -
(numfiles_layout / 2);
/* Actual (physical) scrolling info, in pixels, used to detect whether we are fully at the
- * begining/end of the view. */
+ * beginning/end of the view. */
/* Note that there is a weird glitch, that sometimes tot rctf is smaller than cur rctf...
* that is why we still need to keep the min/max_middle_offset checks too. :( */
const float min_tot_scroll = is_horizontal ? ar->v2d.tot.xmin : -ar->v2d.tot.ymax;
@@ -1747,16 +1747,16 @@ static int file_smoothscroll_invoke(bContext *C, wmOperator *UNUSED(op), const w
/* Check if we have reached our final scroll position. */
/* Filelist has to be ready, otherwise it makes no sense to stop scrolling yet. */
const bool is_ready = filelist_is_ready(sfile->files);
- /* Edited item must be in the 'middle' of shown area (kind of approximative).
+ /* Edited item must be in the 'middle' of shown area (kind of approximated).
* Note that we have to do the check in 'block space', not in 'item space' here. */
const bool is_centered = (abs(middle_offset / items_block_size -
sfile->scroll_offset / items_block_size) == 0);
- /* OR edited item must be towards the begining, and we are scrolled fully to the start. */
+ /* OR edited item must be towards the beginning, and we are scrolled fully to the start. */
const bool is_full_start = ((sfile->scroll_offset < min_middle_offset) &&
(min_curr_scroll - min_tot_scroll < 1.0f) &&
(middle_offset - min_middle_offset < items_block_size));
/* OR edited item must be towards the end, and we are scrolled fully to the end.
- * This one is crucial (unlike the one for the begining), because without it we won't scroll
+ * This one is crucial (unlike the one for the beginning), because without it we won't scroll
* fully to the end, and last column or row wil end up only partially drawn. */
const bool is_full_end = ((sfile->scroll_offset > max_middle_offset) &&
(max_tot_scroll - max_curr_scroll < 1.0f) &&
diff --git a/source/blender/editors/space_image/image_draw.c b/source/blender/editors/space_image/image_draw.c
index 86db6d50fcc..97a3c7f2480 100644
--- a/source/blender/editors/space_image/image_draw.c
+++ b/source/blender/editors/space_image/image_draw.c
@@ -797,6 +797,11 @@ void draw_image_main(const bContext *C, ARegion *ar)
ima = ED_space_image(sima);
ED_space_image_get_zoom(sima, ar, &zoomx, &zoomy);
+ /* Tag image as in active use for garbage collector. */
+ if (ima) {
+ BKE_image_tag_time(ima);
+ }
+
show_viewer = (ima && ima->source == IMA_SRC_VIEWER) != 0;
show_render = (show_viewer && ima->type == IMA_TYPE_R_RESULT) != 0;
show_paint = (ima && (sima->mode == SI_MODE_PAINT) && (show_viewer == false) &&
diff --git a/source/blender/editors/space_image/image_ops.c b/source/blender/editors/space_image/image_ops.c
index 96eaa89d175..b79ed1c83c4 100644
--- a/source/blender/editors/space_image/image_ops.c
+++ b/source/blender/editors/space_image/image_ops.c
@@ -1391,7 +1391,7 @@ static int image_open_exec(bContext *C, wmOperator *op)
BKE_image_init_imageuser(ima, iuser);
}
- /* XXX unpackImage frees image buffers */
+ /* XXX BKE_packedfile_unpack_image frees image buffers */
ED_preview_kill_jobs(CTX_wm_manager(C), bmain);
BKE_image_signal(bmain, ima, iuser, IMA_SIGNAL_RELOAD);
@@ -1601,7 +1601,7 @@ static int image_replace_exec(bContext *C, wmOperator *op)
sima->image->source = IMA_SRC_FILE;
}
- /* XXX unpackImage frees image buffers */
+ /* XXX BKE_packedfile_unpack_image frees image buffers */
ED_preview_kill_jobs(CTX_wm_manager(C), CTX_data_main(C));
BKE_icon_changed(BKE_icon_id_ensure(&sima->image->id));
@@ -2401,7 +2401,7 @@ static int image_reload_exec(bContext *C, wmOperator *UNUSED(op))
return OPERATOR_CANCELLED;
}
- /* XXX unpackImage frees image buffers */
+ /* XXX BKE_packedfile_unpack_image frees image buffers */
ED_preview_kill_jobs(CTX_wm_manager(C), CTX_data_main(C));
BKE_image_signal(bmain, ima, iuser, IMA_SIGNAL_RELOAD);
@@ -2859,10 +2859,10 @@ static int image_unpack_exec(bContext *C, wmOperator *op)
"AutoPack is enabled, so image will be packed again on file save");
}
- /* XXX unpackImage frees image buffers */
+ /* XXX BKE_packedfile_unpack_image frees image buffers */
ED_preview_kill_jobs(CTX_wm_manager(C), CTX_data_main(C));
- unpackImage(CTX_data_main(C), op->reports, ima, method);
+ BKE_packedfile_unpack_image(CTX_data_main(C), op->reports, ima, method);
WM_event_add_notifier(C, NC_IMAGE | NA_EDITED, ima);
diff --git a/source/blender/editors/space_image/space_image.c b/source/blender/editors/space_image/space_image.c
index 6bf79711ae5..e8116193c1f 100644
--- a/source/blender/editors/space_image/space_image.c
+++ b/source/blender/editors/space_image/space_image.c
@@ -843,6 +843,11 @@ static void image_buttons_region_listener(wmWindow *UNUSED(win),
ED_region_tag_redraw(ar);
}
break;
+ case NC_BRUSH:
+ if (wmn->action == NA_EDITED) {
+ ED_region_tag_redraw(ar);
+ }
+ break;
}
}
@@ -946,6 +951,11 @@ static void image_header_region_listener(wmWindow *UNUSED(win),
break;
}
break;
+ case NC_BRUSH:
+ if (wmn->action == NA_EDITED) {
+ ED_region_tag_redraw(ar);
+ }
+ break;
}
}
diff --git a/source/blender/editors/space_info/info_ops.c b/source/blender/editors/space_info/info_ops.c
index bf43e493cc5..14817e9ffa1 100644
--- a/source/blender/editors/space_info/info_ops.c
+++ b/source/blender/editors/space_info/info_ops.c
@@ -65,7 +65,7 @@ static int pack_libraries_exec(bContext *C, wmOperator *op)
{
Main *bmain = CTX_data_main(C);
- packLibraries(bmain, op->reports);
+ BKE_packedfile_pack_all_libraries(bmain, op->reports);
return OPERATOR_FINISHED;
}
@@ -88,7 +88,7 @@ static int unpack_libraries_exec(bContext *C, wmOperator *op)
{
Main *bmain = CTX_data_main(C);
- unpackLibraries(bmain, op->reports);
+ BKE_packedfile_unpack_all_libraries(bmain, op->reports);
return OPERATOR_FINISHED;
}
@@ -124,7 +124,7 @@ static int autopack_toggle_exec(bContext *C, wmOperator *op)
G.fileflags &= ~G_FILE_AUTOPACK;
}
else {
- packAll(bmain, op->reports, true);
+ BKE_packedfile_pack_all(bmain, op->reports, true);
G.fileflags |= G_FILE_AUTOPACK;
}
@@ -151,7 +151,7 @@ static int pack_all_exec(bContext *C, wmOperator *op)
{
Main *bmain = CTX_data_main(C);
- packAll(bmain, op->reports, true);
+ BKE_packedfile_pack_all(bmain, op->reports, true);
return OPERATOR_FINISHED;
}
@@ -221,7 +221,7 @@ static int unpack_all_exec(bContext *C, wmOperator *op)
int method = RNA_enum_get(op->ptr, "method");
if (method != PF_KEEP) {
- unpackAll(bmain, op->reports, method); /* XXX PF_ASK can't work here */
+ BKE_packedfile_unpack_all(bmain, op->reports, method); /* XXX PF_ASK can't work here */
}
G.fileflags &= ~G_FILE_AUTOPACK;
@@ -236,7 +236,7 @@ static int unpack_all_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(
char title[64];
int count = 0;
- count = countPackedFiles(bmain);
+ count = BKE_packedfile_count_all(bmain);
if (!count) {
BKE_report(op->reports, RPT_WARNING, "No packed files to unpack");
@@ -321,7 +321,7 @@ static int unpack_item_exec(bContext *C, wmOperator *op)
}
if (method != PF_KEEP) {
- BKE_unpack_id(bmain, id, op->reports, method); /* XXX PF_ASK can't work here */
+ BKE_packedfile_id_unpack(bmain, id, op->reports, method); /* XXX PF_ASK can't work here */
}
G.fileflags &= ~G_FILE_AUTOPACK;
@@ -545,7 +545,8 @@ static int update_reports_display_invoke(bContext *C, wmOperator *UNUSED(op), co
/* escape if not our timer */
if ((reports->reporttimer == NULL) || (reports->reporttimer != event->customdata) ||
- ((report = BKE_reports_last_displayable(reports)) == NULL) /* may have been deleted */
+ ((report = BKE_reports_last_displayable(reports)) == NULL)
+ /* may have been deleted */
) {
return OPERATOR_PASS_THROUGH;
}
diff --git a/source/blender/editors/space_node/node_edit.c b/source/blender/editors/space_node/node_edit.c
index a5755ae43c6..d31256a1425 100644
--- a/source/blender/editors/space_node/node_edit.c
+++ b/source/blender/editors/space_node/node_edit.c
@@ -210,6 +210,7 @@ static void compo_initjob(void *cjv)
/* NOTE: Don't update animation to preserve unkeyed changes, this means can not use
* evaluate_on_framechange. */
+ DEG_graph_flush_update(bmain, cj->compositor_depsgraph);
DEG_evaluate_on_refresh(cj->compositor_depsgraph);
bNodeTree *ntree_eval = (bNodeTree *)DEG_get_evaluated_id(cj->compositor_depsgraph,
@@ -2418,6 +2419,7 @@ static int ntree_socket_move_exec(bContext *C, wmOperator *op)
}
}
+ ntree->update |= NTREE_UPDATE_GROUP;
ntreeUpdateTree(CTX_data_main(C), ntree);
snode_notify(C, snode);
diff --git a/source/blender/editors/space_node/node_view.c b/source/blender/editors/space_node/node_view.c
index b33960bb454..7dec6f5a4ef 100644
--- a/source/blender/editors/space_node/node_view.c
+++ b/source/blender/editors/space_node/node_view.c
@@ -347,7 +347,7 @@ static int backimage_fit_exec(bContext *C, wmOperator *UNUSED(op))
BKE_image_release_ibuf(ima, ibuf, lock);
- snode->zoom *= min_ff(facx, facy);
+ snode->zoom *= min_ff(facx, facy) * U.dpi_fac;
snode->xof = 0;
snode->yof = 0;
diff --git a/source/blender/editors/space_outliner/outliner_collections.c b/source/blender/editors/space_outliner/outliner_collections.c
index 459183ff226..4740c412083 100644
--- a/source/blender/editors/space_outliner/outliner_collections.c
+++ b/source/blender/editors/space_outliner/outliner_collections.c
@@ -593,7 +593,7 @@ static int collection_link_exec(bContext *C, wmOperator *op)
if (ID_IS_LINKED(active_collection) ||
((active_collection->flag & COLLECTION_IS_MASTER) && ID_IS_LINKED(scene))) {
- BKE_report(op->reports, RPT_ERROR, "Cannot add a colection to a linked collection/scene");
+ BKE_report(op->reports, RPT_ERROR, "Cannot add a collection to a linked collection/scene");
return OPERATOR_CANCELLED;
}
diff --git a/source/blender/editors/space_outliner/outliner_draw.c b/source/blender/editors/space_outliner/outliner_draw.c
index 86f99555e12..55130ae8894 100644
--- a/source/blender/editors/space_outliner/outliner_draw.c
+++ b/source/blender/editors/space_outliner/outliner_draw.c
@@ -116,6 +116,10 @@ static void outliner_tree_dimensions(SpaceOutliner *soops, int *r_width, int *r_
*/
static bool is_object_data_in_editmode(const ID *id, const Object *obact)
{
+ if (id == NULL) {
+ return false;
+ }
+
const short id_type = GS(id->name);
if (id_type == ID_GD && obact && obact->data == id) {
@@ -929,6 +933,40 @@ static void outliner_restrict_properties_enable_layer_collection_set(
}
}
+static bool outliner_restrict_properties_collection_set(Scene *scene,
+ TreeElement *te,
+ PointerRNA *collection_ptr,
+ PointerRNA *layer_collection_ptr,
+ RestrictProperties *props,
+ RestrictPropertiesActive *props_active)
+{
+ TreeStoreElem *tselem = TREESTORE(te);
+ LayerCollection *layer_collection = (tselem->type == TSE_LAYER_COLLECTION) ? te->directdata :
+ NULL;
+ Collection *collection = outliner_collection_from_tree_element(te);
+
+ if ((collection->flag & COLLECTION_IS_MASTER) ||
+ (layer_collection && ((layer_collection->flag & LAYER_COLLECTION_EXCLUDE) != 0))) {
+ return false;
+ }
+
+ /* Create the PointerRNA. */
+ RNA_id_pointer_create(&collection->id, collection_ptr);
+ if (layer_collection != NULL) {
+ RNA_pointer_create(&scene->id, &RNA_LayerCollection, layer_collection, layer_collection_ptr);
+ }
+
+ /* 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);
+ }
+ return true;
+}
+
static void outliner_draw_restrictbuts(uiBlock *block,
Scene *scene,
ViewLayer *view_layer,
@@ -1333,30 +1371,16 @@ static void outliner_draw_restrictbuts(uiBlock *block,
}
}
else if (outliner_is_collection_tree_element(te)) {
- LayerCollection *layer_collection = (tselem->type == TSE_LAYER_COLLECTION) ?
- te->directdata :
- NULL;
- Collection *collection = outliner_collection_from_tree_element(te);
- if ((!layer_collection || !(layer_collection->flag & LAYER_COLLECTION_EXCLUDE)) &&
- !(collection->flag & COLLECTION_IS_MASTER)) {
+ PointerRNA collection_ptr;
+ PointerRNA layer_collection_ptr;
- 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 (outliner_restrict_properties_collection_set(
+ scene, te, &collection_ptr, &layer_collection_ptr, &props, &props_active)) {
- /* 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);
- }
+ LayerCollection *layer_collection = (tselem->type == TSE_LAYER_COLLECTION) ?
+ te->directdata :
+ NULL;
+ Collection *collection = outliner_collection_from_tree_element(te);
if (layer_collection != NULL) {
if (soops->show_restrict_flags & SO_RESTRICT_HIDE) {
@@ -1443,7 +1467,8 @@ static void outliner_draw_restrictbuts(uiBlock *block,
layer_collection,
(char *)"indirect_only");
UI_but_flag_enable(bt, UI_BUT_DRAG_LOCK);
- if (!props_active.layer_collection_indirect_only) {
+ if (props_active.layer_collection_holdout ||
+ !props_active.layer_collection_indirect_only) {
UI_but_flag_enable(bt, UI_BUT_INACTIVE);
}
}
@@ -1558,6 +1583,12 @@ static void outliner_draw_restrictbuts(uiBlock *block,
}
}
}
+ else if (outliner_is_collection_tree_element(te)) {
+ PointerRNA collection_ptr;
+ PointerRNA layer_collection_ptr;
+ outliner_restrict_properties_collection_set(
+ scene, te, &collection_ptr, &layer_collection_ptr, &props, &props_active);
+ }
if (TSELEM_OPEN(tselem, soops)) {
outliner_draw_restrictbuts(block, scene, view_layer, ar, soops, &te->subtree, props_active);
@@ -2202,7 +2233,7 @@ TreeElementIcon tree_element_get_icon(TreeStoreElem *tselem, TreeElement *te)
data.icon = ICON_OUTLINER_OB_LIGHTPROBE;
break;
case OB_EMPTY:
- if (ob->instance_collection) {
+ if (ob->instance_collection && (ob->transflag & OB_DUPLICOLLECTION)) {
data.icon = ICON_OUTLINER_OB_GROUP_INSTANCE;
}
else if (ob->empty_drawtype == OB_EMPTY_IMAGE) {
diff --git a/source/blender/editors/space_outliner/outliner_tools.c b/source/blender/editors/space_outliner/outliner_tools.c
index e1e7bf49606..89eb3b9d953 100644
--- a/source/blender/editors/space_outliner/outliner_tools.c
+++ b/source/blender/editors/space_outliner/outliner_tools.c
@@ -109,8 +109,9 @@ static void set_operation_types(SpaceOutliner *soops,
}
}
else {
- int idcode = GS(tselem->id->name);
- switch (idcode) {
+ const int idcode = (int)GS(tselem->id->name);
+ bool is_standard_id = false;
+ switch ((ID_Type)idcode) {
case ID_SCE:
*scenelevel = 1;
break;
@@ -134,21 +135,47 @@ static void set_operation_types(SpaceOutliner *soops,
case ID_KE:
case ID_WO:
case ID_AC:
- case ID_NLA:
case ID_TXT:
case ID_GR:
case ID_LS:
case ID_LI:
- if (*idlevel == 0) {
- *idlevel = idcode;
- }
- else if (*idlevel != idcode) {
- *idlevel = -1;
- }
- if (ELEM(*datalevel, TSE_VIEW_COLLECTION_BASE, TSE_SCENE_COLLECTION_BASE)) {
- *datalevel = 0;
- }
+ case ID_VF:
+ case ID_NT:
+ case ID_BR:
+ case ID_PA:
+ case ID_GD:
+ case ID_MC:
+ case ID_MSK:
+ case ID_PAL:
+ case ID_PC:
+ case ID_CF:
+ case ID_WS:
+ case ID_LP:
+ is_standard_id = true;
break;
+ case ID_WM:
+ case ID_SCR:
+ /* Those are ignored here. */
+ /* Note: while Screens should be manageable here, deleting a screen used by a workspace
+ * will cause crashes when trying to use that workspace, so for now let's play minimal,
+ * safe change. */
+ break;
+ }
+ if (idcode == ID_NLA) {
+ /* Fake one, not an actual ID type... */
+ is_standard_id = true;
+ }
+
+ if (is_standard_id) {
+ if (*idlevel == 0) {
+ *idlevel = idcode;
+ }
+ else if (*idlevel != idcode) {
+ *idlevel = -1;
+ }
+ if (ELEM(*datalevel, TSE_VIEW_COLLECTION_BASE, TSE_SCENE_COLLECTION_BASE)) {
+ *datalevel = 0;
+ }
}
}
}
@@ -288,31 +315,33 @@ static void unlink_object_cb(bContext *C,
TreeStoreElem *tselem,
void *UNUSED(user_data))
{
- Main *bmain = CTX_data_main(C);
- Object *ob = (Object *)tselem->id;
+ if (tsep && tsep->id) {
+ Main *bmain = CTX_data_main(C);
+ Object *ob = (Object *)tselem->id;
- if (GS(tsep->id->name) == ID_OB) {
- /* Parented objects need to find which collection to unlink from. */
- TreeElement *te_parent = te->parent;
- while (tsep && GS(tsep->id->name) == ID_OB) {
- te_parent = te_parent->parent;
- tsep = te_parent ? TREESTORE(te_parent) : NULL;
+ if (GS(tsep->id->name) == ID_OB) {
+ /* Parented objects need to find which collection to unlink from. */
+ TreeElement *te_parent = te->parent;
+ while (tsep && GS(tsep->id->name) == ID_OB) {
+ te_parent = te_parent->parent;
+ tsep = te_parent ? TREESTORE(te_parent) : NULL;
+ }
}
- }
- if (tsep) {
- if (GS(tsep->id->name) == ID_GR) {
- Collection *parent = (Collection *)tsep->id;
- BKE_collection_object_remove(bmain, parent, ob, true);
- DEG_id_tag_update(&parent->id, ID_RECALC_COPY_ON_WRITE);
- DEG_relations_tag_update(bmain);
- }
- else if (GS(tsep->id->name) == ID_SCE) {
- Scene *scene = (Scene *)tsep->id;
- Collection *parent = BKE_collection_master(scene);
- BKE_collection_object_remove(bmain, parent, ob, true);
- DEG_id_tag_update(&scene->id, ID_RECALC_COPY_ON_WRITE);
- DEG_relations_tag_update(bmain);
+ if (tsep && tsep->id) {
+ if (GS(tsep->id->name) == ID_GR) {
+ Collection *parent = (Collection *)tsep->id;
+ BKE_collection_object_remove(bmain, parent, ob, true);
+ DEG_id_tag_update(&parent->id, ID_RECALC_COPY_ON_WRITE);
+ DEG_relations_tag_update(bmain);
+ }
+ else if (GS(tsep->id->name) == ID_SCE) {
+ Scene *scene = (Scene *)tsep->id;
+ Collection *parent = BKE_collection_master(scene);
+ BKE_collection_object_remove(bmain, parent, ob, true);
+ DEG_id_tag_update(&scene->id, ID_RECALC_COPY_ON_WRITE);
+ DEG_relations_tag_update(bmain);
+ }
}
}
}
diff --git a/source/blender/editors/space_outliner/outliner_tree.c b/source/blender/editors/space_outliner/outliner_tree.c
index d428a190549..cc062467dbe 100644
--- a/source/blender/editors/space_outliner/outliner_tree.c
+++ b/source/blender/editors/space_outliner/outliner_tree.c
@@ -515,7 +515,7 @@ static void outliner_add_object_contents(SpaceOutliner *soops,
}
/* duplicated group */
- if (ob->instance_collection) {
+ if (ob->instance_collection && (ob->transflag & OB_DUPLICOLLECTION)) {
outliner_add_element(soops, &te->subtree, ob->instance_collection, te, 0, 0);
}
}
@@ -1545,7 +1545,7 @@ static void outliner_make_object_parent_hierarchy_collections(SpaceOutliner *soo
if (!found) {
/* We add the child in the tree even if it is not in the collection.
- * We deliberately clear its subtree though, to make it less proeminent. */
+ * We deliberately clear its sub-tree though, to make it less prominent. */
TreeElement *child_ob_tree_element = outliner_add_element(
soops, &parent_ob_tree_element->subtree, child, parent_ob_tree_element, 0, 0);
outliner_free_tree(&child_ob_tree_element->subtree);
diff --git a/source/blender/editors/space_sequencer/sequencer_draw.c b/source/blender/editors/space_sequencer/sequencer_draw.c
index e53a3cb02a7..76c198b3d6b 100644
--- a/source/blender/editors/space_sequencer/sequencer_draw.c
+++ b/source/blender/editors/space_sequencer/sequencer_draw.c
@@ -2042,8 +2042,6 @@ void draw_timeline_seq(const bContext *C, ARegion *ar)
if (ed) {
/* draw the data */
draw_seq_strips(C, ed, ar);
- draw_cache_view(C);
-
/* text draw cached (for sequence names), in pixelspace now */
UI_view2d_text_cache_draw(ar);
}
@@ -2063,8 +2061,12 @@ void draw_timeline_seq(const bContext *C, ARegion *ar)
}
ED_markers_draw(C, marker_draw_flag);
- /* preview range */
UI_view2d_view_ortho(v2d);
+ /* draw cache on top of markers area */
+ if (ed) {
+ draw_cache_view(C);
+ }
+ /* preview range */
ANIM_draw_previewrange(C, v2d, 1);
/* overlap playhead */
diff --git a/source/blender/editors/space_text/text_autocomplete.c b/source/blender/editors/space_text/text_autocomplete.c
index c36175489b3..b6c660ae5b2 100644
--- a/source/blender/editors/space_text/text_autocomplete.c
+++ b/source/blender/editors/space_text/text_autocomplete.c
@@ -260,7 +260,7 @@ static void get_suggest_prefix(Text *text, int offset)
texttool_suggest_prefix(line + i, len);
}
-static void confirm_suggestion(Text *text, TextUndoBuf *utxt)
+static void confirm_suggestion(Text *text)
{
SuggItem *sel;
int i, over = 0;
@@ -285,7 +285,7 @@ static void confirm_suggestion(Text *text, TextUndoBuf *utxt)
// for (i = 0; i < skipleft; i++)
// txt_move_left(text, 0);
BLI_assert(memcmp(sel->name, &line[i], over) == 0);
- txt_insert_buf(text, utxt, sel->name + over);
+ txt_insert_buf(text, sel->name + over);
// for (i = 0; i < skipleft; i++)
// txt_move_right(text, 0);
@@ -308,8 +308,8 @@ static int text_autocomplete_invoke(bContext *C, wmOperator *op, const wmEvent *
ED_area_tag_redraw(CTX_wm_area(C));
if (texttool_suggest_first() == texttool_suggest_last()) {
- TextUndoBuf *utxt = ED_text_undo_push_init(C);
- confirm_suggestion(st->text, utxt);
+ ED_text_undo_push_init(C);
+ confirm_suggestion(st->text);
text_update_line_edited(st->text->curl);
text_autocomplete_free(C, op);
ED_undo_push(C, op->type->name);
@@ -371,8 +371,8 @@ static int text_autocomplete_modal(bContext *C, wmOperator *op, const wmEvent *e
case MIDDLEMOUSE:
if (event->val == KM_PRESS) {
if (text_do_suggest_select(st, ar)) {
- TextUndoBuf *utxt = ED_text_undo_push_init(C);
- confirm_suggestion(st->text, utxt);
+ ED_text_undo_push_init(C);
+ confirm_suggestion(st->text);
text_update_line_edited(st->text->curl);
ED_undo_push(C, op->type->name);
swallow = 1;
@@ -410,8 +410,8 @@ static int text_autocomplete_modal(bContext *C, wmOperator *op, const wmEvent *e
case PADENTER:
if (event->val == KM_PRESS) {
if (tools & TOOL_SUGG_LIST) {
- TextUndoBuf *utxt = ED_text_undo_push_init(C);
- confirm_suggestion(st->text, utxt);
+ ED_text_undo_push_init(C);
+ confirm_suggestion(st->text);
text_update_line_edited(st->text->curl);
ED_undo_push(C, op->type->name);
swallow = 1;
diff --git a/source/blender/editors/space_text/text_ops.c b/source/blender/editors/space_text/text_ops.c
index 63d4f3e3119..8f7bd83cbf4 100644
--- a/source/blender/editors/space_text/text_ops.c
+++ b/source/blender/editors/space_text/text_ops.c
@@ -241,6 +241,8 @@ static int text_new_exec(bContext *C, wmOperator *UNUSED(op))
PropertyRNA *prop;
text = BKE_text_add(bmain, "Text");
+ /* Texts have no user by default... Only the 'real' user flag. */
+ id_us_min(&text->id);
/* hook into UI */
UI_context_active_but_prop_get_templateID(C, &ptr, &prop);
@@ -307,6 +309,8 @@ static int text_open_exec(bContext *C, wmOperator *op)
RNA_string_get(op->ptr, "filepath", str);
text = BKE_text_load_ex(bmain, str, BKE_main_blendfile_path(bmain), internal);
+ /* Texts have no user by default... Only the 'real' user flag. */
+ id_us_min(&text->id);
if (!text) {
if (op->customdata) {
@@ -322,8 +326,6 @@ static int text_open_exec(bContext *C, wmOperator *op)
/* hook into UI */
pprop = op->customdata;
- id_us_ensure_real(&text->id);
-
if (pprop->prop) {
RNA_id_pointer_create(&text->id, &idptr);
RNA_property_pointer_set(&pprop->ptr, pprop->prop, idptr, NULL);
@@ -840,7 +842,7 @@ static int text_paste_exec(bContext *C, wmOperator *op)
text_drawcache_tag_update(CTX_wm_space_text(C), 0);
- TextUndoBuf *utxt = ED_text_undo_push_init(C);
+ ED_text_undo_push_init(C);
/* Convert clipboard content indentation to spaces if specified */
if (text->flags & TXT_TABSTOSPACES) {
@@ -849,7 +851,7 @@ static int text_paste_exec(bContext *C, wmOperator *op)
buf = new_buf;
}
- txt_insert_buf(text, utxt, buf);
+ txt_insert_buf(text, buf);
text_update_edited(text);
MEM_freeN(buf);
@@ -893,9 +895,9 @@ static int text_duplicate_line_exec(bContext *C, wmOperator *UNUSED(op))
{
Text *text = CTX_data_edit_text(C);
- TextUndoBuf *utxt = ED_text_undo_push_init(C);
+ ED_text_undo_push_init(C);
- txt_duplicate_line(text, utxt);
+ txt_duplicate_line(text);
WM_event_add_notifier(C, NC_TEXT | NA_EDITED, text);
@@ -932,7 +934,7 @@ static void txt_copy_clipboard(Text *text)
return;
}
- buf = txt_sel_to_buf(text);
+ buf = txt_sel_to_buf(text, NULL);
if (buf) {
WM_clipboard_text_set(buf, 0);
@@ -971,8 +973,8 @@ static int text_cut_exec(bContext *C, wmOperator *UNUSED(op))
txt_copy_clipboard(text);
- TextUndoBuf *utxt = ED_text_undo_push_init(C);
- txt_delete_selected(text, utxt);
+ ED_text_undo_push_init(C);
+ txt_delete_selected(text);
text_update_cursor_moved(C);
WM_event_add_notifier(C, NC_TEXT | NA_EDITED, text);
@@ -1008,14 +1010,14 @@ static int text_indent_exec(bContext *C, wmOperator *UNUSED(op))
text_drawcache_tag_update(CTX_wm_space_text(C), 0);
- TextUndoBuf *utxt = ED_text_undo_push_init(C);
+ ED_text_undo_push_init(C);
if (txt_has_sel(text)) {
txt_order_cursors(text, false);
- txt_indent(text, utxt);
+ txt_indent(text);
}
else {
- txt_add_char(text, utxt, '\t');
+ txt_add_char(text, '\t');
}
text_update_edited(text);
@@ -1049,10 +1051,10 @@ static int text_unindent_exec(bContext *C, wmOperator *UNUSED(op))
text_drawcache_tag_update(CTX_wm_space_text(C), 0);
- TextUndoBuf *utxt = ED_text_undo_push_init(C);
+ ED_text_undo_push_init(C);
txt_order_cursors(text, false);
- txt_unindent(text, utxt);
+ txt_unindent(text);
text_update_edited(text);
@@ -1090,15 +1092,15 @@ static int text_line_break_exec(bContext *C, wmOperator *UNUSED(op))
// double check tabs/spaces before splitting the line
curts = txt_setcurr_tab_spaces(text, space);
- TextUndoBuf *utxt = ED_text_undo_push_init(C);
- txt_split_curline(text, utxt);
+ ED_text_undo_push_init(C);
+ txt_split_curline(text);
for (a = 0; a < curts; a++) {
if (text->flags & TXT_TABSTOSPACES) {
- txt_add_char(text, utxt, ' ');
+ txt_add_char(text, ' ');
}
else {
- txt_add_char(text, utxt, '\t');
+ txt_add_char(text, '\t');
}
}
@@ -1139,10 +1141,10 @@ static int text_comment_exec(bContext *C, wmOperator *UNUSED(op))
if (txt_has_sel(text)) {
text_drawcache_tag_update(CTX_wm_space_text(C), 0);
- TextUndoBuf *utxt = ED_text_undo_push_init(C);
+ ED_text_undo_push_init(C);
txt_order_cursors(text, false);
- txt_comment(text, utxt);
+ txt_comment(text);
text_update_edited(text);
text_update_cursor_moved(C);
@@ -1177,10 +1179,10 @@ static int text_uncomment_exec(bContext *C, wmOperator *UNUSED(op))
if (txt_has_sel(text)) {
text_drawcache_tag_update(CTX_wm_space_text(C), 0);
- TextUndoBuf *utxt = ED_text_undo_push_init(C);
+ ED_text_undo_push_init(C);
txt_order_cursors(text, false);
- txt_uncomment(text, utxt);
+ txt_uncomment(text);
text_update_edited(text);
text_update_cursor_moved(C);
@@ -1446,9 +1448,9 @@ static int move_lines_exec(bContext *C, wmOperator *op)
Text *text = CTX_data_edit_text(C);
const int direction = RNA_enum_get(op->ptr, "direction");
- TextUndoBuf *utxt = ED_text_undo_push_init(C);
+ ED_text_undo_push_init(C);
- txt_move_lines(text, utxt, direction);
+ txt_move_lines(text, direction);
text_update_cursor_moved(C);
WM_event_add_notifier(C, NC_TEXT | NA_EDITED, text);
@@ -2230,13 +2232,13 @@ static int text_delete_exec(bContext *C, wmOperator *op)
}
}
- TextUndoBuf *utxt = ED_text_undo_push_init(C);
+ ED_text_undo_push_init(C);
if (type == DEL_PREV_WORD) {
if (txt_cursor_is_line_start(text)) {
- txt_backspace_char(text, utxt);
+ txt_backspace_char(text);
}
- txt_backspace_word(text, utxt);
+ txt_backspace_word(text);
}
else if (type == DEL_PREV_CHAR) {
@@ -2252,13 +2254,13 @@ static int text_delete_exec(bContext *C, wmOperator *op)
}
}
- txt_backspace_char(text, utxt);
+ txt_backspace_char(text);
}
else if (type == DEL_NEXT_WORD) {
if (txt_cursor_is_line_end(text)) {
- txt_delete_char(text, utxt);
+ txt_delete_char(text);
}
- txt_delete_word(text, utxt);
+ txt_delete_word(text);
}
else if (type == DEL_NEXT_CHAR) {
@@ -2274,7 +2276,7 @@ static int text_delete_exec(bContext *C, wmOperator *op)
}
}
- txt_delete_char(text, utxt);
+ txt_delete_char(text);
}
text_update_line_edited(text->curl);
@@ -2994,7 +2996,7 @@ static void text_cursor_set_exit(bContext *C, wmOperator *op)
char *buffer;
if (txt_has_sel(text)) {
- buffer = txt_sel_to_buf(text);
+ buffer = txt_sel_to_buf(text, NULL);
WM_clipboard_text_set(buffer, 1);
MEM_freeN(buffer);
}
@@ -3190,18 +3192,18 @@ static int text_insert_exec(bContext *C, wmOperator *op)
str = RNA_string_get_alloc(op->ptr, "text", NULL, 0);
- TextUndoBuf *utxt = ED_text_undo_push_init(C);
+ ED_text_undo_push_init(C);
if (st && st->overwrite) {
while (str[i]) {
code = BLI_str_utf8_as_unicode_step(str, &i);
- done |= txt_replace_char(text, utxt, code);
+ done |= txt_replace_char(text, code);
}
}
else {
while (str[i]) {
code = BLI_str_utf8_as_unicode_step(str, &i);
- done |= txt_add_char(text, utxt, code);
+ done |= txt_add_char(text, code);
}
}
@@ -3308,7 +3310,7 @@ static int text_find_and_replace(bContext *C, wmOperator *op, short mode)
/* Replace current */
if (mode != TEXT_FIND && txt_has_sel(text)) {
- tmp = txt_sel_to_buf(text);
+ tmp = txt_sel_to_buf(text, NULL);
if (flags & ST_MATCH_CASE) {
found = STREQ(st->findstr, tmp);
@@ -3319,8 +3321,8 @@ static int text_find_and_replace(bContext *C, wmOperator *op, short mode)
if (found) {
if (mode == TEXT_REPLACE) {
- TextUndoBuf *utxt = ED_text_undo_push_init(C);
- txt_insert_buf(text, utxt, st->replacestr);
+ ED_text_undo_push_init(C);
+ txt_insert_buf(text, st->replacestr);
if (text->curl && text->curl->format) {
MEM_freeN(text->curl->format);
text->curl->format = NULL;
@@ -3406,7 +3408,7 @@ static int text_find_set_selected_exec(bContext *C, wmOperator *op)
Text *text = CTX_data_edit_text(C);
char *tmp;
- tmp = txt_sel_to_buf(text);
+ tmp = txt_sel_to_buf(text, NULL);
BLI_strncpy(st->findstr, tmp, ST_MAX_FIND_STR);
MEM_freeN(tmp);
@@ -3437,7 +3439,7 @@ static int text_replace_set_selected_exec(bContext *C, wmOperator *UNUSED(op))
Text *text = CTX_data_edit_text(C);
char *tmp;
- tmp = txt_sel_to_buf(text);
+ tmp = txt_sel_to_buf(text, NULL);
BLI_strncpy(st->replacestr, tmp, ST_MAX_FIND_STR);
MEM_freeN(tmp);
diff --git a/source/blender/editors/space_text/text_undo.c b/source/blender/editors/space_text/text_undo.c
index 7db97f15a68..6ecb2b731b0 100644
--- a/source/blender/editors/space_text/text_undo.c
+++ b/source/blender/editors/space_text/text_undo.c
@@ -25,6 +25,7 @@
#include "DNA_text_types.h"
+#include "BLI_array_store.h"
#include "BLI_array_utils.h"
#include "BLT_translation.h"
@@ -35,6 +36,7 @@
#include "BKE_report.h"
#include "BKE_text.h"
#include "BKE_undo_system.h"
+#include "BKE_main.h"
#include "WM_api.h"
#include "WM_types.h"
@@ -53,18 +55,32 @@
#include "text_intern.h"
#include "text_format.h"
-/* TODO(campbell): undo_system: move text undo out of text block. */
-
/* -------------------------------------------------------------------- */
/** \name Implements ED Undo System
* \{ */
+#define ARRAY_CHUNK_SIZE 128
+
typedef struct TextUndoStep {
UndoStep step;
UndoRefID_Text text_ref;
- TextUndoBuf data;
+ struct {
+ BArrayState *state;
+ int buf_len;
+ } data;
+
+ struct {
+ int line, line_select;
+ int column, column_select;
+ } cursor;
+
} TextUndoStep;
+static struct {
+ BArrayStore *buffer_store;
+ int users;
+} g_text_buffers = {NULL};
+
static bool text_undosys_poll(bContext *UNUSED(C))
{
/* Only use when operators initialized. */
@@ -77,12 +93,8 @@ static void text_undosys_step_encode_init(struct bContext *C, UndoStep *us_p)
TextUndoStep *us = (TextUndoStep *)us_p;
BLI_assert(BLI_array_is_zeroed(&us->data, 1));
- UNUSED_VARS(C);
+ UNUSED_VARS(C, us);
/* XXX, use to set the undo type only. */
-
- us->data.buf = NULL;
- us->data.len = 0;
- us->data.pos = -1;
}
static bool text_undosys_step_encode(struct bContext *C,
@@ -93,97 +105,71 @@ static bool text_undosys_step_encode(struct bContext *C,
Text *text = CTX_data_edit_text(C);
- /* No undo data was generated. Hint, use global undo here. */
- if ((us->data.pos == -1) || (us->data.buf == NULL)) {
- return false;
- }
+ int buf_len = 0;
- us_p->is_applied = true;
-
- us->text_ref.ptr = text;
+ uchar *buf = (uchar *)txt_to_buf_for_undo(text, &buf_len);
+ if (g_text_buffers.buffer_store == NULL) {
+ g_text_buffers.buffer_store = BLI_array_store_create(1, ARRAY_CHUNK_SIZE);
+ }
+ g_text_buffers.users += 1;
+ const size_t total_size_prev = BLI_array_store_calc_size_compacted_get(
+ g_text_buffers.buffer_store);
- us->step.data_size = us->data.len;
+ us->data.state = BLI_array_store_state_add(g_text_buffers.buffer_store, buf, buf_len, NULL);
+ MEM_freeN(buf);
- return true;
-}
+ us->cursor.line = txt_get_span(text->lines.first, text->curl);
+ us->cursor.column = text->curc;
-static void text_undosys_step_decode_undo_impl(Text *text, TextUndoStep *us)
-{
- BLI_assert(us->step.is_applied == true);
- TextUndoBuf data = us->data;
- while (data.pos > -1) {
- txt_do_undo(text, &data);
+ if (txt_has_sel(text)) {
+ us->cursor.line_select = (text->curl == text->sell) ?
+ us->cursor.line :
+ txt_get_span(text->lines.first, text->sell);
+ us->cursor.column_select = text->selc;
}
- BLI_assert(data.pos == -1);
- us->step.is_applied = false;
-}
-
-static void text_undosys_step_decode_redo_impl(Text *text, TextUndoStep *us)
-{
- BLI_assert(us->step.is_applied == false);
- TextUndoBuf data = us->data;
- data.pos = -1;
- while (data.pos < us->data.pos) {
- txt_do_redo(text, &data);
+ else {
+ us->cursor.line_select = us->cursor.line;
+ us->cursor.column_select = us->cursor.column;
}
- BLI_assert(data.pos == us->data.pos);
- us->step.is_applied = true;
-}
-static void text_undosys_step_decode_undo(Text *text, TextUndoStep *us)
-{
- TextUndoStep *us_iter = us;
- while (us_iter->step.next && (us_iter->step.next->type == us_iter->step.type)) {
- if (us_iter->step.next->is_applied == false) {
- break;
- }
- us_iter = (TextUndoStep *)us_iter->step.next;
- }
- while (us_iter != us) {
- text_undosys_step_decode_undo_impl(text, us_iter);
- us_iter = (TextUndoStep *)us_iter->step.prev;
- }
-}
+ us_p->is_applied = true;
-static void text_undosys_step_decode_redo(Text *text, TextUndoStep *us)
-{
- TextUndoStep *us_iter = us;
- while (us_iter->step.prev && (us_iter->step.prev->type == us_iter->step.type)) {
- if (us_iter->step.prev->is_applied == true) {
- break;
- }
- us_iter = (TextUndoStep *)us_iter->step.prev;
- }
- while (us_iter && (us_iter->step.is_applied == false)) {
- text_undosys_step_decode_redo_impl(text, us_iter);
- if (us_iter == us) {
- break;
- }
- us_iter = (TextUndoStep *)us_iter->step.next;
- }
+ us->text_ref.ptr = text;
+
+ us->step.data_size = BLI_array_store_calc_size_compacted_get(g_text_buffers.buffer_store) -
+ total_size_prev;
+
+ return true;
}
static void text_undosys_step_decode(struct bContext *C,
struct Main *UNUSED(bmain),
UndoStep *us_p,
- int dir)
+ int UNUSED(dir),
+ bool UNUSED(is_final))
{
TextUndoStep *us = (TextUndoStep *)us_p;
Text *text = us->text_ref.ptr;
+ size_t buf_len;
- if (dir < 0) {
- text_undosys_step_decode_undo(text, us);
+ {
+ const uchar *buf = BLI_array_store_state_data_get_alloc(us->data.state, &buf_len);
+ txt_from_buf_for_undo(text, (const char *)buf, buf_len);
+ MEM_freeN((void *)buf);
}
- else {
- text_undosys_step_decode_redo(text, us);
+
+ const bool has_select = ((us->cursor.line != us->cursor.line_select) ||
+ (us->cursor.column != us->cursor.column_select));
+ if (has_select) {
+ txt_move_to(text, us->cursor.line_select, us->cursor.column_select, false);
}
+ txt_move_to(text, us->cursor.line, us->cursor.column, has_select);
SpaceText *st = CTX_wm_space_text(C);
if (st) {
/* Not essential, always show text being undo where possible. */
st->text = text;
}
- text_update_edited(text);
text_update_cursor_moved(C);
text_drawcache_tag_update(st, 1);
WM_event_add_notifier(C, NC_TEXT | NA_EDITED, text);
@@ -192,7 +178,14 @@ static void text_undosys_step_decode(struct bContext *C,
static void text_undosys_step_free(UndoStep *us_p)
{
TextUndoStep *us = (TextUndoStep *)us_p;
- MEM_SAFE_FREE(us->data.buf);
+
+ BLI_array_store_state_remove(g_text_buffers.buffer_store, us->data.state);
+
+ g_text_buffers.users -= 1;
+ if (g_text_buffers.users == 0) {
+ BLI_array_store_destroy(g_text_buffers.buffer_store);
+ g_text_buffers.buffer_store = NULL;
+ }
}
static void text_undosys_foreach_ID_ref(UndoStep *us_p,
@@ -228,12 +221,16 @@ void ED_text_undosys_type(UndoType *ut)
* \{ */
/* Use operator system to finish the undo step. */
-TextUndoBuf *ED_text_undo_push_init(bContext *C)
+UndoStep *ED_text_undo_push_init(bContext *C)
{
UndoStack *ustack = ED_undo_stack_get();
- UndoStep *us_p = BKE_undosys_step_push_init_with_type(ustack, C, NULL, BKE_UNDOSYS_TYPE_TEXT);
- TextUndoStep *us = (TextUndoStep *)us_p;
- return &us->data;
+ Main *bmain = CTX_data_main(C);
+ wmWindowManager *wm = bmain->wm.first;
+ if (wm->op_undo_depth <= 1) {
+ UndoStep *us_p = BKE_undosys_step_push_init_with_type(ustack, C, NULL, BKE_UNDOSYS_TYPE_TEXT);
+ return us_p;
+ }
+ return NULL;
}
/** \} */
diff --git a/source/blender/editors/space_userpref/userpref_ops.c b/source/blender/editors/space_userpref/userpref_ops.c
index 04ef2ed8118..1ec459ccfca 100644
--- a/source/blender/editors/space_userpref/userpref_ops.c
+++ b/source/blender/editors/space_userpref/userpref_ops.c
@@ -26,6 +26,8 @@
#include "DNA_screen_types.h"
#include "BKE_context.h"
+#include "BKE_global.h"
+#include "BKE_main.h"
#include "BKE_report.h"
#include "RNA_types.h"
@@ -45,8 +47,10 @@
static int reset_default_theme_exec(bContext *C, wmOperator *UNUSED(op))
{
+ Main *bmain = CTX_data_main(C);
UI_theme_init_default();
UI_style_init_default();
+ WM_reinit_gizmomap_all(bmain);
WM_event_add_notifier(C, NC_WINDOW, NULL);
U.runtime.is_dirty = true;
return OPERATOR_FINISHED;
diff --git a/source/blender/editors/space_view3d/space_view3d.c b/source/blender/editors/space_view3d/space_view3d.c
index c1891865d6d..57b98ffeda3 100644
--- a/source/blender/editors/space_view3d/space_view3d.c
+++ b/source/blender/editors/space_view3d/space_view3d.c
@@ -662,7 +662,10 @@ static void view3d_widgets(void)
WM_gizmogrouptype_append_and_link(gzmap_type, VIEW3D_GGT_camera);
WM_gizmogrouptype_append_and_link(gzmap_type, VIEW3D_GGT_camera_view);
WM_gizmogrouptype_append_and_link(gzmap_type, VIEW3D_GGT_empty_image);
+ /* TODO(campbell): Not working well enough, disable for now. */
+#if 0
WM_gizmogrouptype_append_and_link(gzmap_type, VIEW3D_GGT_armature_spline);
+#endif
WM_gizmogrouptype_append(VIEW3D_GGT_xform_gizmo);
WM_gizmogrouptype_append(VIEW3D_GGT_xform_cage);
diff --git a/source/blender/editors/space_view3d/view3d_draw.c b/source/blender/editors/space_view3d/view3d_draw.c
index d14a6870a6c..eef36dae86a 100644
--- a/source/blender/editors/space_view3d/view3d_draw.c
+++ b/source/blender/editors/space_view3d/view3d_draw.c
@@ -169,7 +169,13 @@ void ED_view3d_update_viewmat(Depsgraph *depsgraph,
v2[2] = rv3d->persmat[2][1];
len_px = 2.0f / sqrtf(min_ff(len_squared_v3(v1), len_squared_v3(v2)));
- len_sc = (float)MAX2(ar->winx, ar->winy);
+
+ if (rect) {
+ len_sc = (float)max_ii(BLI_rcti_size_x(rect), BLI_rcti_size_y(rect));
+ }
+ else {
+ len_sc = (float)MAX2(ar->winx, ar->winy);
+ }
rv3d->pixsize = len_px / len_sc;
}
@@ -798,7 +804,11 @@ void ED_view3d_draw_depth(Depsgraph *depsgraph, ARegion *ar, View3D *v3d, bool a
GPU_depth_test(true);
GPUViewport *viewport = WM_draw_region_get_viewport(ar, 0);
- DRW_draw_depth_loop(depsgraph, ar, v3d, viewport);
+ /* When Blender is starting, a click event can trigger a depth test while the viewport is not
+ * yet available. */
+ if (viewport != NULL) {
+ DRW_draw_depth_loop(depsgraph, ar, v3d, viewport);
+ }
if (rv3d->rflag & RV3D_CLIPPING) {
ED_view3d_clipping_disable();
diff --git a/source/blender/editors/space_view3d/view3d_edit.c b/source/blender/editors/space_view3d/view3d_edit.c
index b6eb57a3c81..7c4b35507b9 100644
--- a/source/blender/editors/space_view3d/view3d_edit.c
+++ b/source/blender/editors/space_view3d/view3d_edit.c
@@ -4661,6 +4661,7 @@ static int background_image_add_invoke(bContext *C, wmOperator *op, const wmEven
cam->flag |= CAM_SHOW_BG_IMAGE;
WM_event_add_notifier(C, NC_CAMERA | ND_DRAW_RENDER_VIEWPORT, cam);
+ DEG_id_tag_update(&cam->id, ID_RECALC_COPY_ON_WRITE);
return OPERATOR_FINISHED;
}
@@ -4721,6 +4722,8 @@ static int background_image_remove_exec(bContext *C, wmOperator *op)
BKE_camera_background_image_remove(cam, bgpic_rem);
WM_event_add_notifier(C, NC_CAMERA | ND_DRAW_RENDER_VIEWPORT, cam);
+ DEG_id_tag_update(&cam->id, ID_RECALC_COPY_ON_WRITE);
+
return OPERATOR_FINISHED;
}
else {
@@ -4944,7 +4947,7 @@ void ED_view3d_cursor3d_position_rotation(bContext *C,
ray_no,
NULL,
&ob_dummy,
- obmat)) {
+ obmat) != 0) {
if (use_depth) {
copy_v3_v3(cursor_co, ray_co);
}
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 9cbf179ab49..64697a59019 100644
--- a/source/blender/editors/space_view3d/view3d_gizmo_preselect_type.c
+++ b/source/blender/editors/space_view3d/view3d_gizmo_preselect_type.c
@@ -21,7 +21,7 @@
*
* Use for tools to hover over data before activation.
*
- * \note This is a slight mis-use of gizmo's, since clicking performs no action.
+ * \note This is a slight misuse of gizmo's, since clicking performs no action.
*/
#include "MEM_guardedalloc.h"
diff --git a/source/blender/editors/space_view3d/view3d_gizmo_ruler.c b/source/blender/editors/space_view3d/view3d_gizmo_ruler.c
index ebfd66008f7..e781e129540 100644
--- a/source/blender/editors/space_view3d/view3d_gizmo_ruler.c
+++ b/source/blender/editors/space_view3d/view3d_gizmo_ruler.c
@@ -113,6 +113,13 @@ typedef struct RulerInfo {
wmWindow *win;
ScrArea *sa;
ARegion *ar; /* re-assigned every modal update */
+
+ /* Track changes in state. */
+ struct {
+ bool do_snap;
+ bool do_thickness;
+ } drag_state_prev;
+
} RulerInfo;
/* -------------------------------------------------------------------- */
@@ -280,6 +287,7 @@ static void ruler_state_set(bContext *C, RulerInfo *ruler_info, int state)
/* pass */
}
else if (state == RULER_STATE_DRAG) {
+ memset(&ruler_info->drag_state_prev, 0x0, sizeof(ruler_info->drag_state_prev));
ruler_info->snap_context = ED_transform_snap_object_context_create_view3d(
bmain, CTX_data_scene(C), CTX_data_depsgraph(C), 0, ruler_info->ar, CTX_wm_view3d(C));
}
@@ -857,27 +865,43 @@ static int gizmo_ruler_test_select(bContext *UNUSED(C), wmGizmo *gz, const int m
static int gizmo_ruler_modal(bContext *C,
wmGizmo *gz,
const wmEvent *event,
- eWM_GizmoFlagTweak UNUSED(tweak_flag))
+ eWM_GizmoFlagTweak tweak_flag)
{
bool do_draw = false;
int exit_code = OPERATOR_RUNNING_MODAL;
RulerInfo *ruler_info = gz->parent_gzgroup->customdata;
RulerItem *ruler_item = (RulerItem *)gz;
ARegion *ar = CTX_wm_region(C);
+ bool do_cursor_update = false;
ruler_info->ar = ar;
switch (event->type) {
case MOUSEMOVE: {
- if (ruler_info->state == RULER_STATE_DRAG) {
- if (view3d_ruler_item_mousemove(
- ruler_info, ruler_item, event->mval, event->shift != 0, event->ctrl != 0)) {
- do_draw = true;
- }
- }
+ do_cursor_update = true;
break;
}
}
+
+ const bool do_snap = tweak_flag & WM_GIZMO_TWEAK_SNAP;
+ const bool do_thickness = tweak_flag & WM_GIZMO_TWEAK_PRECISE;
+ if ((ruler_info->drag_state_prev.do_snap != do_snap) ||
+ (ruler_info->drag_state_prev.do_thickness != do_thickness)) {
+ do_cursor_update = true;
+ }
+
+ if (do_cursor_update) {
+ if (ruler_info->state == RULER_STATE_DRAG) {
+ if (view3d_ruler_item_mousemove(
+ ruler_info, ruler_item, event->mval, do_thickness, do_snap)) {
+ do_draw = true;
+ }
+ }
+ }
+
+ ruler_info->drag_state_prev.do_snap = do_snap;
+ ruler_info->drag_state_prev.do_thickness = do_thickness;
+
if (do_draw) {
ED_region_tag_redraw(ar);
}
@@ -920,8 +944,7 @@ static int gizmo_ruler_invoke(bContext *C, wmGizmo *gz, const wmEvent *event)
}
/* update the new location */
- view3d_ruler_item_mousemove(
- ruler_info, ruler_item_pick, event->mval, event->shift != 0, event->ctrl != 0);
+ view3d_ruler_item_mousemove(ruler_info, ruler_item_pick, event->mval, false, false);
}
}
else {
diff --git a/source/blender/editors/space_view3d/view3d_iterators.c b/source/blender/editors/space_view3d/view3d_iterators.c
index 6ed0508f09f..2636062ed8b 100644
--- a/source/blender/editors/space_view3d/view3d_iterators.c
+++ b/source/blender/editors/space_view3d/view3d_iterators.c
@@ -38,6 +38,7 @@
#include "BKE_editmesh.h"
#include "BKE_mesh_runtime.h"
#include "BKE_mesh_iterators.h"
+#include "BKE_modifier.h"
#include "DEG_depsgraph.h"
#include "DEG_depsgraph_query.h"
@@ -293,8 +294,15 @@ void mesh_foreachScreenFace(
data.clip_flag = clip_flag;
BM_mesh_elem_table_ensure(vc->em->bm, BM_FACE);
- BKE_mesh_foreach_mapped_face_center(
- me, mesh_foreachScreenFace__mapFunc, &data, MESH_FOREACH_NOP);
+
+ if (modifiers_usesSubsurfFacedots(vc->scene, vc->obedit)) {
+ BKE_mesh_foreach_mapped_subdiv_face_center(
+ me, mesh_foreachScreenFace__mapFunc, &data, MESH_FOREACH_NOP);
+ }
+ else {
+ BKE_mesh_foreach_mapped_face_center(
+ me, mesh_foreachScreenFace__mapFunc, &data, MESH_FOREACH_NOP);
+ }
}
/* ------------------------------------------------------------------------ */
diff --git a/source/blender/editors/space_view3d/view3d_select.c b/source/blender/editors/space_view3d/view3d_select.c
index 3ff97cdd59a..61de61c8e31 100644
--- a/source/blender/editors/space_view3d/view3d_select.c
+++ b/source/blender/editors/space_view3d/view3d_select.c
@@ -1602,31 +1602,63 @@ static const EnumPropertyItem *object_select_menu_enum_itemf(bContext *C,
static int object_select_menu_exec(bContext *C, wmOperator *op)
{
const int name_index = RNA_enum_get(op->ptr, "name");
+ const bool extend = RNA_boolean_get(op->ptr, "extend");
+ const bool deselect = RNA_boolean_get(op->ptr, "deselect");
const bool toggle = RNA_boolean_get(op->ptr, "toggle");
bool changed = false;
const char *name = object_mouse_select_menu_data[name_index].idname;
- if (!toggle) {
- CTX_DATA_BEGIN (C, Base *, base, selectable_bases) {
- if ((base->flag & BASE_SELECTED) != 0) {
- ED_object_base_select(base, BA_DESELECT);
- changed = true;
- }
- }
- CTX_DATA_END;
- }
+ View3D *v3d = CTX_wm_view3d(C);
+ ViewLayer *view_layer = CTX_data_view_layer(C);
+ const Base *oldbasact = BASACT(view_layer);
+ Base *basact = NULL;
CTX_DATA_BEGIN (C, Base *, base, selectable_bases) {
/* This is a bit dodgy, there should only be ONE object with this name,
* but library objects can mess this up. */
if (STREQ(name, base->object->id.name + 2)) {
- ED_object_base_activate(C, base);
- ED_object_base_select(base, BA_SELECT);
- changed = true;
+ basact = base;
+ break;
}
}
CTX_DATA_END;
+ if (basact == NULL) {
+ return OPERATOR_CANCELLED;
+ }
+ UNUSED_VARS_NDEBUG(v3d);
+ BLI_assert(BASE_SELECTABLE(v3d, basact));
+
+ if (extend) {
+ ED_object_base_select(basact, BA_SELECT);
+ changed = true;
+ }
+ else if (deselect) {
+ ED_object_base_select(basact, BA_DESELECT);
+ changed = true;
+ }
+ else if (toggle) {
+ if (basact->flag & BASE_SELECTED) {
+ if (basact == oldbasact) {
+ ED_object_base_select(basact, BA_DESELECT);
+ changed = true;
+ }
+ }
+ else {
+ ED_object_base_select(basact, BA_SELECT);
+ changed = true;
+ }
+ }
+ else {
+ object_deselect_all_except(view_layer, basact);
+ ED_object_base_select(basact, BA_SELECT);
+ changed = true;
+ }
+
+ if ((oldbasact != basact)) {
+ ED_object_base_activate(C, basact);
+ }
+
/* weak but ensures we activate menu again before using the enum */
memset(object_mouse_select_menu_data, 0, sizeof(object_mouse_select_menu_data));
@@ -1664,12 +1696,19 @@ void VIEW3D_OT_select_menu(wmOperatorType *ot)
RNA_def_property_flag(prop, PROP_HIDDEN | PROP_ENUM_NO_TRANSLATE);
ot->prop = prop;
- RNA_def_boolean(
- ot->srna, "toggle", 0, "Toggle", "Toggle selection instead of deselecting everything first");
+ RNA_def_boolean(ot->srna, "extend", 0, "Extend", "");
+ RNA_def_boolean(ot->srna, "deselect", 0, "Deselect", "");
+ RNA_def_boolean(ot->srna, "toggle", 0, "Toggle", "");
}
-static Base *object_mouse_select_menu(
- bContext *C, ViewContext *vc, uint *buffer, int hits, const int mval[2], bool toggle)
+static Base *object_mouse_select_menu(bContext *C,
+ ViewContext *vc,
+ uint *buffer,
+ int hits,
+ const int mval[2],
+ bool extend,
+ bool deselect,
+ bool toggle)
{
short baseCount = 0;
bool ok;
@@ -1739,6 +1778,8 @@ static Base *object_mouse_select_menu(
PointerRNA ptr;
WM_operator_properties_create_ptr(&ptr, ot);
+ RNA_boolean_set(&ptr, "extend", extend);
+ RNA_boolean_set(&ptr, "deselect", deselect);
RNA_boolean_set(&ptr, "toggle", toggle);
WM_operator_name_call_ptr(C, ot, WM_OP_INVOKE_DEFAULT, &ptr);
WM_operator_properties_free(&ptr);
@@ -2122,7 +2163,7 @@ static bool ed_object_select_pick(bContext *C,
/* note; shift+alt goes to group-flush-selecting */
if (enumerate) {
- basact = object_mouse_select_menu(C, &vc, NULL, 0, mval, toggle);
+ basact = object_mouse_select_menu(C, &vc, NULL, 0, mval, extend, deselect, toggle);
}
else {
base = startbase;
@@ -2190,7 +2231,7 @@ static bool ed_object_select_pick(bContext *C,
/* note; shift+alt goes to group-flush-selecting */
if (enumerate) {
- basact = object_mouse_select_menu(C, &vc, buffer, hits, mval, toggle);
+ basact = object_mouse_select_menu(C, &vc, buffer, hits, mval, extend, deselect, toggle);
}
else {
basact = mouse_select_eval_buffer(&vc, buffer, hits, startbase, has_bones, do_nearest);
@@ -2278,11 +2319,17 @@ static bool ed_object_select_pick(bContext *C,
retval = true;
WM_event_add_notifier(C, NC_OBJECT | ND_BONE_SELECT, basact->object);
WM_event_add_notifier(C, NC_OBJECT | ND_BONE_ACTIVE, basact->object);
+ DEG_id_tag_update(&scene->id, ID_RECALC_BASE_FLAGS);
- /* in weightpaint, we use selected bone to select vertexgroup,
- * so no switch to new active object */
+ /* In weight-paint, we use selected bone to select vertex-group,
+ * so don't switch to new active object. */
if (oldbasact && (oldbasact->object->mode & OB_MODE_WEIGHT_PAINT)) {
- /* prevent activating */
+ /* Prevent activating.
+ * Selection causes this to be considered the 'active' pose in weight-paint mode.
+ * Eventually this limitation may be removed.
+ * For now, de-select all other pose objects deforming this mesh. */
+ ED_armature_pose_select_in_wpaint_mode(view_layer, basact);
+
basact = NULL;
}
}
@@ -2353,7 +2400,7 @@ static bool ed_object_select_pick(bContext *C,
}
else {
/* When enabled, this puts other objects out of multi pose-mode. */
- if (is_pose_mode == false) {
+ if (is_pose_mode == false || (basact->object->mode & OB_MODE_POSE) == 0) {
object_deselect_all_except(view_layer, basact);
ED_object_base_select(basact, BA_SELECT);
}
@@ -2507,6 +2554,9 @@ static int view3d_select_exec(bContext *C, wmOperator *op)
/* pass */
}
}
+ if (retval) {
+ WM_event_add_notifier(C, NC_GEOM | ND_SELECT, obedit->data);
+ }
}
else if (obact && obact->mode & OB_MODE_PARTICLE_EDIT) {
retval = PE_mouse_particles(C, location, extend, deselect, toggle);
diff --git a/source/blender/editors/space_view3d/view3d_snap.c b/source/blender/editors/space_view3d/view3d_snap.c
index 51dc14f3dff..0103fd0df53 100644
--- a/source/blender/editors/space_view3d/view3d_snap.c
+++ b/source/blender/editors/space_view3d/view3d_snap.c
@@ -634,14 +634,12 @@ static bool snap_curs_to_sel_ex(bContext *C, float cursor[3])
TransVertStore tvs = {NULL};
TransVert *tv;
float bmat[3][3], vec[3], min[3], max[3], centroid[3];
- int count, a;
+ int count = 0;
- count = 0;
INIT_MINMAX(min, max);
zero_v3(centroid);
if (obedit) {
- int global_transverts_tot = 0;
ViewLayer *view_layer = CTX_data_view_layer(C);
uint objects_len = 0;
Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data(
@@ -662,13 +660,13 @@ static bool snap_curs_to_sel_ex(bContext *C, float cursor[3])
ED_transverts_create_from_obedit(&tvs, obedit, TM_ALL_JOINTS | TM_SKIP_HANDLES);
}
- global_transverts_tot += tvs.transverts_tot;
+ count += tvs.transverts_tot;
if (tvs.transverts_tot != 0) {
Object *obedit_eval = DEG_get_evaluated_object(depsgraph, obedit);
copy_m3_m4(bmat, obedit_eval->obmat);
tv = tvs.transverts;
- for (a = 0; a < tvs.transverts_tot; a++, tv++) {
+ for (int i = 0; i < tvs.transverts_tot; i++, tv++) {
copy_v3_v3(vec, tv->loc);
mul_m3_v3(bmat, vec);
add_v3_v3(vec, obedit_eval->obmat[3]);
@@ -679,14 +677,6 @@ static bool snap_curs_to_sel_ex(bContext *C, float cursor[3])
ED_transverts_free(&tvs);
}
MEM_freeN(objects);
-
- if (scene->toolsettings->transform_pivot_point == V3D_AROUND_CENTER_MEDIAN) {
- mul_v3_fl(centroid, 1.0f / (float)global_transverts_tot);
- copy_v3_v3(cursor, centroid);
- }
- else {
- mid_v3_v3v3(cursor, min, max);
- }
}
else {
Object *obact = CTX_data_active_object(C);
@@ -725,18 +715,18 @@ static bool snap_curs_to_sel_ex(bContext *C, float cursor[3])
}
FOREACH_SELECTED_OBJECT_END;
}
+ }
- if (count == 0) {
- return false;
- }
+ if (count == 0) {
+ return false;
+ }
- if (scene->toolsettings->transform_pivot_point == V3D_AROUND_CENTER_MEDIAN) {
- mul_v3_fl(centroid, 1.0f / (float)count);
- copy_v3_v3(cursor, centroid);
- }
- else {
- mid_v3_v3v3(cursor, min, max);
- }
+ if (scene->toolsettings->transform_pivot_point == V3D_AROUND_CENTER_MEDIAN) {
+ mul_v3_fl(centroid, 1.0f / (float)count);
+ copy_v3_v3(cursor, centroid);
+ }
+ else {
+ mid_v3_v3v3(cursor, min, max);
}
return true;
}
diff --git a/source/blender/editors/space_view3d/view3d_view.c b/source/blender/editors/space_view3d/view3d_view.c
index 5865efa0ffa..c0902cd1cd5 100644
--- a/source/blender/editors/space_view3d/view3d_view.c
+++ b/source/blender/editors/space_view3d/view3d_view.c
@@ -30,6 +30,7 @@
#include "BLI_math.h"
#include "BLI_rect.h"
#include "BLI_utildefines.h"
+#include "BLI_linklist.h"
#include "BKE_action.h"
#include "BKE_camera.h"
@@ -38,6 +39,7 @@
#include "BKE_global.h"
#include "BKE_layer.h"
#include "BKE_main.h"
+#include "BKE_modifier.h"
#include "BKE_report.h"
#include "BKE_scene.h"
@@ -962,8 +964,8 @@ static bool drw_select_filter_object_mode_lock(Object *ob, void *user_data)
* we want to select pose bones (this doesn't switch modes). */
static bool drw_select_filter_object_mode_lock_for_weight_paint(Object *ob, void *user_data)
{
- const Object *ob_pose = user_data;
- return (DEG_get_original_object(ob) == ob_pose);
+ LinkNode *ob_pose_list = user_data;
+ return ob_pose_list && (BLI_linklist_index(ob_pose_list, DEG_get_original_object(ob)) != -1);
}
/**
@@ -1044,10 +1046,22 @@ int view3d_opengl_select(ViewContext *vc,
case VIEW3D_SELECT_FILTER_WPAINT_POSE_MODE_LOCK: {
Object *obact = vc->obact;
BLI_assert(obact && (obact->mode & OB_MODE_WEIGHT_PAINT));
- Object *ob_pose = BKE_object_pose_armature_get(obact);
+ /* While this uses 'alloca' in a loop (which we typically avoid),
+ * the number of items is nearly always 1, maybe 2..3 in rare cases. */
+ LinkNode *ob_pose_list = NULL;
+ VirtualModifierData virtualModifierData;
+ const ModifierData *md = modifiers_getVirtualModifierList(obact, &virtualModifierData);
+ for (; md; md = md->next) {
+ if (md->type == eModifierType_Armature) {
+ ArmatureModifierData *amd = (ArmatureModifierData *)md;
+ if (amd->object && (amd->object->mode & OB_MODE_POSE)) {
+ BLI_linklist_prepend_alloca(&ob_pose_list, amd->object);
+ }
+ }
+ }
object_filter.fn = drw_select_filter_object_mode_lock_for_weight_paint;
- object_filter.user_data = ob_pose;
+ object_filter.user_data = ob_pose_list;
break;
}
case VIEW3D_SELECT_FILTER_NOP:
diff --git a/source/blender/editors/transform/transform.c b/source/blender/editors/transform/transform.c
index 5b3f7d85b43..a316567fc63 100644
--- a/source/blender/editors/transform/transform.c
+++ b/source/blender/editors/transform/transform.c
@@ -617,6 +617,8 @@ static void viewRedrawForce(const bContext *C, TransInfo *t)
}
else if (t->spacetype == SPACE_SEQ) {
WM_event_add_notifier(C, NC_SCENE | ND_SEQUENCER, NULL);
+ /* Keyframes on strips has been moved, so make sure related editos are informed. */
+ WM_event_add_notifier(C, NC_ANIMATION, NULL);
}
else if (t->spacetype == SPACE_IMAGE) {
if (t->options & CTX_MASK) {
@@ -6440,6 +6442,8 @@ static void slide_origdata_create_data(TransDataContainer *tc,
layer_index_dst = 0;
+ /* TODO: We don't need `sod->layer_math_map` when there are no loops linked
+ * to one of the sliding vertices. */
if (CustomData_has_math(&bm->ldata)) {
/* over alloc, only 'math' layers are indexed */
sod->layer_math_map = MEM_mallocN(bm->ldata.totlayer * sizeof(int), __func__);
@@ -6583,7 +6587,7 @@ static void slide_origdata_interp_data_vert(SlideOrigData *sod,
}
}
- if (sod->layer_math_map_num) {
+ if (sod->layer_math_map_num && sv->cd_loop_groups) {
if (do_loop_weight) {
for (j = 0; j < sod->layer_math_map_num; j++) {
BM_vert_loop_groups_data_layer_merge_weights(
@@ -6699,9 +6703,28 @@ static void slide_origdata_free_date(SlideOrigData *sod)
/** \name Transform Edge Slide
* \{ */
+/**
+ * Get the first valid EdgeSlideData.
+ *
+ * Note we cannot trust TRANS_DATA_CONTAINER_FIRST_OK because of multi-object that
+ * may leave items with invalid custom data in the transform data container.
+ */
+static EdgeSlideData *edgeSlideFirstGet(TransInfo *t)
+{
+ FOREACH_TRANS_DATA_CONTAINER (t, tc) {
+ EdgeSlideData *sld = tc->custom.mode.data;
+ if (sld == NULL) {
+ continue;
+ }
+ return sld;
+ }
+ BLI_assert(!"Should never happen, at least one EdgeSlideData should be valid");
+ return NULL;
+}
+
static void calcEdgeSlideCustomPoints(struct TransInfo *t)
{
- EdgeSlideData *sld = TRANS_DATA_CONTAINER_FIRST_OK(t)->custom.mode.data;
+ EdgeSlideData *sld = edgeSlideFirstGet(t);
setCustomPoints(t, &t->mouse, sld->mval_end, sld->mval_start);
@@ -7675,10 +7698,14 @@ void projectEdgeSlideData(TransInfo *t, bool is_final)
{
FOREACH_TRANS_DATA_CONTAINER (t, tc) {
EdgeSlideData *sld = tc->custom.mode.data;
- SlideOrigData *sod = &sld->orig_data;
+ if (sld == NULL) {
+ continue;
+ }
+
+ SlideOrigData *sod = &sld->orig_data;
if (sod->use_origfaces == false) {
- return;
+ continue;
}
slide_origdata_interp_data(tc->obedit,
@@ -7701,7 +7728,7 @@ void freeEdgeSlideVerts(TransInfo *UNUSED(t),
{
EdgeSlideData *sld = custom_data->data;
- if (!sld) {
+ if (sld == NULL) {
return;
}
@@ -7843,9 +7870,9 @@ static eRedrawFlag handleEventEdgeSlide(struct TransInfo *t, const struct wmEven
static void drawEdgeSlide(TransInfo *t)
{
- if ((t->mode == TFM_EDGE_SLIDE) && TRANS_DATA_CONTAINER_FIRST_OK(t)->custom.mode.data) {
+ if ((t->mode == TFM_EDGE_SLIDE) && edgeSlideFirstGet(t)) {
const EdgeSlideParams *slp = t->custom.mode.data;
- EdgeSlideData *sld = TRANS_DATA_CONTAINER_FIRST_OK(t)->custom.mode.data;
+ EdgeSlideData *sld = edgeSlideFirstGet(t);
const bool is_clamp = !(t->flag & T_ALT_TRANSFORM);
/* Even mode */
@@ -7964,7 +7991,7 @@ static void drawEdgeSlide(TransInfo *t)
static void doEdgeSlide(TransInfo *t, float perc)
{
EdgeSlideParams *slp = t->custom.mode.data;
- EdgeSlideData *sld_active = TRANS_DATA_CONTAINER_FIRST_OK(t)->custom.mode.data;
+ EdgeSlideData *sld_active = edgeSlideFirstGet(t);
slp->perc = perc;
@@ -7975,6 +8002,11 @@ static void doEdgeSlide(TransInfo *t, float perc)
const float perc_final = fabsf(perc);
FOREACH_TRANS_DATA_CONTAINER (t, tc) {
EdgeSlideData *sld = tc->custom.mode.data;
+
+ if (sld == NULL) {
+ continue;
+ }
+
TransDataEdgeSlideVert *sv = sld->sv;
for (int i = 0; i < sld->totsv; i++, sv++) {
madd_v3_v3v3fl(sv->v->co, sv->v_co_orig, sv->dir_side[side_index], perc_final);
@@ -7988,6 +8020,11 @@ static void doEdgeSlide(TransInfo *t, float perc)
const int side_index = sld_active->curr_side_unclamp;
FOREACH_TRANS_DATA_CONTAINER (t, tc) {
EdgeSlideData *sld = tc->custom.mode.data;
+
+ if (sld == NULL) {
+ continue;
+ }
+
TransDataEdgeSlideVert *sv = sld->sv;
for (int i = 0; i < sld->totsv; i++, sv++) {
float dir_flip[3];
@@ -8024,6 +8061,11 @@ static void doEdgeSlide(TransInfo *t, float perc)
FOREACH_TRANS_DATA_CONTAINER (t, tc) {
EdgeSlideData *sld = tc->custom.mode.data;
+
+ if (sld == NULL) {
+ continue;
+ }
+
TransDataEdgeSlideVert *sv = sld->sv;
for (int i = 0; i < sld->totsv; i++, sv++) {
if (sv->edge_len > FLT_EPSILON) {
diff --git a/source/blender/editors/transform/transform_constraints.c b/source/blender/editors/transform/transform_constraints.c
index 06851451461..208242d53b3 100644
--- a/source/blender/editors/transform/transform_constraints.c
+++ b/source/blender/editors/transform/transform_constraints.c
@@ -235,8 +235,7 @@ static void axisProjection(const TransInfo *t,
normalize_v3_v3_length(out, axis, -factor);
}
else {
- float v[3], i1[3], i2[3];
- float v2[3], v4[3];
+ float v[3];
float norm_center[3];
float plane[3];
@@ -261,14 +260,17 @@ static void axisProjection(const TransInfo *t,
}
}
else {
- add_v3_v3v3(v2, t_con_center, axis);
- add_v3_v3v3(v4, v, norm);
-
- isect_line_line_v3(t_con_center, v2, v, v4, i1, i2);
-
- sub_v3_v3v3(v, i2, v);
-
- sub_v3_v3v3(out, i1, t_con_center);
+ /* Use ray-ray intersection instead of line-line because this gave
+ * precision issues adding small values to large numbers. */
+ float mul;
+ if (isect_ray_ray_v3(v, norm, t_con_center, axis, &mul, NULL)) {
+ madd_v3_v3v3fl(out, t_con_center, axis, mul);
+ sub_v3_v3(out, t_con_center);
+ }
+ else {
+ /* In practice this should never fail. */
+ BLI_assert(0);
+ }
/* possible some values become nan when
* viewpoint and object are both zero */
@@ -863,9 +865,9 @@ void drawPropCircle(const struct bContext *C, TransInfo *t)
immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR);
immUniformThemeColor(TH_GRID);
- set_inverted_drawing(1);
+ GPU_logic_op_invert_set(true);
imm_drawcircball(t->center_global, t->prop_size, imat, pos);
- set_inverted_drawing(0);
+ GPU_logic_op_invert_set(false);
immUnbindProgram();
diff --git a/source/blender/editors/transform/transform_conversions.c b/source/blender/editors/transform/transform_conversions.c
index 1ed0d5e9221..d13c0f8e8f1 100644
--- a/source/blender/editors/transform/transform_conversions.c
+++ b/source/blender/editors/transform/transform_conversions.c
@@ -1289,7 +1289,6 @@ static void createTransPose(TransInfo *t)
bPose *pose = ob->pose;
bArmature *arm;
- short ik_on = 0;
/* check validity of state */
arm = BKE_armature_from_object(tc->poseobj);
@@ -1315,8 +1314,7 @@ static void createTransPose(TransInfo *t)
/* do we need to add temporal IK chains? */
if ((pose->flag & POSE_AUTO_IK) && t->mode == TFM_TRANSLATION) {
- ik_on = pose_grab_with_ik(bmain, ob);
- if (ik_on) {
+ if (pose_grab_with_ik(bmain, ob)) {
t->flag |= T_AUTOIK;
has_translate_rotate[0] = true;
}
@@ -1359,7 +1357,6 @@ static void createTransPose(TransInfo *t)
Object *ob = tc->poseobj;
TransData *td;
TransDataExtension *tdx;
- short ik_on = 0;
int i;
PoseInitData_Mirror *pid = tc->custom.type.data;
@@ -1407,7 +1404,7 @@ static void createTransPose(TransInfo *t)
}
/* initialize initial auto=ik chainlen's? */
- if (ik_on) {
+ if (t->flag & T_AUTOIK) {
transform_autoik_update(t, 0);
}
}
@@ -2537,6 +2534,7 @@ void flushTransParticles(TransInfo *t)
}
PE_update_object(t->depsgraph, scene, OBACT(view_layer), 1);
+ BKE_particle_batch_cache_dirty_tag(psys, BKE_PARTICLE_BATCH_DIRTY_ALL);
DEG_id_tag_update(&ob->id, ID_RECALC_PSYS_REDO);
}
}
@@ -2935,11 +2933,16 @@ static void VertsToTransData(TransInfo *t,
}
else if (t->mode == TFM_SKIN_RESIZE) {
MVertSkin *vs = CustomData_bmesh_get(&em->bm->vdata, eve->head.data, CD_MVERT_SKIN);
- /* skin node size */
- td->ext = tx;
- copy_v3_v3(tx->isize, vs->radius);
- tx->size = vs->radius;
- td->val = vs->radius;
+ if (vs) {
+ /* skin node size */
+ td->ext = tx;
+ copy_v3_v3(tx->isize, vs->radius);
+ tx->size = vs->radius;
+ td->val = vs->radius;
+ }
+ else {
+ td->flag |= TD_SKIP;
+ }
}
else if (t->mode == TFM_SHRINKFATTEN) {
td->ext = tx;
@@ -3705,50 +3708,48 @@ bool clipUVTransform(TransInfo *t, float vec[2], const bool resize)
for (a = 0, td = tc->data; a < tc->data_len; a++, td++) {
minmax_v2v2_v2(min, max, td->loc);
}
+ }
- if (resize) {
- if (min[0] < 0.0f && t->center_global[0] > 0.0f &&
- t->center_global[0] < t->aspect[0] * 0.5f) {
- vec[0] *= t->center_global[0] / (t->center_global[0] - min[0]);
- }
- else if (max[0] > t->aspect[0] && t->center_global[0] < t->aspect[0]) {
- vec[0] *= (t->center_global[0] - t->aspect[0]) / (t->center_global[0] - max[0]);
- }
- else {
- clipx = 0;
- }
+ if (resize) {
+ if (min[0] < 0.0f && t->center_global[0] > 0.0f && t->center_global[0] < t->aspect[0] * 0.5f) {
+ vec[0] *= t->center_global[0] / (t->center_global[0] - min[0]);
+ }
+ else if (max[0] > t->aspect[0] && t->center_global[0] < t->aspect[0]) {
+ vec[0] *= (t->center_global[0] - t->aspect[0]) / (t->center_global[0] - max[0]);
+ }
+ else {
+ clipx = 0;
+ }
- if (min[1] < 0.0f && t->center_global[1] > 0.0f &&
- t->center_global[1] < t->aspect[1] * 0.5f) {
- vec[1] *= t->center_global[1] / (t->center_global[1] - min[1]);
- }
- else if (max[1] > t->aspect[1] && t->center_global[1] < t->aspect[1]) {
- vec[1] *= (t->center_global[1] - t->aspect[1]) / (t->center_global[1] - max[1]);
- }
- else {
- clipy = 0;
- }
+ if (min[1] < 0.0f && t->center_global[1] > 0.0f && t->center_global[1] < t->aspect[1] * 0.5f) {
+ vec[1] *= t->center_global[1] / (t->center_global[1] - min[1]);
+ }
+ else if (max[1] > t->aspect[1] && t->center_global[1] < t->aspect[1]) {
+ vec[1] *= (t->center_global[1] - t->aspect[1]) / (t->center_global[1] - max[1]);
}
else {
- if (min[0] < 0.0f) {
- vec[0] -= min[0];
- }
- else if (max[0] > t->aspect[0]) {
- vec[0] -= max[0] - t->aspect[0];
- }
- else {
- clipx = 0;
- }
+ clipy = 0;
+ }
+ }
+ else {
+ if (min[0] < 0.0f) {
+ vec[0] -= min[0];
+ }
+ else if (max[0] > t->aspect[0]) {
+ vec[0] -= max[0] - t->aspect[0];
+ }
+ else {
+ clipx = 0;
+ }
- if (min[1] < 0.0f) {
- vec[1] -= min[1];
- }
- else if (max[1] > t->aspect[1]) {
- vec[1] -= max[1] - t->aspect[1];
- }
- else {
- clipy = 0;
- }
+ if (min[1] < 0.0f) {
+ vec[1] -= min[1];
+ }
+ else if (max[1] > t->aspect[1]) {
+ vec[1] -= max[1] - t->aspect[1];
+ }
+ else {
+ clipy = 0;
}
}
@@ -6438,19 +6439,25 @@ static void trans_object_base_deps_flag_prepare(ViewLayer *view_layer)
}
}
-static void set_trans_object_base_deps_flag_cb(ID *id, void *UNUSED(user_data))
+static void set_trans_object_base_deps_flag_cb(ID *id,
+ eDepsObjectComponentType component,
+ void *UNUSED(user_data))
{
/* Here we only handle object IDs. */
if (GS(id->name) != ID_OB) {
return;
}
+ if (!ELEM(component, DEG_OB_COMP_TRANSFORM, DEG_OB_COMP_GEOMETRY)) {
+ return;
+ }
id->tag |= LIB_TAG_DOIT;
}
static void flush_trans_object_base_deps_flag(Depsgraph *depsgraph, Object *object)
{
object->id.tag |= LIB_TAG_DOIT;
- DEG_foreach_dependent_ID(depsgraph, &object->id, set_trans_object_base_deps_flag_cb, NULL);
+ DEG_foreach_dependent_ID_component(
+ depsgraph, &object->id, DEG_OB_COMP_TRANSFORM, set_trans_object_base_deps_flag_cb, NULL);
}
static void trans_object_base_deps_flag_finish(ViewLayer *view_layer)
@@ -7093,6 +7100,10 @@ void special_aftertrans_update(bContext *C, TransInfo *t)
FOREACH_TRANS_DATA_CONTAINER (t, tc) {
EdgeSlideData *sld = tc->custom.mode.data;
+ if (sld == NULL) {
+ continue;
+ }
+
/* Free temporary faces to avoid auto-merging and deleting
* during cleanup - psy-fi. */
freeEdgeSlideTempFaces(sld);
diff --git a/source/blender/editors/transform/transform_gizmo_3d.c b/source/blender/editors/transform/transform_gizmo_3d.c
index 530abe6faff..a883b5b6ba5 100644
--- a/source/blender/editors/transform/transform_gizmo_3d.c
+++ b/source/blender/editors/transform/transform_gizmo_3d.c
@@ -1489,7 +1489,12 @@ static GizmoGroup *gizmogroup_init(wmGizmoGroup *gzgroup)
ggd->gizmos[MAN_AXIS_ROT_T]->flag |= WM_GIZMO_SELECT_BACKGROUND;
/* Prevent axis gizmos overlapping the center point, see: T63744. */
- ggd->gizmos[MAN_AXIS_SCALE_C]->select_bias = ggd->gizmos[MAN_AXIS_TRANS_C]->select_bias = 2.0f;
+ ggd->gizmos[MAN_AXIS_TRANS_C]->select_bias = 2.0f;
+
+ ggd->gizmos[MAN_AXIS_SCALE_C]->select_bias = -2.0f;
+
+ /* Use 1/6 since this is '0.2' if the main scale is 1.2. */
+ RNA_float_set(ggd->gizmos[MAN_AXIS_SCALE_C]->ptr, "arc_inner_factor", 1.0 / 6.0);
return ggd;
}
@@ -1591,6 +1596,9 @@ static void gizmogroup_init_properties_from_twtype(wmGizmoGroup *gzgroup)
WM_gizmo_set_flag(axis, WM_GIZMO_DRAW_VALUE, true);
WM_gizmo_set_scale(axis, 1.2f);
}
+ else if (axis_idx == MAN_AXIS_SCALE_C) {
+ WM_gizmo_set_scale(axis, 1.2f);
+ }
else {
WM_gizmo_set_scale(axis, 0.2f);
}
@@ -1868,7 +1876,7 @@ static void WIDGETGROUP_gizmo_invoke_prepare(const bContext *C,
GizmoGroup *ggd = gzgroup->customdata;
- /* Support gizmo spesific orientation. */
+ /* Support gizmo specific orientation. */
if (gz != ggd->gizmos[MAN_AXIS_ROT_T]) {
Scene *scene = CTX_data_scene(C);
wmGizmoOpElem *gzop = WM_gizmo_operator_get(gz, 0);
diff --git a/source/blender/editors/transform/transform_ops.c b/source/blender/editors/transform/transform_ops.c
index f028f2dc506..c6c2a441d94 100644
--- a/source/blender/editors/transform/transform_ops.c
+++ b/source/blender/editors/transform/transform_ops.c
@@ -33,6 +33,7 @@
#include "BKE_global.h"
#include "BKE_report.h"
#include "BKE_editmesh.h"
+#include "BKE_layer.h"
#include "BKE_scene.h"
#include "RNA_access.h"
@@ -754,16 +755,6 @@ static void TRANSFORM_OT_resize(struct wmOperatorType *ot)
P_OPTIONS | P_GPENCIL_EDIT | P_CENTER);
}
-static bool skin_resize_poll(bContext *C)
-{
- struct Object *obedit = CTX_data_edit_object(C);
- if (obedit && obedit->type == OB_MESH) {
- BMEditMesh *em = BKE_editmesh_from_object(obedit);
- return (em && CustomData_has_layer(&em->bm->vdata, CD_MVERT_SKIN));
- }
- return 0;
-}
-
static void TRANSFORM_OT_skin_resize(struct wmOperatorType *ot)
{
/* identifiers */
@@ -777,7 +768,7 @@ static void TRANSFORM_OT_skin_resize(struct wmOperatorType *ot)
ot->exec = transform_exec;
ot->modal = transform_modal;
ot->cancel = transform_cancel;
- ot->poll = skin_resize_poll;
+ ot->poll = ED_operator_editmesh;
ot->poll_property = transform_poll_property;
RNA_def_float_vector(
diff --git a/source/blender/editors/transform/transform_snap.c b/source/blender/editors/transform/transform_snap.c
index 58a50da9846..d45a0588003 100644
--- a/source/blender/editors/transform/transform_snap.c
+++ b/source/blender/editors/transform/transform_snap.c
@@ -566,13 +566,8 @@ static void initSnappingMode(TransInfo *t)
/* Edit mode */
if (t->tsnap.applySnap != NULL && // A snapping function actually exist
((obedit_type != -1) &&
- ELEM(obedit_type,
- OB_MESH,
- OB_ARMATURE,
- OB_CURVE,
- OB_LATTICE,
- OB_MBALL))) // Temporary limited to edit mode meshes, armature, curves, metaballs
- {
+ /* Temporary limited to edit mode meshes, armature, curves, metaballs. */
+ ELEM(obedit_type, OB_MESH, OB_ARMATURE, OB_CURVE, OB_LATTICE, OB_MBALL))) {
/* Exclude editmesh if using proportional edit */
if ((obedit_type == OB_MESH) && (t->flag & T_PROP_EDIT)) {
t->tsnap.modeSelect = SNAP_NOT_ACTIVE;
diff --git a/source/blender/editors/transform/transform_snap_object.c b/source/blender/editors/transform/transform_snap_object.c
index 03c43c8d16d..6f06f8639bd 100644
--- a/source/blender/editors/transform/transform_snap_object.c
+++ b/source/blender/editors/transform/transform_snap_object.c
@@ -2820,16 +2820,16 @@ static short transform_snap_context_project_view3d_mixed_impl(
return 0;
}
-bool ED_transform_snap_object_project_view3d_ex(SnapObjectContext *sctx,
- const unsigned short snap_to,
- const struct SnapObjectParams *params,
- const float mval[2],
- float *dist_px,
- float r_loc[3],
- float r_no[3],
- int *r_index,
- Object **r_ob,
- float r_obmat[4][4])
+short ED_transform_snap_object_project_view3d_ex(SnapObjectContext *sctx,
+ const unsigned short snap_to,
+ const struct SnapObjectParams *params,
+ const float mval[2],
+ float *dist_px,
+ float r_loc[3],
+ float r_no[3],
+ int *r_index,
+ Object **r_ob,
+ float r_obmat[4][4])
{
return transform_snap_context_project_view3d_mixed_impl(
sctx, snap_to, params, mval, dist_px, r_loc, r_no, r_index, r_ob, r_obmat) != 0;
@@ -2856,7 +2856,7 @@ bool ED_transform_snap_object_project_view3d(SnapObjectContext *sctx,
float r_no[3])
{
return ED_transform_snap_object_project_view3d_ex(
- sctx, snap_to, params, mval, dist_px, r_loc, r_no, NULL, NULL, NULL);
+ sctx, snap_to, params, mval, dist_px, r_loc, r_no, NULL, NULL, NULL) != 0;
}
/**
diff --git a/source/blender/editors/undo/ed_undo.c b/source/blender/editors/undo/ed_undo.c
index 6d5f486ebe9..183e140169d 100644
--- a/source/blender/editors/undo/ed_undo.c
+++ b/source/blender/editors/undo/ed_undo.c
@@ -99,6 +99,10 @@ void ED_undo_push(bContext *C, const char *str)
BKE_undosys_stack_limit_steps_and_memory(wm->undo_stack, 0, memory_limit);
}
+ if (CLOG_CHECK(&LOG, 1)) {
+ BKE_undosys_print(wm->undo_stack);
+ }
+
WM_file_tag_modified();
}
@@ -236,6 +240,10 @@ static int ed_undo_step_impl(
Main *bmain = CTX_data_main(C);
WM_toolsystem_refresh_screen_all(bmain);
+ if (CLOG_CHECK(&LOG, 1)) {
+ BKE_undosys_print(wm->undo_stack);
+ }
+
return OPERATOR_FINISHED;
}
@@ -322,6 +330,39 @@ bool ED_undo_is_memfile_compatible(const bContext *C)
}
/**
+ * When a property of ID changes, return false.
+ *
+ * This is to avoid changes to a property making undo pushes
+ * which are ignored by the undo-system.
+ * For example, changing a brush property isn't stored by sculpt-mode undo steps.
+ * This workaround is needed until the limitation is removed, see: T61948.
+ */
+bool ED_undo_is_legacy_compatible_for_property(struct bContext *C, ID *id)
+{
+ ViewLayer *view_layer = CTX_data_view_layer(C);
+ if (view_layer != NULL) {
+ Object *obact = OBACT(view_layer);
+ if (obact != NULL) {
+ if (obact->mode & OB_MODE_ALL_PAINT) {
+ /* Don't store property changes when painting
+ * (only do undo pushes on brush strokes which each paint operator handles on it's own). */
+ CLOG_INFO(&LOG, 1, "skipping undo for paint-mode");
+ return false;
+ }
+ else if (obact->mode & OB_MODE_EDIT) {
+ if ((id == NULL) || (obact->data == NULL) ||
+ (GS(id->name) != GS(((ID *)obact->data)->name))) {
+ /* No undo push on id type mismatch in edit-mode. */
+ CLOG_INFO(&LOG, 1, "skipping undo for edit-mode");
+ return false;
+ }
+ }
+ }
+ }
+ return true;
+}
+
+/**
* Ideally we wont access the stack directly,
* this is needed for modes which handle undo themselves (bypassing #ED_undo_push).
*
diff --git a/source/blender/editors/undo/memfile_undo.c b/source/blender/editors/undo/memfile_undo.c
index 0f495d64b29..f3e2ee92558 100644
--- a/source/blender/editors/undo/memfile_undo.c
+++ b/source/blender/editors/undo/memfile_undo.c
@@ -83,10 +83,8 @@ static bool memfile_undosys_step_encode(struct bContext *UNUSED(C),
return true;
}
-static void memfile_undosys_step_decode(struct bContext *C,
- struct Main *bmain,
- UndoStep *us_p,
- int UNUSED(dir))
+static void memfile_undosys_step_decode(
+ struct bContext *C, struct Main *bmain, UndoStep *us_p, int UNUSED(dir), bool UNUSED(is_final))
{
ED_editors_exit(bmain, false);
diff --git a/source/blender/editors/util/ed_util.c b/source/blender/editors/util/ed_util.c
index 1ee8ff6966c..c1b6a7b42b2 100644
--- a/source/blender/editors/util/ed_util.c
+++ b/source/blender/editors/util/ed_util.c
@@ -326,15 +326,15 @@ void unpack_menu(bContext *C,
BLI_split_file_part(abs_name, fi, sizeof(fi));
BLI_snprintf(local_name, sizeof(local_name), "//%s/%s", folder, fi);
if (!STREQ(abs_name, local_name)) {
- switch (checkPackedFile(BKE_main_blendfile_path(bmain), local_name, pf)) {
- case PF_NOFILE:
+ switch (BKE_packedfile_compare_to_file(BKE_main_blendfile_path(bmain), local_name, pf)) {
+ case PF_CMP_NOFILE:
BLI_snprintf(line, sizeof(line), TIP_("Create %s"), local_name);
uiItemFullO_ptr(layout, ot, line, ICON_NONE, NULL, WM_OP_EXEC_DEFAULT, 0, &props_ptr);
RNA_enum_set(&props_ptr, "method", PF_WRITE_LOCAL);
RNA_string_set(&props_ptr, "id", id_name);
break;
- case PF_EQUAL:
+ case PF_CMP_EQUAL:
BLI_snprintf(line, sizeof(line), TIP_("Use %s (identical)"), local_name);
// uiItemEnumO_ptr(layout, ot, line, 0, "method", PF_USE_LOCAL);
uiItemFullO_ptr(layout, ot, line, ICON_NONE, NULL, WM_OP_EXEC_DEFAULT, 0, &props_ptr);
@@ -342,7 +342,7 @@ void unpack_menu(bContext *C,
RNA_string_set(&props_ptr, "id", id_name);
break;
- case PF_DIFFERS:
+ case PF_CMP_DIFFERS:
BLI_snprintf(line, sizeof(line), TIP_("Use %s (differs)"), local_name);
// uiItemEnumO_ptr(layout, ot, line, 0, "method", PF_USE_LOCAL);
uiItemFullO_ptr(layout, ot, line, ICON_NONE, NULL, WM_OP_EXEC_DEFAULT, 0, &props_ptr);
@@ -359,22 +359,22 @@ void unpack_menu(bContext *C,
}
}
- switch (checkPackedFile(BKE_main_blendfile_path(bmain), abs_name, pf)) {
- case PF_NOFILE:
+ switch (BKE_packedfile_compare_to_file(BKE_main_blendfile_path(bmain), abs_name, pf)) {
+ case PF_CMP_NOFILE:
BLI_snprintf(line, sizeof(line), TIP_("Create %s"), abs_name);
// uiItemEnumO_ptr(layout, ot, line, 0, "method", PF_WRITE_ORIGINAL);
uiItemFullO_ptr(layout, ot, line, ICON_NONE, NULL, WM_OP_EXEC_DEFAULT, 0, &props_ptr);
RNA_enum_set(&props_ptr, "method", PF_WRITE_ORIGINAL);
RNA_string_set(&props_ptr, "id", id_name);
break;
- case PF_EQUAL:
+ case PF_CMP_EQUAL:
BLI_snprintf(line, sizeof(line), TIP_("Use %s (identical)"), abs_name);
// uiItemEnumO_ptr(layout, ot, line, 0, "method", PF_USE_ORIGINAL);
uiItemFullO_ptr(layout, ot, line, ICON_NONE, NULL, WM_OP_EXEC_DEFAULT, 0, &props_ptr);
RNA_enum_set(&props_ptr, "method", PF_USE_ORIGINAL);
RNA_string_set(&props_ptr, "id", id_name);
break;
- case PF_DIFFERS:
+ case PF_CMP_DIFFERS:
BLI_snprintf(line, sizeof(line), TIP_("Use %s (differs)"), abs_name);
// uiItemEnumO_ptr(layout, ot, line, 0, "method", PF_USE_ORIGINAL);
uiItemFullO_ptr(layout, ot, line, ICON_NONE, NULL, WM_OP_EXEC_DEFAULT, 0, &props_ptr);
diff --git a/source/blender/editors/util/select_buffer_utils.c b/source/blender/editors/util/select_buffer_utils.c
index 130f6819e34..79f0f48830e 100644
--- a/source/blender/editors/util/select_buffer_utils.c
+++ b/source/blender/editors/util/select_buffer_utils.c
@@ -44,7 +44,7 @@
/** \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.
+ * #BLI_bitmap is used for memory efficiency.
*
* \{ */
@@ -215,7 +215,7 @@ uint ED_select_buffer_sample_point(const int center[2])
/**
* Find the selection id closest to \a center.
- * \param dist[in,out]: Use to initalize the distance,
+ * \param dist[in,out]: Use to initialize 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],
@@ -223,7 +223,7 @@ uint ED_select_buffer_find_nearest_to_point(const int center[2],
const uint id_max,
uint *dist)
{
- /* Smart function to sample a rect spiralling outside, nice for selection ID. */
+ /* Smart function to sample a rect spiraling outside, nice for selection ID. */
/* Create region around center (typically the mouse cursor).
* This must be square and have an odd width,
diff --git a/source/blender/editors/uvedit/uvedit_draw.c b/source/blender/editors/uvedit/uvedit_draw.c
index b1d22e12b10..ed8178d1908 100644
--- a/source/blender/editors/uvedit/uvedit_draw.c
+++ b/source/blender/editors/uvedit/uvedit_draw.c
@@ -412,10 +412,10 @@ static void draw_uvs(SpaceImage *sima, Scene *scene, Object *obedit, Depsgraph *
}
}
if (verts || facedots) {
- float pointsize = UI_GetThemeValuef(TH_VERTEX_SIZE);
UI_GetThemeColor4fv(TH_VERTEX_SELECT, col2);
if (verts) {
- float pinned_col[4] = {1.0f, 0.0f, 0.0f, 1.0f}; /* TODO Theme? */
+ const float point_size = UI_GetThemeValuef(TH_VERTEX_SIZE);
+ const float pinned_col[4] = {1.0f, 0.0f, 0.0f, 1.0f}; /* TODO Theme? */
UI_GetThemeColor4fv(TH_VERTEX, col1);
GPU_blend(true);
GPU_program_point_size(true);
@@ -424,7 +424,7 @@ static void draw_uvs(SpaceImage *sima, Scene *scene, Object *obedit, Depsgraph *
GPU_batch_uniform_4f(verts, "vertColor", col1[0], col1[1], col1[2], 1.0f);
GPU_batch_uniform_4fv(verts, "selectColor", transparent);
GPU_batch_uniform_4fv(verts, "pinnedColor", pinned_col);
- GPU_batch_uniform_1f(verts, "pointSize", (pointsize + 1.5f) * M_SQRT2);
+ GPU_batch_uniform_1f(verts, "pointSize", (point_size + 1.5f) * M_SQRT2);
GPU_batch_uniform_1f(verts, "outlineWidth", 0.75f);
GPU_batch_draw(verts);
@@ -441,7 +441,8 @@ static void draw_uvs(SpaceImage *sima, Scene *scene, Object *obedit, Depsgraph *
GPU_program_point_size(false);
}
if (facedots) {
- GPU_point_size(pointsize);
+ const float point_size = UI_GetThemeValuef(TH_FACEDOT_SIZE);
+ GPU_point_size(point_size);
UI_GetThemeColor4fv(TH_WIRE, col1);
GPU_batch_program_set_builtin(facedots, GPU_SHADER_2D_UV_FACEDOTS);
diff --git a/source/blender/editors/uvedit/uvedit_unwrap_ops.c b/source/blender/editors/uvedit/uvedit_unwrap_ops.c
index 14cdb674698..a42a6eba3ff 100644
--- a/source/blender/editors/uvedit/uvedit_unwrap_ops.c
+++ b/source/blender/editors/uvedit/uvedit_unwrap_ops.c
@@ -2282,7 +2282,6 @@ static void uvedit_unwrap_cube_project(BMesh *bm,
* component, but clusters all together around the center of map. */
BM_ITER_MESH (efa, &iter, bm, BM_FACES_OF_MESH) {
- /* tf = CustomData_bmesh_get(&em->bm->pdata, efa->head.data, CD_MTEXPOLY); */ /* UNUSED */
if (use_select && !BM_elem_flag_test(efa, BM_ELEM_SELECT)) {
continue;
}
diff --git a/source/blender/freestyle/intern/python/BPy_FrsMaterial.cpp b/source/blender/freestyle/intern/python/BPy_FrsMaterial.cpp
index b1d44a55fd5..7a5469cd414 100644
--- a/source/blender/freestyle/intern/python/BPy_FrsMaterial.cpp
+++ b/source/blender/freestyle/intern/python/BPy_FrsMaterial.cpp
@@ -428,8 +428,8 @@ static PyObject *FrsMaterial_shininess_get(BPy_FrsMaterial *self, void *UNUSED(c
static int FrsMaterial_shininess_set(BPy_FrsMaterial *self, PyObject *value, void *UNUSED(closure))
{
float scalar;
- if ((scalar = PyFloat_AsDouble(value)) == -1.0f &&
- PyErr_Occurred()) { /* parsed item not a number */
+ if ((scalar = PyFloat_AsDouble(value)) == -1.0f && PyErr_Occurred()) {
+ /* parsed item not a number */
PyErr_SetString(PyExc_TypeError, "value must be a number");
return -1;
}
diff --git a/source/blender/freestyle/intern/python/BPy_StrokeAttribute.cpp b/source/blender/freestyle/intern/python/BPy_StrokeAttribute.cpp
index 7d2716a3e71..505566d3515 100644
--- a/source/blender/freestyle/intern/python/BPy_StrokeAttribute.cpp
+++ b/source/blender/freestyle/intern/python/BPy_StrokeAttribute.cpp
@@ -577,8 +577,8 @@ static int StrokeAttribute_alpha_set(BPy_StrokeAttribute *self,
void *UNUSED(closure))
{
float scalar;
- if ((scalar = PyFloat_AsDouble(value)) == -1.0f &&
- PyErr_Occurred()) { /* parsed item not a number */
+ if ((scalar = PyFloat_AsDouble(value)) == -1.0f && PyErr_Occurred()) {
+ /* parsed item not a number */
PyErr_SetString(PyExc_TypeError, "value must be a number");
return -1;
}
diff --git a/source/blender/freestyle/intern/python/Interface0D/CurvePoint/BPy_StrokeVertex.cpp b/source/blender/freestyle/intern/python/Interface0D/CurvePoint/BPy_StrokeVertex.cpp
index 503dd3bf044..74d8fe4ce60 100644
--- a/source/blender/freestyle/intern/python/Interface0D/CurvePoint/BPy_StrokeVertex.cpp
+++ b/source/blender/freestyle/intern/python/Interface0D/CurvePoint/BPy_StrokeVertex.cpp
@@ -282,8 +282,8 @@ static int StrokeVertex_curvilinear_abscissa_set(BPy_StrokeVertex *self,
void *UNUSED(closure))
{
float scalar;
- if ((scalar = PyFloat_AsDouble(value)) == -1.0f &&
- PyErr_Occurred()) { /* parsed item not a number */
+ if ((scalar = PyFloat_AsDouble(value)) == -1.0f && PyErr_Occurred()) {
+ /* parsed item not a number */
PyErr_SetString(PyExc_TypeError, "value must be a number");
return -1;
}
@@ -328,8 +328,8 @@ static int StrokeVertex_stroke_length_set(BPy_StrokeVertex *self,
void *UNUSED(closure))
{
float scalar;
- if ((scalar = PyFloat_AsDouble(value)) == -1.0f &&
- PyErr_Occurred()) { /* parsed item not a number */
+ if ((scalar = PyFloat_AsDouble(value)) == -1.0f && PyErr_Occurred()) {
+ /* parsed item not a number */
PyErr_SetString(PyExc_TypeError, "value must be a number");
return -1;
}
diff --git a/source/blender/freestyle/intern/python/Interface1D/BPy_Stroke.cpp b/source/blender/freestyle/intern/python/Interface1D/BPy_Stroke.cpp
index 8ba22b0617a..df80f61a7a6 100644
--- a/source/blender/freestyle/intern/python/Interface1D/BPy_Stroke.cpp
+++ b/source/blender/freestyle/intern/python/Interface1D/BPy_Stroke.cpp
@@ -198,8 +198,10 @@ static PyObject *Stroke_insert_vertex(BPy_Stroke *self, PyObject *args, PyObject
&py_sv_it)) {
return NULL;
}
- ((BPy_StrokeVertex *)py_sv)->py_cp.py_if0D.borrowed =
- true; /* make the wrapped StrokeVertex internal */
+
+ /* Make the wrapped StrokeVertex internal. */
+ ((BPy_StrokeVertex *)py_sv)->py_cp.py_if0D.borrowed = true;
+
StrokeVertex *sv = ((BPy_StrokeVertex *)py_sv)->sv;
StrokeInternal::StrokeVertexIterator sv_it(*(((BPy_StrokeVertexIterator *)py_sv_it)->sv_it));
self->s->InsertVertex(sv, sv_it);
@@ -433,8 +435,8 @@ static PyObject *Stroke_length_2d_get(BPy_Stroke *self, void *UNUSED(closure))
static int Stroke_length_2d_set(BPy_Stroke *self, PyObject *value, void *UNUSED(closure))
{
float scalar;
- if ((scalar = PyFloat_AsDouble(value)) == -1.0f &&
- PyErr_Occurred()) { /* parsed item not a number */
+ if ((scalar = PyFloat_AsDouble(value)) == -1.0f && PyErr_Occurred()) {
+ /* parsed item not a number */
PyErr_SetString(PyExc_TypeError, "value must be a number");
return -1;
}
diff --git a/source/blender/freestyle/intern/scene_graph/IndexedFaceSet.cpp b/source/blender/freestyle/intern/scene_graph/IndexedFaceSet.cpp
index 42e96df39ef..fe0fc715e34 100644
--- a/source/blender/freestyle/intern/scene_graph/IndexedFaceSet.cpp
+++ b/source/blender/freestyle/intern/scene_graph/IndexedFaceSet.cpp
@@ -16,7 +16,7 @@
/** \file
* \ingroup freestyle
- * \brief A Set of indexed faces to represent a surfacic object
+ * \brief A Set of indexed faces to represent a surface object
*/
#include "IndexedFaceSet.h"
diff --git a/source/blender/freestyle/intern/scene_graph/IndexedFaceSet.h b/source/blender/freestyle/intern/scene_graph/IndexedFaceSet.h
index 2a38e6ffcc6..5163a0af07e 100644
--- a/source/blender/freestyle/intern/scene_graph/IndexedFaceSet.h
+++ b/source/blender/freestyle/intern/scene_graph/IndexedFaceSet.h
@@ -168,7 +168,7 @@ class IndexedFaceSet : public Rep {
}
/*! Desctructor
- * desallocates all the ressources
+ * desallocates all the resources
*/
virtual ~IndexedFaceSet();
diff --git a/source/blender/freestyle/intern/winged_edge/WXEdge.h b/source/blender/freestyle/intern/winged_edge/WXEdge.h
index e7d5f4ac8f8..20c0bd172ad 100644
--- a/source/blender/freestyle/intern/winged_edge/WXEdge.h
+++ b/source/blender/freestyle/intern/winged_edge/WXEdge.h
@@ -449,7 +449,7 @@ class WXFaceLayer {
unsigned int GetSmoothEdgeIndex() const;
/*! retrieves the edges of the triangle for which the signs are different (a null value is not
- * considered) for the dotp values at each edge extrimity
+ * considered) for the dotp values at each edge extremity
*/
void RetrieveCuspEdgesIndices(vector<int> &oCuspEdges);
diff --git a/source/blender/gpencil_modifiers/intern/MOD_gpencil_util.c b/source/blender/gpencil_modifiers/intern/MOD_gpencil_util.c
index bdab4c083e9..5b5290dc0ff 100644
--- a/source/blender/gpencil_modifiers/intern/MOD_gpencil_util.c
+++ b/source/blender/gpencil_modifiers/intern/MOD_gpencil_util.c
@@ -192,9 +192,8 @@ void gpencil_apply_modifier_material(
BLI_ghash_insert(gh_color, mat->id.name, newmat);
DEG_id_tag_update(&newmat->id, ID_RECALC_COPY_ON_WRITE);
}
- /* Reaasign color index. */
- int idx = BKE_gpencil_object_material_get_index(ob, newmat);
- gps->mat_nr = idx - 1;
+ /* Reassign color index. */
+ gps->mat_nr = BKE_gpencil_object_material_get_index(ob, newmat);
}
else {
/* reuse existing color (but update only first time) */
diff --git a/source/blender/gpu/GPU_state.h b/source/blender/gpu/GPU_state.h
index 7b970786e5e..efea02eb5a4 100644
--- a/source/blender/gpu/GPU_state.h
+++ b/source/blender/gpu/GPU_state.h
@@ -59,4 +59,6 @@ void GPU_viewport_size_get_i(int coords[4]);
void GPU_flush(void);
void GPU_finish(void);
+void GPU_logic_op_invert_set(bool enable);
+
#endif /* __GPU_STATE_H__ */
diff --git a/source/blender/gpu/GPU_vertex_format.h b/source/blender/gpu/GPU_vertex_format.h
index 43eec55bca2..68608a98a79 100644
--- a/source/blender/gpu/GPU_vertex_format.h
+++ b/source/blender/gpu/GPU_vertex_format.h
@@ -31,7 +31,7 @@
#include "BLI_assert.h"
#define GPU_VERT_ATTR_MAX_LEN 16
-#define GPU_VERT_ATTR_MAX_NAMES 4
+#define GPU_VERT_ATTR_MAX_NAMES 5
#define GPU_VERT_ATTR_NAME_AVERAGE_LEN 11
#define GPU_VERT_ATTR_NAMES_BUF_LEN ((GPU_VERT_ATTR_NAME_AVERAGE_LEN + 1) * GPU_VERT_ATTR_MAX_LEN)
diff --git a/source/blender/gpu/intern/gpu_buffers.c b/source/blender/gpu/intern/gpu_buffers.c
index 241b3bd553f..59b0857c177 100644
--- a/source/blender/gpu/intern/gpu_buffers.c
+++ b/source/blender/gpu/intern/gpu_buffers.c
@@ -374,6 +374,7 @@ GPU_PBVH_Buffers *GPU_pbvh_mesh_buffers_build(const int (*face_vert_indices)[3],
/* Fill the only the line buffer. */
GPUIndexBufBuilder elb_lines;
GPU_indexbuf_init(&elb_lines, GPU_PRIM_LINES, tottri * 3, INT_MAX);
+ int vert_idx = 0;
for (i = 0; i < face_indices_len; ++i) {
const MLoopTri *lt = &looptri[face_indices[i]];
@@ -384,9 +385,10 @@ GPU_PBVH_Buffers *GPU_pbvh_mesh_buffers_build(const int (*face_vert_indices)[3],
}
/* TODO skip "non-real" edges. */
- GPU_indexbuf_add_line_verts(&elb_lines, i * 3 + 0, i * 3 + 1);
- GPU_indexbuf_add_line_verts(&elb_lines, i * 3 + 1, i * 3 + 2);
- GPU_indexbuf_add_line_verts(&elb_lines, i * 3 + 2, i * 3 + 0);
+ GPU_indexbuf_add_line_verts(&elb_lines, vert_idx * 3 + 0, vert_idx * 3 + 1);
+ GPU_indexbuf_add_line_verts(&elb_lines, vert_idx * 3 + 1, vert_idx * 3 + 2);
+ GPU_indexbuf_add_line_verts(&elb_lines, vert_idx * 3 + 2, vert_idx * 3 + 0);
+ vert_idx++;
}
buffers->index_lines_buf = GPU_indexbuf_build(&elb_lines);
}
diff --git a/source/blender/gpu/intern/gpu_draw.c b/source/blender/gpu/intern/gpu_draw.c
index d1d5e1d89a2..be3655648f5 100644
--- a/source/blender/gpu/intern/gpu_draw.c
+++ b/source/blender/gpu/intern/gpu_draw.c
@@ -475,6 +475,9 @@ GPUTexture *GPU_texture_from_blender(Image *ima, ImageUser *iuser, int textarget
ima->gpuflag &= ~IMA_GPU_REFRESH;
}
+ /* Tag as in active use for garbage collector. */
+ BKE_image_tag_time(ima);
+
/* Test if we already have a texture. */
GPUTexture **tex = gpu_get_image_gputexture(ima, textarget);
if (*tex) {
diff --git a/source/blender/gpu/intern/gpu_element.c b/source/blender/gpu/intern/gpu_element.c
index 380de4c4e65..50e7df96503 100644
--- a/source/blender/gpu/intern/gpu_element.c
+++ b/source/blender/gpu/intern/gpu_element.c
@@ -204,7 +204,7 @@ static void squeeze_indices_short(GPUIndexBufBuilder *builder,
* converting in place to avoid extra allocation */
GLushort *data = (GLushort *)builder->data;
- if (max_index > 0xFFFF) {
+ if (max_index >= 0xFFFF) {
elem->base_index = min_index;
for (uint i = 0; i < index_len; ++i) {
data[i] = (values[i] == RESTART_INDEX) ? 0xFFFF : (GLushort)(values[i] - min_index);
diff --git a/source/blender/gpu/intern/gpu_extensions.c b/source/blender/gpu/intern/gpu_extensions.c
index 58efe3dc5c4..ba5cf214a42 100644
--- a/source/blender/gpu/intern/gpu_extensions.c
+++ b/source/blender/gpu/intern/gpu_extensions.c
@@ -378,7 +378,11 @@ void gpu_extensions_init(void)
GG.dfdyfactors[1] = 1.0;
}
- if (strstr(renderer, "HD Graphics 4000")) {
+ if (strstr(version, "Build 10.18.10.3379") || strstr(version, "Build 10.18.10.3574") ||
+ strstr(version, "Build 10.18.10.4252") || strstr(version, "Build 10.18.10.4358") ||
+ strstr(version, "Build 10.18.10.4653") || strstr(version, "Build 10.18.10.5069") ||
+ strstr(version, "Build 10.18.14.4264") || strstr(version, "Build 10.18.14.4432") ||
+ strstr(version, "Build 10.18.14.5067")) {
GG.context_local_shaders_workaround = true;
}
}
diff --git a/source/blender/gpu/intern/gpu_framebuffer.c b/source/blender/gpu/intern/gpu_framebuffer.c
index cd63355ff51..7d096058e4c 100644
--- a/source/blender/gpu/intern/gpu_framebuffer.c
+++ b/source/blender/gpu/intern/gpu_framebuffer.c
@@ -837,7 +837,7 @@ static GPUFrameBuffer *gpu_offscreen_fb_get(GPUOffScreen *ofs)
/* List is full, this should never happen or
* it might just slow things down if it happens
- * regulary. In this case we just empty the list
+ * regularly. In this case we just empty the list
* and start over. This is most likely never going
* to happen under normal usage. */
BLI_assert(0);
diff --git a/source/blender/gpu/intern/gpu_matrix.c b/source/blender/gpu/intern/gpu_matrix.c
index 858afdc534e..58ca800a92c 100644
--- a/source/blender/gpu/intern/gpu_matrix.c
+++ b/source/blender/gpu/intern/gpu_matrix.c
@@ -5,7 +5,7 @@
* 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 ipmlied warranty of
+ * 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.
*
diff --git a/source/blender/gpu/intern/gpu_select_sample_query.c b/source/blender/gpu/intern/gpu_select_sample_query.c
index 56f9ef69221..beea25b4171 100644
--- a/source/blender/gpu/intern/gpu_select_sample_query.c
+++ b/source/blender/gpu/intern/gpu_select_sample_query.c
@@ -40,6 +40,8 @@
#include "PIL_time.h"
+#include "BKE_global.h"
+
#include "gpu_select_private.h"
/* Ad hoc number of queries to allocate to skip doing many glGenQueries */
@@ -173,15 +175,8 @@ uint gpu_select_query_end(void)
for (i = 0; i < g_query_state.active_query; i++) {
uint result = 0;
- /* Wait until the result is available. */
- while (result == 0) {
- glGetQueryObjectuiv(g_query_state.queries[i], GL_QUERY_RESULT_AVAILABLE, &result);
- if (result == 0) {
- /* (fclem) Not sure if this is better than calling
- * glGetQueryObjectuiv() indefinitely. */
- PIL_sleep_ms(1);
- }
- }
+ /* We are not using GL_QUERY_RESULT_AVAILABLE and sleep to wait for results,
+ * because it causes lagging on Windows/NVIDIA, see T61474. */
glGetQueryObjectuiv(g_query_state.queries[i], GL_QUERY_RESULT, &result);
if (result > 0) {
if (g_query_state.mode != GPU_SELECT_NEAREST_SECOND_PASS) {
diff --git a/source/blender/gpu/intern/gpu_shader_interface.c b/source/blender/gpu/intern/gpu_shader_interface.c
index e7483e45312..e34c6e23024 100644
--- a/source/blender/gpu/intern/gpu_shader_interface.c
+++ b/source/blender/gpu/intern/gpu_shader_interface.c
@@ -180,10 +180,10 @@ static const GPUShaderInput *add_uniform(GPUShaderInterface *shaderface, const c
input->location = glGetUniformLocation(shaderface->program, name);
- uint name_len = strlen(name);
+ const uint name_len = strlen(name);
+ /* Include NULL terminator. */
shaderface->name_buffer = MEM_reallocN(shaderface->name_buffer,
- shaderface->name_buffer_offset + name_len +
- 1); /* include NULL terminator */
+ shaderface->name_buffer_offset + name_len + 1);
char *name_buffer = shaderface->name_buffer + shaderface->name_buffer_offset;
strcpy(name_buffer, name);
diff --git a/source/blender/gpu/intern/gpu_state.c b/source/blender/gpu/intern/gpu_state.c
index 7a27fea2f0d..caf97a620ab 100644
--- a/source/blender/gpu/intern/gpu_state.c
+++ b/source/blender/gpu/intern/gpu_state.c
@@ -175,3 +175,17 @@ void GPU_finish(void)
{
glFinish();
}
+
+void GPU_logic_op_invert_set(bool enable)
+{
+ if (enable) {
+ glLogicOp(GL_INVERT);
+ glEnable(GL_COLOR_LOGIC_OP);
+ glDisable(GL_DITHER);
+ }
+ else {
+ glLogicOp(GL_COPY);
+ glDisable(GL_COLOR_LOGIC_OP);
+ glEnable(GL_DITHER);
+ }
+}
diff --git a/source/blender/gpu/intern/gpu_texture.c b/source/blender/gpu/intern/gpu_texture.c
index 6a92832d1e5..dab17fcd72a 100644
--- a/source/blender/gpu/intern/gpu_texture.c
+++ b/source/blender/gpu/intern/gpu_texture.c
@@ -505,7 +505,8 @@ static float *GPU_texture_rescale_3d(
static bool gpu_texture_check_capacity(
GPUTexture *tex, GLenum proxy, GLenum internalformat, GLenum data_format, GLenum data_type)
{
- if (GPU_type_matches(GPU_DEVICE_ATI, GPU_OS_WIN, GPU_DRIVER_ANY)) {
+ if (GPU_type_matches(GPU_DEVICE_ATI, GPU_OS_WIN, GPU_DRIVER_ANY) ||
+ GPU_type_matches(GPU_DEVICE_ATI, GPU_OS_UNIX, GPU_DRIVER_OFFICIAL)) {
/* Some AMD drivers have a faulty `GL_PROXY_TEXTURE_..` check.
* (see T55888, T56185, T59351).
* Checking with `GL_PROXY_TEXTURE_..` doesn't prevent `Out Of Memory` issue,
@@ -1459,7 +1460,9 @@ void *GPU_texture_read(GPUTexture *tex, eGPUDataFormat gpu_data_format, int mipl
break;
}
- void *buf = MEM_mallocN(buf_size, "GPU_texture_read");
+ /* AMD Pro driver have a bug that write 8 bytes past buffer size
+ * if the texture is big. (see T66573) */
+ void *buf = MEM_mallocN(buf_size + 8, "GPU_texture_read");
GLenum data_format = gpu_get_gl_dataformat(tex->format, &tex->format_flag);
GLenum data_type = gpu_get_gl_datatype(gpu_data_format);
diff --git a/source/blender/gpu/intern/gpu_vertex_format.c b/source/blender/gpu/intern/gpu_vertex_format.c
index 37e1f9cf9da..e745c525df6 100644
--- a/source/blender/gpu/intern/gpu_vertex_format.c
+++ b/source/blender/gpu/intern/gpu_vertex_format.c
@@ -365,6 +365,11 @@ void GPU_vertformat_from_interface(GPUVertFormat *format, const GPUShaderInterfa
input = next;
next = input->next;
+ /* OpenGL attributes such as `gl_VertexID` have a location of -1. */
+ if (input->location < 0) {
+ continue;
+ }
+
format->name_len++; /* multiname support */
format->attr_len++;
diff --git a/source/blender/gpu/shaders/gpu_shader_gpencil_fill_frag.glsl b/source/blender/gpu/shaders/gpu_shader_gpencil_fill_frag.glsl
index 946fc752e17..56c9a2bd339 100644
--- a/source/blender/gpu/shaders/gpu_shader_gpencil_fill_frag.glsl
+++ b/source/blender/gpu/shaders/gpu_shader_gpencil_fill_frag.glsl
@@ -22,7 +22,7 @@ uniform sampler2D myTexture;
#define SOLID 0
#define GRADIENT 1
#define RADIAL 2
-#define CHESS 3
+#define CHECKER 3
#define TEXTURE 4
in vec2 texCoord_interp;
@@ -104,7 +104,7 @@ void main()
vec2 rot_tex = (matrot_tex * (texCoord_interp - t_center)) + t_center + t_offset;
vec4 tmp_color = texture2D(myTexture, rot_tex * t_scale);
vec4 text_color = vec4(tmp_color[0], tmp_color[1], tmp_color[2], tmp_color[3] * t_opacity);
- vec4 chesscolor;
+ vec4 checker_color;
/* solid fill */
if (fill_type == SOLID) {
@@ -144,32 +144,32 @@ void main()
}
set_color(color, color2, text_color, mix_factor, intensity, t_mix, t_flip, fragColor);
}
- /* chessboard */
- if (fill_type == CHESS) {
+ /* Checkerboard */
+ if (fill_type == CHECKER) {
vec2 pos = rot / g_boxsize;
if ((fract(pos.x) < 0.5 && fract(pos.y) < 0.5) ||
(fract(pos.x) > 0.5 && fract(pos.y) > 0.5)) {
if (t_flip == 0) {
- chesscolor = color;
+ checker_color = color;
}
else {
- chesscolor = color2;
+ checker_color = color2;
}
}
else {
if (t_flip == 0) {
- chesscolor = color2;
+ checker_color = color2;
}
else {
- chesscolor = color;
+ checker_color = color;
}
}
/* mix with texture */
if (t_mix == 1) {
- fragColor = mix(chesscolor, text_color, mix_factor);
+ fragColor = mix(checker_color, text_color, mix_factor);
}
else {
- fragColor = chesscolor;
+ fragColor = checker_color;
}
}
/* texture */
diff --git a/source/blender/gpu/shaders/gpu_shader_material.glsl b/source/blender/gpu/shaders/gpu_shader_material.glsl
index 1750e124c29..6149409774a 100644
--- a/source/blender/gpu/shaders/gpu_shader_material.glsl
+++ b/source/blender/gpu/shaders/gpu_shader_material.glsl
@@ -2224,7 +2224,7 @@ void node_tex_coord_background(vec3 I,
generated = coords;
normal = -coords;
uv = vec3(attr_uv.xy, 0.0);
- object = coords;
+ object = (obmatinv * vec4(coords, 1.0)).xyz;
camera = vec3(co.xy, -co.z);
window = vec3(mtex_2d_mapping(I).xy * camerafac.xy + camerafac.zw, 0.0);
diff --git a/source/blender/imbuf/IMB_imbuf.h b/source/blender/imbuf/IMB_imbuf.h
index 8574f33bce6..fbaa9b06d3b 100644
--- a/source/blender/imbuf/IMB_imbuf.h
+++ b/source/blender/imbuf/IMB_imbuf.h
@@ -67,6 +67,7 @@
* \attention defined in ???
*/
struct ImBuf;
+struct rcti;
/**
*
@@ -222,6 +223,8 @@ void IMB_blend_color_byte(unsigned char dst[4],
IMB_BlendMode mode);
void IMB_blend_color_float(float dst[4], float src1[4], float src2[4], IMB_BlendMode mode);
+void IMB_rect_crop(struct ImBuf *ibuf, const struct rcti *crop);
+
void IMB_rectclip(struct ImBuf *dbuf,
struct ImBuf *sbuf,
int *destx,
diff --git a/source/blender/imbuf/intern/allocimbuf.c b/source/blender/imbuf/intern/allocimbuf.c
index d518406124f..7d2f51af65e 100644
--- a/source/blender/imbuf/intern/allocimbuf.c
+++ b/source/blender/imbuf/intern/allocimbuf.c
@@ -493,11 +493,12 @@ bool IMB_initImBuf(
ibuf->y = y;
ibuf->planes = planes;
ibuf->ftype = IMB_FTYPE_PNG;
- ibuf->foptions.quality =
- 15; /* the 15 means, set compression to low ratio but not time consuming */
- ibuf->channels = 4; /* float option, is set to other values when buffers get assigned */
- ibuf->ppm[0] = ibuf->ppm[1] = IMB_DPI_DEFAULT /
- 0.0254f; /* IMB_DPI_DEFAULT -> pixels-per-meter */
+ /* The '15' means, set compression to low ratio but not time consuming. */
+ ibuf->foptions.quality = 15;
+ /* float option, is set to other values when buffers get assigned. */
+ ibuf->channels = 4;
+ /* IMB_DPI_DEFAULT -> pixels-per-meter. */
+ ibuf->ppm[0] = ibuf->ppm[1] = IMB_DPI_DEFAULT / 0.0254f;
if (flags & IB_rect) {
if (imb_addrectImBuf(ibuf) == false) {
diff --git a/source/blender/imbuf/intern/oiio/openimageio_api.cpp b/source/blender/imbuf/intern/oiio/openimageio_api.cpp
index 7a47d0f7787..d2147f833c3 100644
--- a/source/blender/imbuf/intern/oiio/openimageio_api.cpp
+++ b/source/blender/imbuf/intern/oiio/openimageio_api.cpp
@@ -197,6 +197,7 @@ struct ImBuf *imb_load_photoshop(const char *filename, int flags, char colorspac
bool is_float, is_alpha;
int basesize;
char file_colorspace[IM_MAX_SPACE];
+ const bool is_colorspace_manually_set = (colorspace[0] != '\0');
/* load image from file through OIIO */
if (imb_is_a_photoshop(filename) == 0) {
@@ -221,17 +222,19 @@ struct ImBuf *imb_load_photoshop(const char *filename, int flags, char colorspac
return NULL;
}
- string ics = spec.get_string_attribute("oiio:ColorSpace");
- BLI_strncpy(file_colorspace, ics.c_str(), IM_MAX_SPACE);
+ if (!is_colorspace_manually_set) {
+ string ics = spec.get_string_attribute("oiio:ColorSpace");
+ BLI_strncpy(file_colorspace, ics.c_str(), IM_MAX_SPACE);
- /* only use colorspaces exis */
- if (colormanage_colorspace_get_named(file_colorspace)) {
- strcpy(colorspace, file_colorspace);
- }
- else {
- std::cerr << __func__ << ": The embed colorspace (\"" << file_colorspace
- << "\") not supported in existent OCIO configuration file. Fallback "
- << "to system default colorspace (\"" << colorspace << "\")." << std::endl;
+ /* only use colorspaces exis */
+ if (colormanage_colorspace_get_named(file_colorspace)) {
+ strcpy(colorspace, file_colorspace);
+ }
+ else {
+ std::cerr << __func__ << ": The embed colorspace (\"" << file_colorspace
+ << "\") not supported in existent OCIO configuration file. Fallback "
+ << "to system default colorspace (\"" << colorspace << "\")." << std::endl;
+ }
}
width = spec.width;
diff --git a/source/blender/imbuf/intern/openexr/openexr_api.cpp b/source/blender/imbuf/intern/openexr/openexr_api.cpp
index 7b3de4167a2..c9883d5df86 100644
--- a/source/blender/imbuf/intern/openexr/openexr_api.cpp
+++ b/source/blender/imbuf/intern/openexr/openexr_api.cpp
@@ -969,8 +969,8 @@ int IMB_exr_begin_read(void *handle, const char *filename, int *width, int *heig
ExrHandle *data = (ExrHandle *)handle;
ExrChannel *echan;
- if (BLI_exists(filename) &&
- BLI_file_size(filename) > 32) { /* 32 is arbitrary, but zero length files crashes exr */
+ /* 32 is arbitrary, but zero length files crashes exr. */
+ if (BLI_exists(filename) && BLI_file_size(filename) > 32) {
/* avoid crash/abort when we don't have permission to write here */
try {
data->ifile_stream = new IFileStream(filename);
@@ -1762,32 +1762,11 @@ static bool imb_exr_is_multilayer_file(MultiPartInputFile &file)
const ChannelList &channels = file.header(0).channels();
std::set<std::string> layerNames;
- /* will not include empty layer names */
+ /* This will not include empty layer names, so files with just R/G/B/A
+ * channels without a layer name will be single layer. */
channels.layers(layerNames);
- if (layerNames.size() > 1) {
- return true;
- }
-
- if (layerNames.size()) {
- /* if layerNames is not empty, it means at least one layer is non-empty,
- * but it also could be layers without names in the file and such case
- * shall be considered a multilayer exr
- *
- * that's what we do here: test whether they're empty layer names together
- * with non-empty ones in the file
- */
- for (ChannelList::ConstIterator i = channels.begin(); i != channels.end(); i++) {
- std::string layerName = i.name();
- size_t pos = layerName.rfind('.');
-
- if (pos == std::string::npos) {
- return true;
- }
- }
- }
-
- return false;
+ return (layerNames.size() > 0);
}
static void imb_exr_type_by_channels(ChannelList &channels,
@@ -1957,8 +1936,8 @@ struct ImBuf *imb_load_openexr(const unsigned char *mem,
}
}
- if (is_multi &&
- ((flags & IB_thumbnail) == 0)) { /* only enters with IB_multilayer flag set */
+ /* Only enters with IB_multilayer flag set. */
+ if (is_multi && ((flags & IB_thumbnail) == 0)) {
/* constructs channels for reading, allocates memory in channels */
ExrHandle *handle = imb_exr_begin_read_mem(*membuf, *file, width, height);
if (handle) {
diff --git a/source/blender/imbuf/intern/rectop.c b/source/blender/imbuf/intern/rectop.c
index 25390b73737..76918c216f7 100644
--- a/source/blender/imbuf/intern/rectop.c
+++ b/source/blender/imbuf/intern/rectop.c
@@ -25,6 +25,7 @@
#include <stdlib.h>
#include "BLI_utildefines.h"
+#include "BLI_rect.h"
#include "BLI_math_base.h"
#include "BLI_math_color.h"
#include "BLI_math_color_blend.h"
@@ -35,6 +36,8 @@
#include "IMB_colormanagement.h"
+#include "MEM_guardedalloc.h"
+
void IMB_blend_color_byte(unsigned char dst[4],
unsigned char src1[4],
unsigned char src2[4],
@@ -207,6 +210,72 @@ void IMB_blend_color_float(float dst[4], float src1[4], float src2[4], IMB_Blend
}
}
+/** Crop */
+
+static void rect_crop_4bytes(void **buf_p, const int size_src[2], const rcti *crop)
+{
+ if (*buf_p == NULL) {
+ return;
+ }
+ const int size_dst[2] = {
+ BLI_rcti_size_x(crop) + 1,
+ BLI_rcti_size_y(crop) + 1,
+ };
+ uint *src = *buf_p;
+ uint *dst = src + crop->ymin * size_src[0] + crop->xmin;
+ for (int y = 0; y < size_dst[1]; y++, src += size_dst[0], dst += size_src[0]) {
+ memmove(src, dst, sizeof(uint) * size_dst[0]);
+ }
+ *buf_p = MEM_reallocN(*buf_p, sizeof(uint) * size_dst[0] * size_dst[1]);
+}
+
+static void rect_crop_16bytes(void **buf_p, const int size_src[2], const rcti *crop)
+{
+ if (*buf_p == NULL) {
+ return;
+ }
+ const int size_dst[2] = {
+ BLI_rcti_size_x(crop) + 1,
+ BLI_rcti_size_y(crop) + 1,
+ };
+ uint(*src)[4] = *buf_p;
+ uint(*dst)[4] = src + crop->ymin * size_src[0] + crop->xmin;
+ for (int y = 0; y < size_dst[1]; y++, src += size_dst[0], dst += size_src[0]) {
+ memmove(src, dst, sizeof(uint[4]) * size_dst[0]);
+ }
+ *buf_p = (void *)MEM_reallocN(*buf_p, sizeof(uint[4]) * size_dst[0] * size_dst[1]);
+}
+
+/**
+ * In-place image crop.
+ */
+void IMB_rect_crop(ImBuf *ibuf, const rcti *crop)
+{
+ const int size_src[2] = {
+ ibuf->x,
+ ibuf->y,
+ };
+ const int size_dst[2] = {
+ BLI_rcti_size_x(crop) + 1,
+ BLI_rcti_size_y(crop) + 1,
+ };
+ BLI_assert(size_dst[0] > 0 && size_dst[0] > 0);
+ BLI_assert(crop->xmin >= 0 && crop->ymin >= 0);
+ BLI_assert(crop->xmax < ibuf->x && crop->ymax < ibuf->y);
+
+ if ((size_dst[0] == ibuf->x) && (size_dst[1] == ibuf->y)) {
+ return;
+ }
+
+ rect_crop_4bytes((void **)&ibuf->rect, size_src, crop);
+ rect_crop_4bytes((void **)&ibuf->zbuf, size_src, crop);
+ rect_crop_4bytes((void **)&ibuf->zbuf_float, size_src, crop);
+ rect_crop_16bytes((void **)&ibuf->rect_float, size_src, crop);
+
+ ibuf->x = size_dst[0];
+ ibuf->y = size_dst[1];
+}
+
/* clipping */
void IMB_rectclip(ImBuf *dbuf,
diff --git a/source/blender/makesdna/DNA_action_types.h b/source/blender/makesdna/DNA_action_types.h
index c8a76791cef..a4cd31a1357 100644
--- a/source/blender/makesdna/DNA_action_types.h
+++ b/source/blender/makesdna/DNA_action_types.h
@@ -772,6 +772,7 @@ typedef enum eDopeSheet_FilterFlag {
/* DopeSheet filter-flags - Overflow (filterflag2) */
typedef enum eDopeSheet_FilterFlag2 {
ADS_FILTER_NOCACHEFILES = (1 << 1),
+ ADS_FILTER_NOMOVIECLIPS = (1 << 2),
} eDopeSheet_FilterFlag2;
/* DopeSheet general flags */
diff --git a/source/blender/makesdna/DNA_customdata_types.h b/source/blender/makesdna/DNA_customdata_types.h
index c38222a3eb3..75a417150c8 100644
--- a/source/blender/makesdna/DNA_customdata_types.h
+++ b/source/blender/makesdna/DNA_customdata_types.h
@@ -30,6 +30,8 @@
extern "C" {
#endif
+#include "DNA_defs.h"
+
/** descriptor and storage for a custom data layer */
typedef struct CustomDataLayer {
/** Type of data in layer. */
@@ -107,9 +109,11 @@ typedef enum CustomDataType {
CD_PROP_FLT = 10,
CD_PROP_INT = 11,
CD_PROP_STR = 12,
- CD_ORIGSPACE = 13, /* for modifier stack face location mapping */
- CD_ORCO = 14, /* undeformed vertex coordinates, normalized to 0..1 range */
- /* CD_MTEXPOLY = 15, */ /* deprecated */
+ CD_ORIGSPACE = 13, /* for modifier stack face location mapping */
+ CD_ORCO = 14, /* undeformed vertex coordinates, normalized to 0..1 range */
+#ifdef DNA_DEPRECATED
+ CD_MTEXPOLY = 15, /* deprecated */
+#endif
CD_MLOOPUV = 16,
CD_MLOOPCOL = 17,
CD_TANGENT = 18,
diff --git a/source/blender/makesdna/DNA_material_types.h b/source/blender/makesdna/DNA_material_types.h
index d65a4896758..42308f54d7a 100644
--- a/source/blender/makesdna/DNA_material_types.h
+++ b/source/blender/makesdna/DNA_material_types.h
@@ -338,7 +338,7 @@ enum {
enum {
GP_STYLE_FILL_STYLE_SOLID = 0,
GP_STYLE_FILL_STYLE_GRADIENT,
- GP_STYLE_FILL_STYLE_CHESSBOARD,
+ GP_STYLE_FILL_STYLE_CHECKER,
GP_STYLE_FILL_STYLE_TEXTURE,
};
diff --git a/source/blender/makesdna/DNA_meshdata_types.h b/source/blender/makesdna/DNA_meshdata_types.h
index 04d060b065d..88eef05f8be 100644
--- a/source/blender/makesdna/DNA_meshdata_types.h
+++ b/source/blender/makesdna/DNA_meshdata_types.h
@@ -394,6 +394,7 @@ enum {
/* SELECT = (1 << 0), */
ME_VERT_TMP_TAG = (1 << 2),
ME_HIDE = (1 << 4),
+ ME_VERT_FACEDOT = (1 << 5),
/* ME_VERT_MERGED = (1 << 6), */
ME_VERT_PBVH_UPDATE = (1 << 7),
};
diff --git a/source/blender/makesdna/DNA_packedFile_types.h b/source/blender/makesdna/DNA_packedFile_types.h
index a8afa667158..8196e3098eb 100644
--- a/source/blender/makesdna/DNA_packedFile_types.h
+++ b/source/blender/makesdna/DNA_packedFile_types.h
@@ -30,20 +30,4 @@ typedef struct PackedFile {
void *data;
} PackedFile;
-enum ePF_FileStatus {
- PF_EQUAL = 0,
- PF_DIFFERS = 1,
- PF_NOFILE = 2,
-
- PF_WRITE_ORIGINAL = 3,
- PF_WRITE_LOCAL = 4,
- PF_USE_LOCAL = 5,
- PF_USE_ORIGINAL = 6,
- PF_KEEP = 7,
- PF_REMOVE = 8,
- PF_NOOP = 9,
-
- PF_ASK = 10,
-};
-
#endif /* PACKEDFILE_TYPES_H */
diff --git a/source/blender/makesdna/DNA_text_types.h b/source/blender/makesdna/DNA_text_types.h
index 8dfaf95a10a..4eec2c1fde8 100644
--- a/source/blender/makesdna/DNA_text_types.h
+++ b/source/blender/makesdna/DNA_text_types.h
@@ -55,8 +55,6 @@ typedef struct Text {
} Text;
#define TXT_TABSIZE 4
-#define TXT_INIT_UNDO 1024
-#define TXT_MAX_UNDO (TXT_INIT_UNDO * TXT_INIT_UNDO)
/* text flags */
enum {
diff --git a/source/blender/makesdna/DNA_view3d_types.h b/source/blender/makesdna/DNA_view3d_types.h
index 31ffb3efebd..e7a4f9cbd4e 100644
--- a/source/blender/makesdna/DNA_view3d_types.h
+++ b/source/blender/makesdna/DNA_view3d_types.h
@@ -433,6 +433,10 @@ enum {
V3D_SHADING_TEXTURE_COLOR = 3,
V3D_SHADING_OBJECT_COLOR = 4,
V3D_SHADING_VERTEX_COLOR = 5,
+
+ /* Is used to display the object using the error color. For example when in
+ * solid texture paint mode without any textures configured */
+ V3D_SHADING_ERROR_COLOR = 999,
};
/** #View3DShading.background_type */
diff --git a/source/blender/makesrna/intern/rna_action.c b/source/blender/makesrna/intern/rna_action.c
index ba5355a8d95..4ad2aa55c75 100644
--- a/source/blender/makesrna/intern/rna_action.c
+++ b/source/blender/makesrna/intern/rna_action.c
@@ -571,6 +571,13 @@ static void rna_def_dopesheet(BlenderRNA *brna)
RNA_def_property_ui_icon(prop, ICON_OUTLINER_OB_GREASEPENCIL, 0);
RNA_def_property_update(prop, NC_ANIMATION | ND_ANIMCHAN | NA_EDITED, NULL);
+ prop = RNA_def_property(srna, "show_movieclips", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_negative_sdna(prop, NULL, "filterflag2", ADS_FILTER_NOMOVIECLIPS);
+ RNA_def_property_ui_text(
+ prop, "Display Movie Clips", "Include visualization of movie clip related animation data");
+ RNA_def_property_ui_icon(prop, ICON_TRACKER, 0);
+ RNA_def_property_update(prop, NC_ANIMATION | ND_ANIMCHAN | NA_EDITED, NULL);
+
/* GPencil Mode Settings */
prop = RNA_def_property(srna, "show_gpencil_3d_only", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "filterflag", ADS_FILTER_GP_3DONLY);
diff --git a/source/blender/makesrna/intern/rna_armature.c b/source/blender/makesrna/intern/rna_armature.c
index 99b2c423b44..6737363bae4 100644
--- a/source/blender/makesrna/intern/rna_armature.c
+++ b/source/blender/makesrna/intern/rna_armature.c
@@ -268,18 +268,6 @@ static IDProperty *rna_EditBone_idprops(PointerRNA *ptr, bool create)
return ebone->prop;
}
-/* Update the layers_used variable after bones are moved between layer
- * NOTE: Used to be done in drawing code in 2.7, but that won't work with
- * Copy-on-Write, as drawing uses evaluated copies.
- */
-static void rna_Armature_layer_used_refresh(bArmature *arm, ListBase *bones)
-{
- for (Bone *bone = bones->first; bone; bone = bone->next) {
- arm->layer_used |= bone->layer;
- rna_Armature_layer_used_refresh(arm, &bone->childbase);
- }
-}
-
static void rna_bone_layer_set(int *layer, const bool *values)
{
int i, tot = 0;
@@ -312,8 +300,7 @@ static void rna_Bone_layer_set(PointerRNA *ptr, const bool *values)
rna_bone_layer_set(&bone->layer, values);
- arm->layer_used = 0;
- rna_Armature_layer_used_refresh(arm, &arm->bonebase);
+ BKE_armature_refresh_layer_used(arm);
}
static void rna_Armature_layer_set(PointerRNA *ptr, const bool *values)
@@ -1355,7 +1342,7 @@ static void rna_def_armature(BlenderRNA *brna)
prop = RNA_def_property(srna, "display_type", PROP_ENUM, PROP_NONE);
RNA_def_property_enum_sdna(prop, NULL, "drawtype");
RNA_def_property_enum_items(prop, prop_drawtype_items);
- RNA_def_property_ui_text(prop, "Display Type Type", "");
+ RNA_def_property_ui_text(prop, "Display Type", "");
RNA_def_property_update(prop, 0, "rna_Armature_redraw_data");
RNA_def_property_flag(prop, PROP_LIB_EXCEPTION);
diff --git a/source/blender/makesrna/intern/rna_brush.c b/source/blender/makesrna/intern/rna_brush.c
index fabbc7ca18b..fb60f092d16 100644
--- a/source/blender/makesrna/intern/rna_brush.c
+++ b/source/blender/makesrna/intern/rna_brush.c
@@ -1426,7 +1426,7 @@ static void rna_def_gpencil_options(BlenderRNA *brna)
RNA_def_property_clear_flag(prop, PROP_ANIMATABLE);
prop = RNA_def_property(srna, "use_occlude_eraser", PROP_BOOLEAN, PROP_NONE);
- RNA_def_property_boolean_negative_sdna(prop, NULL, "flag", GP_BRUSH_OCCLUDE_ERASER);
+ RNA_def_property_boolean_sdna(prop, NULL, "flag", GP_BRUSH_OCCLUDE_ERASER);
RNA_def_property_ui_text(prop, "Occlude Eraser", "Erase only strokes visible and not occluded");
RNA_def_property_clear_flag(prop, PROP_ANIMATABLE);
}
@@ -1807,9 +1807,8 @@ static void rna_def_brush(BlenderRNA *brna)
RNA_def_property_ui_text(prop,
"Topology Rake",
"Automatically align edges to the brush direction to "
- "to generate cleaner topology and define sharp features "
- "dynamic topology. Best used on low-poly meshes as it has "
- "a performance impact");
+ "generate cleaner topology and define sharp features. "
+ "Best used on low-poly meshes as it has a performance impact");
RNA_def_property_update(prop, 0, "rna_Brush_update");
prop = RNA_def_property(srna, "stencil_pos", PROP_FLOAT, PROP_XYZ);
diff --git a/source/blender/makesrna/intern/rna_cloth.c b/source/blender/makesrna/intern/rna_cloth.c
index c93833ef493..548ed656d7b 100644
--- a/source/blender/makesrna/intern/rna_cloth.c
+++ b/source/blender/makesrna/intern/rna_cloth.c
@@ -824,7 +824,7 @@ static void rna_def_cloth_collision_settings(BlenderRNA *brna)
prop = RNA_def_property(srna, "use_collision", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "flags", CLOTH_COLLSETTINGS_FLAG_ENABLED);
RNA_def_property_ui_text(prop, "Enable Collision", "Enable collisions with other objects");
- RNA_def_property_update(prop, 0, "rna_cloth_update");
+ RNA_def_property_update(prop, 0, "rna_cloth_dependency_update");
prop = RNA_def_property(srna, "distance_min", PROP_FLOAT, PROP_DISTANCE);
RNA_def_property_float_sdna(prop, NULL, "epsilon");
diff --git a/source/blender/makesrna/intern/rna_gpencil.c b/source/blender/makesrna/intern/rna_gpencil.c
index b59e97f1991..2671246b589 100644
--- a/source/blender/makesrna/intern/rna_gpencil.c
+++ b/source/blender/makesrna/intern/rna_gpencil.c
@@ -685,6 +685,24 @@ static void rna_GPencil_stroke_remove(bGPDframe *frame,
WM_main_add_notifier(NC_GPENCIL | NA_EDITED, NULL);
}
+static void rna_GPencil_stroke_close(ID *id,
+ bGPDframe *frame,
+ ReportList *reports,
+ PointerRNA *stroke_ptr)
+{
+ bGPdata *gpd = (bGPdata *)id;
+ bGPDstroke *stroke = stroke_ptr->data;
+ if (BLI_findindex(&frame->strokes, stroke) == -1) {
+ BKE_report(reports, RPT_ERROR, "Stroke not found in grease pencil frame");
+ return;
+ }
+
+ BKE_gpencil_close_stroke(stroke);
+
+ DEG_id_tag_update(&gpd->id, ID_RECALC_TRANSFORM | ID_RECALC_GEOMETRY | ID_RECALC_COPY_ON_WRITE);
+ WM_main_add_notifier(NC_GPENCIL | ND_DATA | NA_EDITED, NULL);
+}
+
static void rna_GPencil_stroke_select_set(PointerRNA *ptr, const bool value)
{
bGPDstroke *gps = ptr->data;
@@ -710,7 +728,10 @@ static void rna_GPencil_stroke_select_set(PointerRNA *ptr, const bool value)
}
}
-static bGPDframe *rna_GPencil_frame_new(bGPDlayer *layer, ReportList *reports, int frame_number)
+static bGPDframe *rna_GPencil_frame_new(bGPDlayer *layer,
+ ReportList *reports,
+ int frame_number,
+ bool active)
{
bGPDframe *frame;
@@ -720,7 +741,9 @@ static bGPDframe *rna_GPencil_frame_new(bGPDlayer *layer, ReportList *reports, i
}
frame = BKE_gpencil_frame_addnew(layer, frame_number);
-
+ if (active) {
+ layer->actframe = BKE_gpencil_layer_getframe(layer, frame_number, GP_GETFRAME_USE_PREV);
+ }
WM_main_add_notifier(NC_GPENCIL | NA_EDITED, NULL);
return frame;
@@ -1154,6 +1177,13 @@ static void rna_def_gpencil_strokes_api(BlenderRNA *brna, PropertyRNA *cprop)
parm = RNA_def_pointer(func, "stroke", "GPencilStroke", "Stroke", "The stroke to remove");
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, "close", "rna_GPencil_stroke_close");
+ RNA_def_function_ui_description(func, "Close a grease pencil stroke adding geometry");
+ RNA_def_function_flag(func, FUNC_USE_REPORTS | FUNC_USE_SELF_ID);
+ parm = RNA_def_pointer(func, "stroke", "GPencilStroke", "Stroke", "The stroke to close");
+ RNA_def_parameter_flags(parm, PROP_NEVER_NULL, PARM_REQUIRED | PARM_RNAPTR);
+ RNA_def_parameter_clear_flags(parm, PROP_THICK_WRAP, 0);
}
static void rna_def_gpencil_frame(BlenderRNA *brna)
@@ -1222,6 +1252,7 @@ static void rna_def_gpencil_frames_api(BlenderRNA *brna, PropertyRNA *cprop)
MINAFRAME,
MAXFRAME);
RNA_def_parameter_flags(parm, 0, PARM_REQUIRED);
+ RNA_def_boolean(func, "active", 0, "Active", "");
parm = RNA_def_pointer(func, "frame", "GPencilFrame", "", "The newly created frame");
RNA_def_function_return(func, parm);
diff --git a/source/blender/makesrna/intern/rna_gpencil_modifier.c b/source/blender/makesrna/intern/rna_gpencil_modifier.c
index 2dabaeebb09..2b89225d34d 100644
--- a/source/blender/makesrna/intern/rna_gpencil_modifier.c
+++ b/source/blender/makesrna/intern/rna_gpencil_modifier.c
@@ -663,7 +663,7 @@ static void rna_def_modifier_gpencilsimplify(BlenderRNA *brna)
/* Mode */
prop = RNA_def_property(srna, "mode", PROP_ENUM, PROP_NONE);
RNA_def_property_enum_items(prop, prop_gpencil_simplify_mode_items);
- RNA_def_property_ui_text(prop, "Mode", "How simplify the stroke");
+ RNA_def_property_ui_text(prop, "Mode", "How to simplify the stroke");
RNA_def_property_update(prop, 0, "rna_GpencilModifier_update");
prop = RNA_def_property(srna, "step", PROP_INT, PROP_NONE);
diff --git a/source/blender/makesrna/intern/rna_image_api.c b/source/blender/makesrna/intern/rna_image_api.c
index 933dae70457..d167c650683 100644
--- a/source/blender/makesrna/intern/rna_image_api.c
+++ b/source/blender/makesrna/intern/rna_image_api.c
@@ -36,13 +36,14 @@
#include "RNA_define.h"
#include "RNA_enum_types.h"
+#include "BKE_packedFile.h"
+
#include "rna_internal.h" /* own include */
#ifdef RNA_RUNTIME
# include <errno.h>
# include "BKE_image.h"
-# include "BKE_packedFile.h"
# include "BKE_main.h"
# include "IMB_imbuf.h"
@@ -55,7 +56,7 @@
static void rna_ImagePackedFile_save(ImagePackedFile *imapf, Main *bmain, ReportList *reports)
{
- if (writePackedFile(
+ if (BKE_packedfile_write_to_file(
reports, BKE_main_blendfile_path(bmain), imapf->filepath, imapf->packedfile, 0) !=
RET_OK) {
BKE_reportf(reports, RPT_ERROR, "Could not save packed file to disk as '%s'", imapf->filepath);
@@ -179,7 +180,7 @@ static void rna_Image_unpack(Image *image, Main *bmain, ReportList *reports, int
}
else {
/* reports its own error on failure */
- unpackImage(bmain, reports, image, method);
+ BKE_packedfile_unpack_image(bmain, reports, image, method);
}
}
diff --git a/source/blender/makesrna/intern/rna_layer.c b/source/blender/makesrna/intern/rna_layer.c
index 003faed5b81..1c0ced060d5 100644
--- a/source/blender/makesrna/intern/rna_layer.c
+++ b/source/blender/makesrna/intern/rna_layer.c
@@ -178,6 +178,13 @@ static void rna_ViewLayer_update_tagged(ID *id_ptr, ViewLayer *view_layer, Main
Scene *scene = (Scene *)id_ptr;
Depsgraph *depsgraph = BKE_scene_get_depsgraph(scene, view_layer, true);
+ /* NOTE: This is similar to CTX_data_depsgraph(). Ideally such access would be de-duplicated
+ * across all possible cases, but for now this is safest and easiest way to go.
+ *
+ * The reason for this is that it's possible to have Python operator which asks view layer to
+ * be updated. After re-do of such operator view layer's dependency graph will not be marked
+ * as active. */
+ DEG_make_active(depsgraph);
BKE_scene_graph_update_tagged(depsgraph, bmain);
# ifdef WITH_PYTHON
@@ -271,15 +278,18 @@ static void rna_LayerCollection_exclude_update(Main *bmain, Scene *UNUSED(scene)
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);
+ /* Set/Unset it recursively to match the behavior of excluding via the menu or shortcuts. */
+ const bool exclude = (lc->flag & LAYER_COLLECTION_EXCLUDE) != 0;
+ rna_LayerCollection_exclude_update_recursive(&lc->layer_collections, exclude);
BKE_layer_collection_sync(scene, view_layer);
DEG_id_tag_update(&scene->id, ID_RECALC_BASE_FLAGS);
DEG_relations_tag_update(bmain);
WM_main_add_notifier(NC_SCENE | ND_LAYER_CONTENT, NULL);
+ if (exclude) {
+ ED_object_base_active_refresh(bmain, scene, view_layer);
+ }
}
static void rna_LayerCollection_update(Main *UNUSED(bmain), Scene *UNUSED(scene), PointerRNA *ptr)
@@ -342,7 +352,6 @@ static void rna_def_layer_collection(BlenderRNA *brna)
RNA_def_property_boolean_funcs(prop, NULL, "rna_LayerCollection_exclude_set");
RNA_def_property_clear_flag(prop, PROP_ANIMATABLE);
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");
diff --git a/source/blender/makesrna/intern/rna_main_api.c b/source/blender/makesrna/intern/rna_main_api.c
index d7acbb40bb8..fec991e16da 100644
--- a/source/blender/makesrna/intern/rna_main_api.c
+++ b/source/blender/makesrna/intern/rna_main_api.c
@@ -555,6 +555,8 @@ static Text *rna_Main_texts_load(Main *bmain,
errno = 0;
txt = BKE_text_load_ex(bmain, filepath, BKE_main_blendfile_path(bmain), is_internal);
+ /* Texts have no user by default... Only the 'real' user flag. */
+ id_us_min(&txt->id);
if (!txt) {
BKE_reportf(reports,
diff --git a/source/blender/makesrna/intern/rna_material.c b/source/blender/makesrna/intern/rna_material.c
index 3ff2e884d92..28989d1dd5f 100644
--- a/source/blender/makesrna/intern/rna_material.c
+++ b/source/blender/makesrna/intern/rna_material.c
@@ -433,11 +433,11 @@ static void rna_def_material_greasepencil(BlenderRNA *brna)
static EnumPropertyItem fill_style_items[] = {
{GP_STYLE_FILL_STYLE_SOLID, "SOLID", 0, "Solid", "Fill area with solid color"},
{GP_STYLE_FILL_STYLE_GRADIENT, "GRADIENT", 0, "Gradient", "Fill area with gradient color"},
- {GP_STYLE_FILL_STYLE_CHESSBOARD,
- "CHESSBOARD",
+ {GP_STYLE_FILL_STYLE_CHECKER,
+ "CHECKER",
0,
"Checker Board",
- "Fill area with chessboard pattern"},
+ "Fill area with checkerboard pattern"},
{GP_STYLE_FILL_STYLE_TEXTURE, "TEXTURE", 0, "Texture", "Fill area with image texture"},
{0, NULL, 0, NULL, NULL},
};
diff --git a/source/blender/makesrna/intern/rna_mesh.c b/source/blender/makesrna/intern/rna_mesh.c
index c51097fc8c3..03173bcb3da 100644
--- a/source/blender/makesrna/intern/rna_mesh.c
+++ b/source/blender/makesrna/intern/rna_mesh.c
@@ -3095,8 +3095,7 @@ static void rna_def_mesh(BlenderRNA *brna)
prop = RNA_def_property(srna, "use_paint_mask_vertex", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "editflag", ME_EDIT_PAINT_VERT_SEL);
- RNA_def_property_ui_text(
- prop, "Vertex Selection", "Vertex selection masking for painting (weight paint only)");
+ RNA_def_property_ui_text(prop, "Vertex Selection", "Vertex selection masking for painting");
RNA_def_property_ui_icon(prop, ICON_VERTEXSEL, 0);
RNA_def_property_update(prop, NC_SPACE | ND_SPACE_VIEW3D, "rna_Mesh_update_vertmask");
diff --git a/source/blender/makesrna/intern/rna_nodetree.c b/source/blender/makesrna/intern/rna_nodetree.c
index 5f156864479..eec280a5f3e 100644
--- a/source/blender/makesrna/intern/rna_nodetree.c
+++ b/source/blender/makesrna/intern/rna_nodetree.c
@@ -1711,6 +1711,12 @@ static void rna_Node_update(Main *bmain, Scene *UNUSED(scene), PointerRNA *ptr)
ED_node_tag_update_nodetree(bmain, ntree, node);
}
+static void rna_Node_update_relations(Main *bmain, Scene *scene, PointerRNA *ptr)
+{
+ rna_Node_update(bmain, scene, ptr);
+ DEG_relations_tag_update(bmain);
+}
+
static void rna_Node_socket_value_update(ID *id, bNode *node, bContext *C)
{
ED_node_tag_update_nodetree(CTX_data_main(C), (bNodeTree *)id, node);
@@ -4458,7 +4464,7 @@ static void def_sh_tex_coord(StructRNA *srna)
RNA_def_property_flag(prop, PROP_EDITABLE | PROP_ID_REFCOUNT);
RNA_def_property_ui_text(
prop, "Object", "Use coordinates from this object (for object texture coordinates output)");
- RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_update");
+ RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_update_relations");
prop = RNA_def_property(srna, "from_instancer", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "custom1", 1);
diff --git a/source/blender/makesrna/intern/rna_object.c b/source/blender/makesrna/intern/rna_object.c
index 578097733f2..d3b532dd11d 100644
--- a/source/blender/makesrna/intern/rna_object.c
+++ b/source/blender/makesrna/intern/rna_object.c
@@ -444,7 +444,7 @@ static void rna_Object_data_set(PointerRNA *ptr, PointerRNA value, struct Report
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 "
+ "Can only assign evaluated data to evaluated object, or original data to "
"original object");
return;
}
@@ -638,7 +638,7 @@ static void rna_Object_dup_collection_set(PointerRNA *ptr,
id_us_plus(&ob->instance_collection->id);
}
else {
- BKE_report(NULL, RPT_ERROR, "Only empty objects support group instances");
+ BKE_report(NULL, RPT_ERROR, "Only empty objects support collection instances");
}
}
else {
@@ -2358,7 +2358,7 @@ static void rna_def_object(BlenderRNA *brna)
RNA_def_property_flag(prop, PROP_EDITABLE | PROP_NEVER_UNLINK);
RNA_def_property_override_flag(prop, PROPOVERRIDE_OVERRIDABLE_LIBRARY);
RNA_def_property_ui_text(prop, "Data", "Object data");
- RNA_def_property_update(prop, 0, "rna_Object_internal_update_data");
+ RNA_def_property_update(prop, 0, "rna_Object_internal_update_data_dependency");
prop = RNA_def_property(srna, "type", PROP_ENUM, PROP_NONE);
RNA_def_property_enum_sdna(prop, NULL, "type");
diff --git a/source/blender/makesrna/intern/rna_object_api.c b/source/blender/makesrna/intern/rna_object_api.c
index a891e11a944..c91481931a2 100644
--- a/source/blender/makesrna/intern/rna_object_api.c
+++ b/source/blender/makesrna/intern/rna_object_api.c
@@ -98,11 +98,13 @@ static void rna_Object_select_set(
Base *base = BKE_view_layer_base_find(view_layer, ob);
if (!base) {
- BKE_reportf(reports,
- RPT_ERROR,
- "Object '%s' not in View Layer '%s'!",
- ob->id.name + 2,
- view_layer->name);
+ if (select) {
+ BKE_reportf(reports,
+ RPT_ERROR,
+ "Object '%s' can't be selected because it is not in View Layer '%s'!",
+ ob->id.name + 2,
+ view_layer->name);
+ }
return;
}
@@ -113,10 +115,7 @@ static void rna_Object_select_set(
WM_main_add_notifier(NC_SCENE | ND_OB_SELECT, scene);
}
-static bool rna_Object_select_get(Object *ob,
- bContext *C,
- ReportList *reports,
- ViewLayer *view_layer)
+static bool rna_Object_select_get(Object *ob, bContext *C, ViewLayer *view_layer)
{
if (view_layer == NULL) {
view_layer = CTX_data_view_layer(C);
@@ -124,11 +123,6 @@ static bool rna_Object_select_get(Object *ob,
Base *base = BKE_view_layer_base_find(view_layer, ob);
if (!base) {
- BKE_reportf(reports,
- RPT_ERROR,
- "Object '%s' not in View Layer '%s'!",
- ob->id.name + 2,
- view_layer->name);
return false;
}
@@ -144,11 +138,13 @@ static void rna_Object_hide_set(
Base *base = BKE_view_layer_base_find(view_layer, ob);
if (!base) {
- BKE_reportf(reports,
- RPT_ERROR,
- "Object '%s' not in View Layer '%s'!",
- ob->id.name + 2,
- view_layer->name);
+ if (hide) {
+ BKE_reportf(reports,
+ RPT_ERROR,
+ "Object '%s' can't be hidden because it is not in View Layer '%s'!",
+ ob->id.name + 2,
+ view_layer->name);
+ }
return;
}
@@ -165,10 +161,7 @@ static void rna_Object_hide_set(
WM_event_add_notifier(C, NC_SCENE | ND_OB_SELECT, scene);
}
-static bool rna_Object_hide_get(Object *ob,
- bContext *C,
- ReportList *reports,
- ViewLayer *view_layer)
+static bool rna_Object_hide_get(Object *ob, bContext *C, ViewLayer *view_layer)
{
if (view_layer == NULL) {
view_layer = CTX_data_view_layer(C);
@@ -176,19 +169,13 @@ static bool rna_Object_hide_get(Object *ob,
Base *base = BKE_view_layer_base_find(view_layer, ob);
if (!base) {
- BKE_reportf(reports,
- RPT_ERROR,
- "Object '%s' not in View Layer '%s'!",
- ob->id.name + 2,
- view_layer->name);
return false;
}
return ((base->flag & BASE_HIDDEN) != 0);
}
-static bool rna_Object_visible_get(
- Object *ob, bContext *C, ReportList *reports, ViewLayer *view_layer, View3D *v3d)
+static bool rna_Object_visible_get(Object *ob, bContext *C, ViewLayer *view_layer, View3D *v3d)
{
if (view_layer == NULL) {
view_layer = CTX_data_view_layer(C);
@@ -199,21 +186,13 @@ static bool rna_Object_visible_get(
Base *base = BKE_view_layer_base_find(view_layer, ob);
if (!base) {
- BKE_reportf(reports,
- RPT_ERROR,
- "Object '%s' not in View Layer '%s'!",
- ob->id.name + 2,
- view_layer->name);
return false;
}
return BASE_VISIBLE(v3d, base);
}
-static bool rna_Object_holdout_get(Object *ob,
- bContext *C,
- ReportList *reports,
- ViewLayer *view_layer)
+static bool rna_Object_holdout_get(Object *ob, bContext *C, ViewLayer *view_layer)
{
if (view_layer == NULL) {
view_layer = CTX_data_view_layer(C);
@@ -221,21 +200,13 @@ static bool rna_Object_holdout_get(Object *ob,
Base *base = BKE_view_layer_base_find(view_layer, ob);
if (!base) {
- BKE_reportf(reports,
- RPT_ERROR,
- "Object '%s' not in View Layer '%s'!",
- ob->id.name + 2,
- view_layer->name);
return false;
}
return ((base->flag & BASE_HOLDOUT) != 0);
}
-static bool rna_Object_indirect_only_get(Object *ob,
- bContext *C,
- ReportList *reports,
- ViewLayer *view_layer)
+static bool rna_Object_indirect_only_get(Object *ob, bContext *C, ViewLayer *view_layer)
{
if (view_layer == NULL) {
view_layer = CTX_data_view_layer(C);
@@ -243,11 +214,6 @@ static bool rna_Object_indirect_only_get(Object *ob,
Base *base = BKE_view_layer_base_find(view_layer, ob);
if (!base) {
- BKE_reportf(reports,
- RPT_ERROR,
- "Object '%s' not in View Layer '%s'!",
- ob->id.name + 2,
- view_layer->name);
return false;
}
@@ -741,7 +707,7 @@ void RNA_api_object(StructRNA *srna)
func = RNA_def_function(srna, "select_get", "rna_Object_select_get");
RNA_def_function_ui_description(
func, "Test if the object is selected. The selection state is per view layer");
- RNA_def_function_flag(func, FUNC_USE_CONTEXT | FUNC_USE_REPORTS);
+ RNA_def_function_flag(func, FUNC_USE_CONTEXT);
parm = RNA_def_pointer(
func, "view_layer", "ViewLayer", "", "Use this instead of the active view layer");
parm = RNA_def_boolean(func, "result", 0, "", "Object selected");
@@ -760,10 +726,10 @@ void RNA_api_object(StructRNA *srna)
RNA_def_function_ui_description(
func,
"Test if the object is hidden for viewport editing. This hiding state is per view layer");
- RNA_def_function_flag(func, FUNC_USE_CONTEXT | FUNC_USE_REPORTS);
+ RNA_def_function_flag(func, FUNC_USE_CONTEXT);
parm = RNA_def_pointer(
func, "view_layer", "ViewLayer", "", "Use this instead of the active view layer");
- parm = RNA_def_boolean(func, "result", 0, "", "Object hideed");
+ parm = RNA_def_boolean(func, "result", 0, "", "Object hidden");
RNA_def_function_return(func, parm);
func = RNA_def_function(srna, "hide_set", "rna_Object_hide_set");
@@ -779,7 +745,7 @@ void RNA_api_object(StructRNA *srna)
RNA_def_function_ui_description(func,
"Test if the object is visible in the 3D viewport, taking into "
"account all visibility settings");
- RNA_def_function_flag(func, FUNC_USE_CONTEXT | FUNC_USE_REPORTS);
+ RNA_def_function_flag(func, FUNC_USE_CONTEXT);
parm = RNA_def_pointer(
func, "view_layer", "ViewLayer", "", "Use this instead of the active view layer");
parm = RNA_def_pointer(
@@ -789,7 +755,7 @@ void RNA_api_object(StructRNA *srna)
func = RNA_def_function(srna, "holdout_get", "rna_Object_holdout_get");
RNA_def_function_ui_description(func, "Test if object is masked in the view layer");
- RNA_def_function_flag(func, FUNC_USE_CONTEXT | FUNC_USE_REPORTS);
+ RNA_def_function_flag(func, FUNC_USE_CONTEXT);
parm = RNA_def_pointer(
func, "view_layer", "ViewLayer", "", "Use this instead of the active view layer");
parm = RNA_def_boolean(func, "result", 0, "", "Object holdout");
@@ -799,7 +765,7 @@ void RNA_api_object(StructRNA *srna)
RNA_def_function_ui_description(func,
"Test if object is set to contribute only indirectly (through "
"shadows and reflections) in the view layer");
- RNA_def_function_flag(func, FUNC_USE_CONTEXT | FUNC_USE_REPORTS);
+ RNA_def_function_flag(func, FUNC_USE_CONTEXT);
parm = RNA_def_pointer(
func, "view_layer", "ViewLayer", "", "Use this instead of the active view layer");
parm = RNA_def_boolean(func, "result", 0, "", "Object indirect only");
diff --git a/source/blender/makesrna/intern/rna_object_force.c b/source/blender/makesrna/intern/rna_object_force.c
index c97491a92c6..ab6cffe615d 100644
--- a/source/blender/makesrna/intern/rna_object_force.c
+++ b/source/blender/makesrna/intern/rna_object_force.c
@@ -523,6 +523,8 @@ static void rna_FieldSettings_shape_update(Main *bmain, Scene *scene, PointerRNA
if (!particle_id_check(ptr)) {
Object *ob = (Object *)ptr->id.data;
ED_object_check_force_modifiers(bmain, scene, ob);
+
+ DEG_id_tag_update(&ob->id, ID_RECALC_TRANSFORM);
WM_main_add_notifier(NC_OBJECT | ND_DRAW, ob);
WM_main_add_notifier(NC_OBJECT | ND_MODIFIER, ob);
}
diff --git a/source/blender/makesrna/intern/rna_packedfile.c b/source/blender/makesrna/intern/rna_packedfile.c
index 0b1b48b1bd3..dda1c637f39 100644
--- a/source/blender/makesrna/intern/rna_packedfile.c
+++ b/source/blender/makesrna/intern/rna_packedfile.c
@@ -27,6 +27,8 @@
#include "RNA_define.h"
#include "RNA_enum_types.h"
+#include "BKE_packedFile.h"
+
#include "rna_internal.h"
const EnumPropertyItem rna_enum_unpack_method_items[] = {
diff --git a/source/blender/makesrna/intern/rna_particle.c b/source/blender/makesrna/intern/rna_particle.c
index c1822b35f28..a96e85473a2 100644
--- a/source/blender/makesrna/intern/rna_particle.c
+++ b/source/blender/makesrna/intern/rna_particle.c
@@ -2822,11 +2822,7 @@ static void rna_def_particle_settings(BlenderRNA *brna)
prop = RNA_def_property(srna, "count", PROP_INT, PROP_UNSIGNED);
RNA_def_property_int_sdna(prop, NULL, "totpart");
RNA_def_property_clear_flag(prop, PROP_ANIMATABLE);
- /* This limit is for those freaks who have the machine power to handle it. */
- /* 10M particles take around 2.2 Gb of memory / disk space in saved file and */
- /* each cached frame takes around 0.5 Gb of memory / disk space depending on cache mode. */
- RNA_def_property_range(prop, 0, 10000000);
- RNA_def_property_ui_range(prop, 0, 100000, 1, -1);
+ RNA_def_property_ui_range(prop, 0, 1000000, 1, -1);
RNA_def_property_ui_text(prop, "Number", "Total number of particles");
RNA_def_property_update(prop, 0, "rna_Particle_reset");
diff --git a/source/blender/makesrna/intern/rna_rna.c b/source/blender/makesrna/intern/rna_rna.c
index 8c3e1a724cf..9834520f952 100644
--- a/source/blender/makesrna/intern/rna_rna.c
+++ b/source/blender/makesrna/intern/rna_rna.c
@@ -1870,8 +1870,8 @@ int rna_property_override_diff_default(Main *bmain,
# undef RNA_PATH_FREE
}
- equals = equals && !(iter_a.valid || iter_b.valid) &&
- !abort; /* Not same number of items in both collections... */
+ /* Not same number of items in both collections. */
+ equals = equals && !(iter_a.valid || iter_b.valid) && !abort;
RNA_property_collection_end(&iter_a);
RNA_property_collection_end(&iter_b);
diff --git a/source/blender/makesrna/intern/rna_scene.c b/source/blender/makesrna/intern/rna_scene.c
index b47454ecd84..dcbbdd67d7b 100644
--- a/source/blender/makesrna/intern/rna_scene.c
+++ b/source/blender/makesrna/intern/rna_scene.c
@@ -1666,6 +1666,13 @@ static void rna_Scene_use_nodes_update(bContext *C, PointerRNA *ptr)
DEG_relations_tag_update(CTX_data_main(C));
}
+static void rna_Physics_relations_update(Main *bmain,
+ Scene *UNUSED(scene),
+ PointerRNA *UNUSED(ptr))
+{
+ DEG_relations_tag_update(bmain);
+}
+
static void rna_Physics_update(Main *UNUSED(bmain), Scene *UNUSED(scene), PointerRNA *ptr)
{
Scene *scene = (Scene *)ptr->id.data;
@@ -7346,7 +7353,7 @@ void RNA_def_scene(BlenderRNA *brna)
RNA_def_property_pointer_sdna(prop, NULL, "rigidbody_world");
RNA_def_property_struct_type(prop, "RigidBodyWorld");
RNA_def_property_ui_text(prop, "Rigid Body World", "");
- RNA_def_property_update(prop, NC_SCENE, NULL);
+ RNA_def_property_update(prop, NC_SCENE, "rna_Physics_relations_update");
/* Tool Settings */
prop = RNA_def_property(srna, "tool_settings", PROP_POINTER, PROP_NONE);
diff --git a/source/blender/makesrna/intern/rna_screen.c b/source/blender/makesrna/intern/rna_screen.c
index 6982b8a7f52..853017e6daf 100644
--- a/source/blender/makesrna/intern/rna_screen.c
+++ b/source/blender/makesrna/intern/rna_screen.c
@@ -576,7 +576,7 @@ static void rna_def_screen(BlenderRNA *brna)
prop = RNA_def_property(srna, "use_play_3d_editors", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "redraws_flag", TIME_ALL_3D_WIN);
- RNA_def_property_ui_text(prop, "All 3D View Editors", "");
+ RNA_def_property_ui_text(prop, "All 3D Viewports", "");
RNA_def_property_update(prop, NC_SPACE | ND_SPACE_TIME, "rna_Screen_redraw_update");
prop = RNA_def_property(srna, "use_follow", PROP_BOOLEAN, PROP_NONE);
diff --git a/source/blender/makesrna/intern/rna_sculpt_paint.c b/source/blender/makesrna/intern/rna_sculpt_paint.c
index 221d4375970..ac41736451a 100644
--- a/source/blender/makesrna/intern/rna_sculpt_paint.c
+++ b/source/blender/makesrna/intern/rna_sculpt_paint.c
@@ -230,11 +230,12 @@ static void rna_ParticleEdit_redo(bContext *C, PointerRNA *UNUSED(ptr))
BKE_particle_batch_cache_dirty_tag(edit->psys, BKE_PARTICLE_BATCH_DIRTY_ALL);
psys_free_path_cache(edit->psys, edit);
- DEG_id_tag_update(&CTX_data_scene(C)->id, ID_RECALC_COPY_ON_WRITE);
+ DEG_id_tag_update(&scene->id, ID_RECALC_COPY_ON_WRITE);
}
static void rna_ParticleEdit_update(bContext *C, PointerRNA *UNUSED(ptr))
{
+ Scene *scene = CTX_data_scene(C);
ViewLayer *view_layer = CTX_data_view_layer(C);
Object *ob = OBACT(view_layer);
@@ -243,7 +244,7 @@ static void rna_ParticleEdit_update(bContext *C, PointerRNA *UNUSED(ptr))
}
/* Sync tool setting changes from original to evaluated scenes. */
- DEG_id_tag_update(&CTX_data_scene(C)->id, ID_RECALC_COPY_ON_WRITE);
+ DEG_id_tag_update(&scene->id, ID_RECALC_COPY_ON_WRITE);
}
static void rna_ParticleEdit_tool_set(PointerRNA *ptr, int value)
diff --git a/source/blender/makesrna/intern/rna_sound.c b/source/blender/makesrna/intern/rna_sound.c
index e4b120261c6..8402c4a8705 100644
--- a/source/blender/makesrna/intern/rna_sound.c
+++ b/source/blender/makesrna/intern/rna_sound.c
@@ -40,26 +40,10 @@ static void rna_Sound_update(Main *UNUSED(bmain), Scene *UNUSED(scene), PointerR
DEG_id_tag_update(&sound->id, ID_RECALC_AUDIO);
}
-static bool rna_Sound_caching_get(PointerRNA *ptr)
+static void rna_Sound_caching_update(Main *bmain, Scene *scene, PointerRNA *ptr)
{
- bSound *sound = (bSound *)(ptr->data);
- return (sound->flags & SOUND_FLAGS_CACHING) != 0;
-}
-
-static void rna_Sound_caching_set(PointerRNA *ptr, const bool value)
-{
- bSound *sound = (bSound *)(ptr->data);
- if (value) {
- BKE_sound_cache(sound);
- }
- else {
- BKE_sound_delete_cache(sound);
- }
-}
-
-static void rna_Sound_caching_update(Main *UNUSED(bmain), Scene *scene, PointerRNA *ptr)
-{
- BKE_sequencer_update_sound(scene, (bSound *)(ptr->data));
+ rna_Sound_update(bmain, scene, ptr);
+ DEG_id_tag_update(&scene->id, ID_RECALC_SEQUENCER_STRIPS);
}
#else
@@ -87,7 +71,7 @@ static void rna_def_sound(BlenderRNA *brna)
RNA_def_property_ui_text(prop, "Packed File", "");
prop = RNA_def_property(srna, "use_memory_cache", PROP_BOOLEAN, PROP_NONE);
- RNA_def_property_boolean_funcs(prop, "rna_Sound_caching_get", "rna_Sound_caching_set");
+ RNA_def_property_boolean_sdna(prop, NULL, "flags", SOUND_FLAGS_CACHING);
RNA_def_property_ui_text(prop, "Caching", "The sound file is decoded and loaded into RAM");
RNA_def_property_update(prop, 0, "rna_Sound_caching_update");
diff --git a/source/blender/makesrna/intern/rna_sound_api.c b/source/blender/makesrna/intern/rna_sound_api.c
index f172c659900..2be0ed966f1 100644
--- a/source/blender/makesrna/intern/rna_sound_api.c
+++ b/source/blender/makesrna/intern/rna_sound_api.c
@@ -26,15 +26,15 @@
#include "RNA_define.h"
#include "RNA_enum_types.h"
+#include "BKE_packedFile.h"
+
#include "rna_internal.h"
#ifdef RNA_RUNTIME
-# include "BKE_packedFile.h"
-
static void rna_Sound_pack(bSound *sound, Main *bmain, ReportList *reports)
{
- sound->packedfile = newPackedFile(reports, sound->name, ID_BLEND_PATH(bmain, &sound->id));
+ sound->packedfile = BKE_packedfile_new(reports, sound->name, ID_BLEND_PATH(bmain, &sound->id));
}
static void rna_Sound_unpack(bSound *sound, Main *bmain, ReportList *reports, int method)
@@ -44,7 +44,7 @@ static void rna_Sound_unpack(bSound *sound, Main *bmain, ReportList *reports, in
}
else {
/* reports its own error on failure */
- unpackSound(bmain, reports, sound, method);
+ BKE_packedfile_unpack_sound(bmain, reports, sound, method);
}
}
diff --git a/source/blender/makesrna/intern/rna_space.c b/source/blender/makesrna/intern/rna_space.c
index 2b51b1eee97..6dc0cf045cd 100644
--- a/source/blender/makesrna/intern/rna_space.c
+++ b/source/blender/makesrna/intern/rna_space.c
@@ -1058,21 +1058,6 @@ static PointerRNA rna_View3DShading_selected_studio_light_get(PointerRNA *ptr)
}
/* shading.light */
-static int rna_View3DShading_light_get(PointerRNA *ptr)
-{
- View3DShading *shading = (View3DShading *)ptr->data;
- return shading->light;
-}
-
-static void rna_View3DShading_light_set(PointerRNA *ptr, int value)
-{
- View3DShading *shading = (View3DShading *)ptr->data;
- if (value == V3D_LIGHTING_MATCAP && shading->color_type == V3D_SHADING_TEXTURE_COLOR) {
- shading->color_type = V3D_SHADING_MATERIAL_COLOR;
- }
- shading->light = value;
-}
-
static const EnumPropertyItem *rna_View3DShading_color_type_itemf(bContext *UNUSED(C),
PointerRNA *ptr,
PropertyRNA *UNUSED(prop),
@@ -1081,36 +1066,24 @@ static const EnumPropertyItem *rna_View3DShading_color_type_itemf(bContext *UNUS
View3DShading *shading = (View3DShading *)ptr->data;
int totitem = 0;
- EnumPropertyItem *item = NULL;
- if (shading->type == OB_SOLID) {
- RNA_enum_items_add_value(
- &item, &totitem, rna_enum_shading_color_type_items, V3D_SHADING_MATERIAL_COLOR);
+ if (shading->type == OB_WIRE) {
+ EnumPropertyItem *item = NULL;
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);
- RNA_enum_items_add_value(
- &item, &totitem, rna_enum_shading_color_type_items, V3D_SHADING_VERTEX_COLOR);
- if (shading->light != V3D_LIGHTING_MATCAP) {
- RNA_enum_items_add_value(
- &item, &totitem, rna_enum_shading_color_type_items, V3D_SHADING_TEXTURE_COLOR);
- }
+ RNA_enum_item_end(&item, &totitem);
+ *r_free = true;
+ return item;
}
- else if (shading->type == OB_WIRE) {
- 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);
+ else {
+ /* Solid mode, or lookdev mode for workbench engine. */
+ r_free = false;
+ return rna_enum_shading_color_type_items;
}
-
- RNA_enum_item_end(&item, &totitem);
- *r_free = true;
- return item;
}
/* Studio light */
@@ -2132,6 +2105,13 @@ static void rna_SpaceClipEditor_clip_mode_update(Main *UNUSED(bmain),
{
SpaceClip *sc = (SpaceClip *)(ptr->data);
+ if (sc->mode == SC_MODE_MASKEDIT && sc->view != SC_VIEW_CLIP) {
+ /* Make sure we are in the right view for mask editing */
+ sc->view = SC_VIEW_CLIP;
+ ScrArea *sa = rna_area_from_space(ptr);
+ ED_area_tag_refresh(sa);
+ }
+
sc->scopes.ok = 0;
}
@@ -2997,8 +2977,6 @@ static void rna_def_space_view3d_shading(BlenderRNA *brna)
prop = RNA_def_property(srna, "light", PROP_ENUM, PROP_NONE);
RNA_def_property_enum_sdna(prop, NULL, "light");
RNA_def_property_enum_items(prop, rna_enum_viewport_lighting_items);
- RNA_def_property_enum_funcs(
- prop, "rna_View3DShading_light_get", "rna_View3DShading_light_set", NULL);
RNA_def_property_ui_text(prop, "Lighting", "Lighting Method for Solid/Texture Viewport Shading");
RNA_def_property_update(prop, NC_SPACE | ND_SPACE_VIEW3D, NULL);
@@ -3551,7 +3529,8 @@ static void rna_def_space_view3d_overlay(BlenderRNA *brna)
prop = RNA_def_property(srna, "texture_paint_mode_opacity", PROP_FLOAT, PROP_FACTOR);
RNA_def_property_float_sdna(prop, NULL, "overlay.texture_paint_mode_opacity");
RNA_def_property_float_default(prop, 1.0f);
- RNA_def_property_ui_text(prop, "Texture Opacity", "Opacity of the texture paint mode overlay");
+ RNA_def_property_ui_text(
+ prop, "Stencil Opacity", "Opacity of the texture paint mode stencil mask overlay");
RNA_def_property_range(prop, 0.0f, 1.0f);
RNA_def_property_update(prop, NC_SPACE | ND_SPACE_VIEW3D, NULL);
diff --git a/source/blender/makesrna/intern/rna_text_api.c b/source/blender/makesrna/intern/rna_text_api.c
index ad36a56ac6a..4ca48226ee9 100644
--- a/source/blender/makesrna/intern/rna_text_api.c
+++ b/source/blender/makesrna/intern/rna_text_api.c
@@ -34,13 +34,13 @@
static void rna_Text_clear(Text *text)
{
- BKE_text_clear(text, NULL);
+ BKE_text_clear(text);
WM_main_add_notifier(NC_TEXT | NA_EDITED, text);
}
static void rna_Text_write(Text *text, const char *str)
{
- BKE_text_write(text, NULL, str);
+ BKE_text_write(text, str);
WM_main_add_notifier(NC_TEXT | NA_EDITED, text);
}
diff --git a/source/blender/makesrna/intern/rna_userdef.c b/source/blender/makesrna/intern/rna_userdef.c
index bfdb55800a2..8a9b8a14563 100644
--- a/source/blender/makesrna/intern/rna_userdef.c
+++ b/source/blender/makesrna/intern/rna_userdef.c
@@ -5808,8 +5808,8 @@ void RNA_def_userdef(BlenderRNA *brna)
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_property_update(prop, 0, "rna_userdef_ui_update");
rna_def_userdef_view(brna);
rna_def_userdef_edit(brna);
diff --git a/source/blender/makesrna/intern/rna_vfont_api.c b/source/blender/makesrna/intern/rna_vfont_api.c
index f35a764b1b0..a85dde5d8b1 100644
--- a/source/blender/makesrna/intern/rna_vfont_api.c
+++ b/source/blender/makesrna/intern/rna_vfont_api.c
@@ -26,15 +26,15 @@
#include "RNA_define.h"
#include "RNA_enum_types.h"
+#include "BKE_packedFile.h"
+
#include "rna_internal.h"
#ifdef RNA_RUNTIME
-# include "BKE_packedFile.h"
-
static void rna_VectorFont_pack(VFont *vfont, Main *bmain, ReportList *reports)
{
- vfont->packedfile = newPackedFile(reports, vfont->name, ID_BLEND_PATH(bmain, &vfont->id));
+ vfont->packedfile = BKE_packedfile_new(reports, vfont->name, ID_BLEND_PATH(bmain, &vfont->id));
}
static void rna_VectorFont_unpack(VFont *vfont, Main *bmain, ReportList *reports, int method)
@@ -44,7 +44,7 @@ static void rna_VectorFont_unpack(VFont *vfont, Main *bmain, ReportList *reports
}
else {
/* reports its own error on failure */
- unpackVFont(bmain, reports, vfont, method);
+ BKE_packedfile_unpack_vfont(bmain, reports, vfont, method);
}
}
diff --git a/source/blender/makesrna/intern/rna_wm.c b/source/blender/makesrna/intern/rna_wm.c
index 81bb550616e..1edda29a556 100644
--- a/source/blender/makesrna/intern/rna_wm.c
+++ b/source/blender/makesrna/intern/rna_wm.c
@@ -1449,12 +1449,12 @@ static StructRNA *rna_Operator_register(Main *bmain,
/* setup dummy operator & operator type to store static properties in */
dummyop.type = &dummyot;
- dummyot.idname = temp_buffers.idname; /* only assigne the pointer, string is NULL'd */
- dummyot.name = temp_buffers.name; /* only assigne the pointer, string is NULL'd */
- dummyot.description = temp_buffers.description; /* only assigne the pointer, string is NULL'd */
+ dummyot.idname = temp_buffers.idname; /* only assign the pointer, string is NULL'd */
+ dummyot.name = temp_buffers.name; /* only assign the pointer, string is NULL'd */
+ dummyot.description = temp_buffers.description; /* only assign the pointer, string is NULL'd */
dummyot.translation_context =
- temp_buffers.translation_context; /* only assigne the pointer, string is NULL'd */
- dummyot.undo_group = temp_buffers.undo_group; /* only assigne the pointer, string is NULL'd */
+ temp_buffers.translation_context; /* only assign the pointer, string is NULL'd */
+ dummyot.undo_group = temp_buffers.undo_group; /* only assign the pointer, string is NULL'd */
RNA_pointer_create(NULL, &RNA_Operator, &dummyop, &dummyotr);
/* clear in case they are left unset */
@@ -1597,12 +1597,12 @@ static StructRNA *rna_MacroOperator_register(Main *bmain,
/* setup dummy operator & operator type to store static properties in */
dummyop.type = &dummyot;
- dummyot.idname = temp_buffers.idname; /* only assigne the pointer, string is NULL'd */
- dummyot.name = temp_buffers.name; /* only assigne the pointer, string is NULL'd */
- dummyot.description = temp_buffers.description; /* only assigne the pointer, string is NULL'd */
+ dummyot.idname = temp_buffers.idname; /* only assign the pointer, string is NULL'd */
+ dummyot.name = temp_buffers.name; /* only assign the pointer, string is NULL'd */
+ dummyot.description = temp_buffers.description; /* only assign the pointer, string is NULL'd */
dummyot.translation_context =
- temp_buffers.translation_context; /* only assigne the pointer, string is NULL'd */
- dummyot.undo_group = temp_buffers.undo_group; /* only assigne the pointer, string is NULL'd */
+ temp_buffers.translation_context; /* only assign the pointer, string is NULL'd */
+ dummyot.undo_group = temp_buffers.undo_group; /* only assign the pointer, string is NULL'd */
RNA_pointer_create(NULL, &RNA_Macro, &dummyop, &dummyotr);
/* clear in case they are left unset */
diff --git a/source/blender/makesrna/intern/rna_wm_gizmo.c b/source/blender/makesrna/intern/rna_wm_gizmo.c
index 41e499471ea..38b6ac9ac52 100644
--- a/source/blender/makesrna/intern/rna_wm_gizmo.c
+++ b/source/blender/makesrna/intern/rna_wm_gizmo.c
@@ -243,6 +243,12 @@ static void rna_Gizmo_bl_idname_set(PointerRNA *ptr, const char *value)
}
}
+static void rna_Gizmo_update_redraw(Main *UNUSED(bmain), Scene *UNUSED(scene), PointerRNA *ptr)
+{
+ wmGizmo *gizmo = ptr->data;
+ gizmo->do_draw = true;
+}
+
static wmGizmo *rna_GizmoProperties_find_operator(PointerRNA *ptr)
{
# if 0
@@ -1123,7 +1129,7 @@ static void rna_def_gizmo(BlenderRNA *brna, PropertyRNA *cprop)
RNA_def_property_ui_text(prop, "Alpha", "");
RNA_def_property_float_funcs(prop, "rna_Gizmo_alpha_get", "rna_Gizmo_alpha_set", NULL);
RNA_def_property_range(prop, 0.0f, 1.0f);
- RNA_def_property_update(prop, NC_SCREEN | NA_EDITED, NULL);
+ RNA_def_property_update(prop, 0, "rna_Gizmo_update_redraw");
/* Color & Alpha (highlight) */
prop = RNA_def_property(srna, "color_highlight", PROP_FLOAT, PROP_COLOR);
@@ -1134,28 +1140,28 @@ static void rna_def_gizmo(BlenderRNA *brna, PropertyRNA *cprop)
RNA_def_property_ui_text(prop, "Alpha", "");
RNA_def_property_float_funcs(prop, "rna_Gizmo_alpha_hi_get", "rna_Gizmo_alpha_hi_set", NULL);
RNA_def_property_range(prop, 0.0f, 1.0f);
- RNA_def_property_update(prop, NC_SCREEN | NA_EDITED, NULL);
+ RNA_def_property_update(prop, 0, "rna_Gizmo_update_redraw");
prop = RNA_def_property(srna, "matrix_space", PROP_FLOAT, PROP_MATRIX);
RNA_def_property_multi_array(prop, 2, rna_matrix_dimsize_4x4);
RNA_def_property_ui_text(prop, "Space Matrix", "");
RNA_def_property_float_funcs(
prop, "rna_Gizmo_matrix_space_get", "rna_Gizmo_matrix_space_set", NULL);
- RNA_def_property_update(prop, NC_SCREEN | NA_EDITED, NULL);
+ RNA_def_property_update(prop, 0, "rna_Gizmo_update_redraw");
prop = RNA_def_property(srna, "matrix_basis", PROP_FLOAT, PROP_MATRIX);
RNA_def_property_multi_array(prop, 2, rna_matrix_dimsize_4x4);
RNA_def_property_ui_text(prop, "Basis Matrix", "");
RNA_def_property_float_funcs(
prop, "rna_Gizmo_matrix_basis_get", "rna_Gizmo_matrix_basis_set", NULL);
- RNA_def_property_update(prop, NC_SCREEN | NA_EDITED, NULL);
+ RNA_def_property_update(prop, 0, "rna_Gizmo_update_redraw");
prop = RNA_def_property(srna, "matrix_offset", PROP_FLOAT, PROP_MATRIX);
RNA_def_property_multi_array(prop, 2, rna_matrix_dimsize_4x4);
RNA_def_property_ui_text(prop, "Offset Matrix", "");
RNA_def_property_float_funcs(
prop, "rna_Gizmo_matrix_offset_get", "rna_Gizmo_matrix_offset_set", NULL);
- RNA_def_property_update(prop, NC_SCREEN | NA_EDITED, NULL);
+ RNA_def_property_update(prop, 0, "rna_Gizmo_update_redraw");
prop = RNA_def_property(srna, "matrix_world", PROP_FLOAT, PROP_MATRIX);
RNA_def_property_clear_flag(prop, PROP_EDITABLE);
@@ -1168,13 +1174,13 @@ static void rna_def_gizmo(BlenderRNA *brna, PropertyRNA *cprop)
RNA_def_property_float_funcs(
prop, "rna_Gizmo_scale_basis_get", "rna_Gizmo_scale_basis_set", NULL);
RNA_def_property_range(prop, 0.0f, FLT_MAX);
- RNA_def_property_update(prop, NC_SCREEN | NA_EDITED, NULL);
+ RNA_def_property_update(prop, 0, "rna_Gizmo_update_redraw");
prop = RNA_def_property(srna, "line_width", PROP_FLOAT, PROP_PIXEL);
RNA_def_property_ui_text(prop, "Line Width", "");
RNA_def_property_float_funcs(prop, "rna_Gizmo_line_width_get", "rna_Gizmo_line_width_set", NULL);
RNA_def_property_range(prop, 0.0f, FLT_MAX);
- RNA_def_property_update(prop, NC_SCREEN | NA_EDITED, NULL);
+ RNA_def_property_update(prop, 0, "rna_Gizmo_update_redraw");
prop = RNA_def_property(srna, "select_bias", PROP_FLOAT, PROP_NONE);
RNA_def_property_ui_text(prop, "Select Bias", "Depth bias used for selection");
@@ -1187,39 +1193,39 @@ static void rna_def_gizmo(BlenderRNA *brna, PropertyRNA *cprop)
prop = RNA_def_property(srna, "hide", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_funcs(prop, "rna_Gizmo_flag_hide_get", "rna_Gizmo_flag_hide_set");
RNA_def_property_ui_text(prop, "Hide", "");
- RNA_def_property_update(prop, NC_SCREEN | NA_EDITED, NULL);
+ RNA_def_property_update(prop, 0, "rna_Gizmo_update_redraw");
/* WM_GIZMO_HIDDEN_SELECT */
prop = RNA_def_property(srna, "hide_select", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_funcs(
prop, "rna_Gizmo_flag_hide_select_get", "rna_Gizmo_flag_hide_select_set");
RNA_def_property_ui_text(prop, "Hide Select", "");
- RNA_def_property_update(prop, NC_SCREEN | NA_EDITED, NULL);
+ RNA_def_property_update(prop, 0, "rna_Gizmo_update_redraw");
/* WM_GIZMO_MOVE_CURSOR */
prop = RNA_def_property(srna, "use_grab_cursor", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_funcs(
prop, "rna_Gizmo_flag_use_grab_cursor_get", "rna_Gizmo_flag_use_grab_cursor_set");
RNA_def_property_ui_text(prop, "Grab Cursor", "");
- RNA_def_property_update(prop, NC_SCREEN | NA_EDITED, NULL);
+ RNA_def_property_update(prop, 0, "rna_Gizmo_update_redraw");
/* WM_GIZMO_DRAW_HOVER */
prop = RNA_def_property(srna, "use_draw_hover", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_funcs(
prop, "rna_Gizmo_flag_use_draw_hover_get", "rna_Gizmo_flag_use_draw_hover_set");
RNA_def_property_ui_text(prop, "Draw Hover", "");
- RNA_def_property_update(prop, NC_SCREEN | NA_EDITED, NULL);
+ RNA_def_property_update(prop, 0, "rna_Gizmo_update_redraw");
/* WM_GIZMO_DRAW_MODAL */
prop = RNA_def_property(srna, "use_draw_modal", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_funcs(
prop, "rna_Gizmo_flag_use_draw_modal_get", "rna_Gizmo_flag_use_draw_modal_set");
RNA_def_property_ui_text(prop, "Draw Active", "Draw while dragging");
- RNA_def_property_update(prop, NC_SCREEN | NA_EDITED, NULL);
+ RNA_def_property_update(prop, 0, "rna_Gizmo_update_redraw");
/* WM_GIZMO_DRAW_VALUE */
prop = RNA_def_property(srna, "use_draw_value", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_funcs(
prop, "rna_Gizmo_flag_use_draw_value_get", "rna_Gizmo_flag_use_draw_value_set");
RNA_def_property_ui_text(
prop, "Draw Value", "Show an indicator for the current value while dragging");
- RNA_def_property_update(prop, NC_SCREEN | NA_EDITED, NULL);
+ RNA_def_property_update(prop, 0, "rna_Gizmo_update_redraw");
/* WM_GIZMO_DRAW_OFFSET_SCALE */
prop = RNA_def_property(srna, "use_draw_offset_scale", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_funcs(prop,
@@ -1227,20 +1233,20 @@ static void rna_def_gizmo(BlenderRNA *brna, PropertyRNA *cprop)
"rna_Gizmo_flag_use_draw_offset_scale_set");
RNA_def_property_ui_text(
prop, "Scale Offset", "Scale the offset matrix (use to apply screen-space offset)");
- RNA_def_property_update(prop, NC_SCREEN | NA_EDITED, NULL);
+ RNA_def_property_update(prop, 0, "rna_Gizmo_update_redraw");
/* WM_GIZMO_DRAW_NO_SCALE (negated) */
prop = RNA_def_property(srna, "use_draw_scale", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_funcs(
prop, "rna_Gizmo_flag_use_draw_scale_get", "rna_Gizmo_flag_use_draw_scale_set");
RNA_def_property_ui_text(prop, "Scale", "Use scale when calculating the matrix");
- RNA_def_property_update(prop, NC_SCREEN | NA_EDITED, NULL);
+ RNA_def_property_update(prop, 0, "rna_Gizmo_update_redraw");
/* WM_GIZMO_SELECT_BACKGROUND */
prop = RNA_def_property(srna, "use_select_background", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_funcs(prop,
"rna_Gizmo_flag_use_select_background_get",
"rna_Gizmo_flag_use_select_background_set");
RNA_def_property_ui_text(prop, "Select Background", "Don't write into the depth buffer");
- RNA_def_property_update(prop, NC_SCREEN | NA_EDITED, NULL);
+ RNA_def_property_update(prop, 0, "rna_Gizmo_update_redraw");
/* WM_GIZMO_OPERATOR_TOOL_INIT */
prop = RNA_def_property(srna, "use_operator_tool_properties", PROP_BOOLEAN, PROP_NONE);
@@ -1251,7 +1257,7 @@ static void rna_def_gizmo(BlenderRNA *brna, PropertyRNA *cprop)
prop,
"Tool Property Init",
"Merge active tool properties on activation (does not overwrite existing)");
- RNA_def_property_update(prop, NC_SCREEN | NA_EDITED, NULL);
+ RNA_def_property_update(prop, 0, "rna_Gizmo_update_redraw");
/* WM_GIZMO_EVENT_HANDLE_ALL */
prop = RNA_def_property(srna, "use_event_handle_all", PROP_BOOLEAN, PROP_NONE);
@@ -1261,7 +1267,7 @@ static void rna_def_gizmo(BlenderRNA *brna, PropertyRNA *cprop)
"Handle All Events",
"When highlighted, "
"do not pass events through to be handled by other keymaps");
- RNA_def_property_update(prop, NC_SCREEN | NA_EDITED, NULL);
+ RNA_def_property_update(prop, 0, "rna_Gizmo_update_redraw");
/* wmGizmo.state (readonly) */
/* WM_GIZMO_STATE_HIGHLIGHT */
diff --git a/source/blender/modifiers/intern/MOD_bevel.c b/source/blender/modifiers/intern/MOD_bevel.c
index 26b45bbef0d..309af4d4812 100644
--- a/source/blender/modifiers/intern/MOD_bevel.c
+++ b/source/blender/modifiers/intern/MOD_bevel.c
@@ -130,9 +130,6 @@ static Mesh *applyModifier(ModifierData *md, const ModifierEvalContext *ctx, Mes
if (vertex_only) {
BM_ITER_MESH (v, &iter, bm, BM_VERTS_OF_MESH) {
- if (!BM_vert_is_manifold(v)) {
- continue;
- }
if (bmd->lim_flags & MOD_BEVEL_WEIGHT) {
weight = BM_elem_float_data_get(&bm->vdata, v, CD_BWEIGHT);
if (weight == 0.0f) {
@@ -187,7 +184,9 @@ static Mesh *applyModifier(ModifierData *md, const ModifierEvalContext *ctx, Mes
}
}
- if (harden_normals && !(((Mesh *)ctx->object->data)->flag & ME_AUTOSMOOTH)) {
+ Object *ob = ctx->object;
+
+ if (harden_normals && (ob->type == OB_MESH) && !(((Mesh *)ob->data)->flag & ME_AUTOSMOOTH)) {
modifier_setError(md, "Enable 'Auto Smooth' option in mesh settings for hardening");
harden_normals = false;
}
diff --git a/source/blender/modifiers/intern/MOD_cloth.c b/source/blender/modifiers/intern/MOD_cloth.c
index 3c4dd9f2c56..1a6d172d2f9 100644
--- a/source/blender/modifiers/intern/MOD_cloth.c
+++ b/source/blender/modifiers/intern/MOD_cloth.c
@@ -125,12 +125,14 @@ static void updateDepsgraph(ModifierData *md, const ModifierUpdateDepsgraphConte
{
ClothModifierData *clmd = (ClothModifierData *)md;
if (clmd != NULL) {
- DEG_add_collision_relations(ctx->node,
- ctx->object,
- clmd->coll_parms->group,
- eModifierType_Collision,
- NULL,
- "Cloth Collision");
+ if (clmd->coll_parms->flags & CLOTH_COLLSETTINGS_FLAG_ENABLED) {
+ DEG_add_collision_relations(ctx->node,
+ ctx->object,
+ clmd->coll_parms->group,
+ eModifierType_Collision,
+ NULL,
+ "Cloth Collision");
+ }
DEG_add_forcefield_relations(
ctx->node, ctx->object, clmd->sim_parms->effector_weights, true, 0, "Cloth Field");
}
diff --git a/source/blender/modifiers/intern/MOD_decimate.c b/source/blender/modifiers/intern/MOD_decimate.c
index c41abfb6eb2..cff700e8d45 100644
--- a/source/blender/modifiers/intern/MOD_decimate.c
+++ b/source/blender/modifiers/intern/MOD_decimate.c
@@ -200,8 +200,8 @@ static Mesh *applyModifier(ModifierData *md, const ModifierEvalContext *ctx, Mes
updateFaceCount(ctx, dmd, bm->totface);
result = BKE_mesh_from_bmesh_for_eval_nomain(bm, NULL);
- BLI_assert(bm->vtoolflagpool == NULL && bm->etoolflagpool == NULL &&
- bm->ftoolflagpool == NULL); /* make sure we never alloc'd these */
+ /* make sure we never alloc'd these */
+ BLI_assert(bm->vtoolflagpool == NULL && bm->etoolflagpool == NULL && bm->ftoolflagpool == NULL);
BLI_assert(bm->vtable == NULL && bm->etable == NULL && bm->ftable == NULL);
BM_mesh_free(bm);
diff --git a/source/blender/modifiers/intern/MOD_dynamicpaint.c b/source/blender/modifiers/intern/MOD_dynamicpaint.c
index ce488a224aa..26ee75140a6 100644
--- a/source/blender/modifiers/intern/MOD_dynamicpaint.c
+++ b/source/blender/modifiers/intern/MOD_dynamicpaint.c
@@ -112,16 +112,17 @@ static Mesh *applyModifier(ModifierData *md, const ModifierEvalContext *ctx, Mes
return mesh;
}
-static bool is_brush_cb(Object *UNUSED(ob), ModifierData *pmd)
+static bool is_brush_cb(Object *UNUSED(ob), ModifierData *md)
{
- return ((DynamicPaintModifierData *)pmd)->brush != NULL;
+ DynamicPaintModifierData *pmd = (DynamicPaintModifierData *)md;
+ return (pmd->brush != NULL && pmd->type == MOD_DYNAMICPAINT_TYPE_BRUSH);
}
static void updateDepsgraph(ModifierData *md, const ModifierUpdateDepsgraphContext *ctx)
{
DynamicPaintModifierData *pmd = (DynamicPaintModifierData *)md;
/* Add relation from canvases to all brush objects. */
- if (pmd->canvas != NULL) {
+ if (pmd->canvas != NULL && pmd->type == MOD_DYNAMICPAINT_TYPE_CANVAS) {
for (DynamicPaintSurface *surface = pmd->canvas->surfaces.first; surface;
surface = surface->next) {
if (surface->effect & MOD_DPAINT_EFFECT_DO_DRIP) {
diff --git a/source/blender/modifiers/intern/MOD_mirror.c b/source/blender/modifiers/intern/MOD_mirror.c
index 857c69eab50..11f001d7a85 100644
--- a/source/blender/modifiers/intern/MOD_mirror.c
+++ b/source/blender/modifiers/intern/MOD_mirror.c
@@ -335,7 +335,7 @@ static Mesh *doMirrorOnAxis(MirrorModifierData *mmd,
}
/* handle custom split normals */
- if ((((Mesh *)ob->data)->flag & ME_AUTOSMOOTH) &&
+ if (ob->type == OB_MESH && (((Mesh *)ob->data)->flag & ME_AUTOSMOOTH) &&
CustomData_has_layer(&result->ldata, CD_CUSTOMLOOPNORMAL)) {
const int totloop = result->totloop;
const int totpoly = result->totpoly;
diff --git a/source/blender/modifiers/intern/MOD_particlesystem.c b/source/blender/modifiers/intern/MOD_particlesystem.c
index 5d7b380a751..021e61bd46d 100644
--- a/source/blender/modifiers/intern/MOD_particlesystem.c
+++ b/source/blender/modifiers/intern/MOD_particlesystem.c
@@ -138,8 +138,16 @@ static void deformVerts(ModifierData *md,
}
/* TODO(sergey): This is not how particles were working prior to copy on
* write, but now evaluation is similar to case when one duplicates the
- * object. In that case particles were doing reset here. */
- psys->recalc |= ID_RECALC_PSYS_RESET;
+ * object. In that case particles were doing reset here.
+ *
+ * Don't do reset when entering particle edit mode, as that will destroy the edit mode data.
+ * Shouldn't be an issue, since particles are supposed to be evaluated once prior to entering
+ * edit mode anyway.
+ * Could in theory be an issue when everything is done in a script, but then solution is
+ * not known to me. */
+ if (ctx->object->mode != OB_MODE_PARTICLE_EDIT) {
+ psys->recalc |= ID_RECALC_PSYS_RESET;
+ }
}
/* make new mesh */
@@ -193,10 +201,10 @@ static void deformVerts(ModifierData *md,
psmd->mesh_final->totedge != psmd->totdmedge ||
psmd->mesh_final->totface != psmd->totdmface)) {
psys->recalc |= ID_RECALC_PSYS_RESET;
- psmd->totdmvert = psmd->mesh_final->totvert;
- psmd->totdmedge = psmd->mesh_final->totedge;
- psmd->totdmface = psmd->mesh_final->totface;
}
+ psmd->totdmvert = psmd->mesh_final->totvert;
+ psmd->totdmedge = psmd->mesh_final->totedge;
+ psmd->totdmface = psmd->mesh_final->totface;
if (!(ctx->object->transflag & OB_NO_PSYS_UPDATE)) {
struct Scene *scene = DEG_get_evaluated_scene(ctx->depsgraph);
diff --git a/source/blender/modifiers/intern/MOD_screw.c b/source/blender/modifiers/intern/MOD_screw.c
index 79f7e52681b..64f5f14eaa8 100644
--- a/source/blender/modifiers/intern/MOD_screw.c
+++ b/source/blender/modifiers/intern/MOD_screw.c
@@ -132,6 +132,9 @@ static Mesh *mesh_remove_doubles_on_axis(Mesh *result,
tot_doubles += 1;
copy_v3_v3(mvert_new[i].co, axis_co);
}
+ else {
+ mvert_new[i].flag &= ~ME_VERT_TMP_TAG & 0xFF;
+ }
}
if (tot_doubles != 0) {
@@ -438,6 +441,10 @@ static Mesh *applyModifier(ModifierData *md, const ModifierEvalContext *ctx, Mes
med_new->v2 = med_orig->v2;
med_new->crease = med_orig->crease;
med_new->flag = med_orig->flag & ~ME_LOOSEEDGE;
+ /* Tag mvert as not loose.
+ * NOTE: ME_VERT_TMP_TAG is given to be cleared by BKE_mesh_new_nomain_from_template. */
+ mvert_new[med_orig->v1].flag |= ME_VERT_TMP_TAG;
+ mvert_new[med_orig->v2].flag |= ME_VERT_TMP_TAG;
}
/* build polygon -> edge map */
@@ -899,6 +906,9 @@ static Mesh *applyModifier(ModifierData *md, const ModifierEvalContext *ctx, Mes
med_new->v1 = varray_stride + j;
med_new->v2 = med_new->v1 - totvert;
med_new->flag = ME_EDGEDRAW | ME_EDGERENDER;
+ if ((mv_new_base->flag & ME_VERT_TMP_TAG) == 0) {
+ med_new->flag |= ME_LOOSEEDGE;
+ }
med_new++;
}
}
@@ -917,6 +927,9 @@ static Mesh *applyModifier(ModifierData *md, const ModifierEvalContext *ctx, Mes
med_new->v1 = i;
med_new->v2 = varray_stride + i;
med_new->flag = ME_EDGEDRAW | ME_EDGERENDER;
+ if ((mvert_new[i].flag & ME_VERT_TMP_TAG) == 0) {
+ med_new->flag |= ME_LOOSEEDGE;
+ }
med_new++;
}
}
diff --git a/source/blender/modifiers/intern/MOD_solidify.c b/source/blender/modifiers/intern/MOD_solidify.c
index 88135b8790b..05bcc7f695d 100644
--- a/source/blender/modifiers/intern/MOD_solidify.c
+++ b/source/blender/modifiers/intern/MOD_solidify.c
@@ -841,8 +841,10 @@ static Mesh *applyModifier(ModifierData *md, const ModifierEvalContext *ctx, Mes
/* notice we use 'mp->totloop' which is later overwritten,
* we could lookup the original face but there's no point since this is a copy
* and will have the same value, just take care when changing order of assignment */
- k1 = mpoly[pidx].loopstart +
- (((edge_order[eidx] - 1) + mp->totloop) % mp->totloop); /* prev loop */
+
+ /* prev loop */
+ k1 = mpoly[pidx].loopstart + (((edge_order[eidx] - 1) + mp->totloop) % mp->totloop);
+
k2 = mpoly[pidx].loopstart + (edge_order[eidx]);
mp->totloop = 4;
diff --git a/source/blender/nodes/composite/nodes/node_composite_image.c b/source/blender/nodes/composite/nodes/node_composite_image.c
index 79db436ec4e..88765f1d165 100644
--- a/source/blender/nodes/composite/nodes/node_composite_image.c
+++ b/source/blender/nodes/composite/nodes/node_composite_image.c
@@ -32,6 +32,7 @@
#include "BKE_context.h"
#include "BKE_global.h"
+#include "BKE_library.h"
#include "BKE_main.h"
#include "BKE_scene.h"
@@ -514,6 +515,7 @@ static void node_composit_init_rlayers(const bContext *C, PointerRNA *ptr)
int sock_index = 0;
node->id = &scene->id;
+ id_us_plus(node->id);
for (bNodeSocket *sock = node->outputs.first; sock; sock = sock->next, sock_index++) {
NodeImageLayer *sockdata = MEM_callocN(sizeof(NodeImageLayer), "node image layer");
diff --git a/source/blender/nodes/composite/nodes/node_composite_movieclip.c b/source/blender/nodes/composite/nodes/node_composite_movieclip.c
index e871b764a82..07b339a5b78 100644
--- a/source/blender/nodes/composite/nodes/node_composite_movieclip.c
+++ b/source/blender/nodes/composite/nodes/node_composite_movieclip.c
@@ -24,6 +24,7 @@
#include "node_composite_util.h"
#include "BKE_context.h"
+#include "BKE_library.h"
static bNodeSocketTemplate cmp_node_movieclip_out[] = {
{SOCK_RGBA, 0, N_("Image")},
@@ -42,6 +43,7 @@ static void init(const bContext *C, PointerRNA *ptr)
MovieClipUser *user = MEM_callocN(sizeof(MovieClipUser), "node movie clip user");
node->id = (ID *)scene->clip;
+ id_us_plus(node->id);
node->storage = user;
user->framenr = 1;
}
diff --git a/source/blender/nodes/composite/nodes/node_composite_moviedistortion.c b/source/blender/nodes/composite/nodes/node_composite_moviedistortion.c
index dbdd65c5976..d218f7568eb 100644
--- a/source/blender/nodes/composite/nodes/node_composite_moviedistortion.c
+++ b/source/blender/nodes/composite/nodes/node_composite_moviedistortion.c
@@ -24,6 +24,7 @@
#include "node_composite_util.h"
#include "BKE_context.h"
+#include "BKE_library.h"
/* **************** Translate ******************** */
@@ -53,6 +54,7 @@ static void init(const bContext *C, PointerRNA *ptr)
Scene *scene = CTX_data_scene(C);
node->id = (ID *)scene->clip;
+ id_us_plus(node->id);
}
static void storage_free(bNode *node)
diff --git a/source/blender/nodes/composite/nodes/node_composite_stabilize2d.c b/source/blender/nodes/composite/nodes/node_composite_stabilize2d.c
index 55d4ada0ca1..c13356f72b0 100644
--- a/source/blender/nodes/composite/nodes/node_composite_stabilize2d.c
+++ b/source/blender/nodes/composite/nodes/node_composite_stabilize2d.c
@@ -24,6 +24,7 @@
#include "node_composite_util.h"
#include "BKE_context.h"
+#include "BKE_library.h"
/* **************** Translate ******************** */
@@ -43,6 +44,7 @@ static void init(const bContext *C, PointerRNA *ptr)
Scene *scene = CTX_data_scene(C);
node->id = (ID *)scene->clip;
+ id_us_plus(node->id);
/* default to bilinear, see node_sampler_type_items in rna_nodetree.c */
node->custom1 = 1;
diff --git a/source/blender/nodes/composite/nodes/node_composite_switchview.c b/source/blender/nodes/composite/nodes/node_composite_switchview.c
index 12401a8bbdf..92e06307afb 100644
--- a/source/blender/nodes/composite/nodes/node_composite_switchview.c
+++ b/source/blender/nodes/composite/nodes/node_composite_switchview.c
@@ -23,6 +23,8 @@
*/
#include "BKE_context.h"
+#include "BKE_library.h"
+
#include "../node_composite_util.h"
/* **************** SWITCH VIEW ******************** */
@@ -122,6 +124,7 @@ static void init_switch_view(const bContext *C, PointerRNA *ptr)
/* store scene for updates */
node->id = (ID *)scene;
+ id_us_plus(node->id);
if (scene) {
RenderData *rd = &scene->r;
diff --git a/source/blender/nodes/shader/nodes/node_shader_math.c b/source/blender/nodes/shader/nodes/node_shader_math.c
index 70432e04180..f0cd2273e67 100644
--- a/source/blender/nodes/shader/nodes/node_shader_math.c
+++ b/source/blender/nodes/shader/nodes/node_shader_math.c
@@ -64,9 +64,8 @@ static void node_shader_exec_math(void *UNUSED(data),
break;
}
case NODE_MATH_SIN: {
- if (in[0]->hasinput ||
- !in[1]->hasinput) /* This one only takes one input, so we've got to choose. */
- {
+ /* This one only takes one input, so we've got to choose. */
+ if (in[0]->hasinput || !in[1]->hasinput) {
r = sinf(a);
}
else {
@@ -75,9 +74,8 @@ static void node_shader_exec_math(void *UNUSED(data),
break;
}
case NODE_MATH_COS: {
- if (in[0]->hasinput ||
- !in[1]->hasinput) /* This one only takes one input, so we've got to choose. */
- {
+ /* This one only takes one input, so we've got to choose. */
+ if (in[0]->hasinput || !in[1]->hasinput) {
r = cosf(a);
}
else {
@@ -86,9 +84,8 @@ static void node_shader_exec_math(void *UNUSED(data),
break;
}
case NODE_MATH_TAN: {
- if (in[0]->hasinput ||
- !in[1]->hasinput) /* This one only takes one input, so we've got to choose. */
- {
+ /* This one only takes one input, so we've got to choose. */
+ if (in[0]->hasinput || !in[1]->hasinput) {
r = tanf(a);
}
else {
@@ -97,8 +94,8 @@ static void node_shader_exec_math(void *UNUSED(data),
break;
}
case NODE_MATH_ASIN: {
- if (in[0]->hasinput ||
- !in[1]->hasinput) { /* This one only takes one input, so we've got to choose. */
+ /* This one only takes one input, so we've got to choose. */
+ if (in[0]->hasinput || !in[1]->hasinput) {
/* Can't do the impossible... */
if (a <= 1 && a >= -1) {
r = asinf(a);
@@ -119,8 +116,8 @@ static void node_shader_exec_math(void *UNUSED(data),
break;
}
case NODE_MATH_ACOS: {
- if (in[0]->hasinput ||
- !in[1]->hasinput) { /* This one only takes one input, so we've got to choose. */
+ /* This one only takes one input, so we've got to choose. */
+ if (in[0]->hasinput || !in[1]->hasinput) {
/* Can't do the impossible... */
if (a <= 1 && a >= -1) {
r = acosf(a);
@@ -141,9 +138,8 @@ static void node_shader_exec_math(void *UNUSED(data),
break;
}
case NODE_MATH_ATAN: {
- if (in[0]->hasinput ||
- !in[1]->hasinput) /* This one only takes one input, so we've got to choose. */
- {
+ /* This one only takes one input, so we've got to choose. */
+ if (in[0]->hasinput || !in[1]->hasinput) {
r = atan(a);
}
else {
@@ -200,9 +196,8 @@ static void node_shader_exec_math(void *UNUSED(data),
break;
}
case NODE_MATH_ROUND: {
- if (in[0]->hasinput ||
- !in[1]->hasinput) /* This one only takes one input, so we've got to choose. */
- {
+ /* This one only takes one input, so we've got to choose. */
+ if (in[0]->hasinput || !in[1]->hasinput) {
r = (a < 0) ? (int)(a - 0.5f) : (int)(a + 0.5f);
}
else {
@@ -246,9 +241,8 @@ static void node_shader_exec_math(void *UNUSED(data),
break;
}
case NODE_MATH_FLOOR: {
- if (in[0]->hasinput ||
- !in[1]->hasinput) /* This one only takes one input, so we've got to choose. */
- {
+ /* This one only takes one input, so we've got to choose. */
+ if (in[0]->hasinput || !in[1]->hasinput) {
r = floorf(a);
}
else {
@@ -257,9 +251,8 @@ static void node_shader_exec_math(void *UNUSED(data),
break;
}
case NODE_MATH_CEIL: {
- if (in[0]->hasinput ||
- !in[1]->hasinput) /* This one only takes one input, so we've got to choose. */
- {
+ /* This one only takes one input, so we've got to choose. */
+ if (in[0]->hasinput || !in[1]->hasinput) {
r = ceilf(a);
}
else {
@@ -268,9 +261,8 @@ static void node_shader_exec_math(void *UNUSED(data),
break;
}
case NODE_MATH_FRACT: {
- if (in[0]->hasinput ||
- !in[1]->hasinput) /* This one only takes one input, so we've got to choose. */
- {
+ /* This one only takes one input, so we've got to choose. */
+ if (in[0]->hasinput || !in[1]->hasinput) {
r = a - floorf(a);
}
else {
@@ -279,9 +271,8 @@ static void node_shader_exec_math(void *UNUSED(data),
break;
}
case NODE_MATH_SQRT: {
- if (in[0]->hasinput ||
- !in[1]->hasinput) /* This one only takes one input, so we've got to choose. */
- {
+ /* This one only takes one input, so we've got to choose. */
+ if (in[0]->hasinput || !in[1]->hasinput) {
if (a > 0) {
r = sqrt(a);
}
diff --git a/source/blender/nodes/shader/nodes/node_shader_shaderToRgb.c b/source/blender/nodes/shader/nodes/node_shader_shaderToRgb.c
index 583ec7edcc3..3a47fe3e991 100644
--- a/source/blender/nodes/shader/nodes/node_shader_shaderToRgb.c
+++ b/source/blender/nodes/shader/nodes/node_shader_shaderToRgb.c
@@ -38,6 +38,10 @@ static int node_shader_gpu_shadertorgb(GPUMaterial *mat,
GPUNodeStack *in,
GPUNodeStack *out)
{
+ /* Because node_shader_to_rgba is using fallback_cubemap()
+ * we need to tag material as glossy. */
+ GPU_material_flag_set(mat, GPU_MATFLAG_GLOSSY);
+
return GPU_stack_link(mat, node, "node_shader_to_rgba", in, out);
}
diff --git a/source/blender/nodes/shader/nodes/node_shader_vectMath.c b/source/blender/nodes/shader/nodes/node_shader_vectMath.c
index c6b74e2a727..41273a6dc1d 100644
--- a/source/blender/nodes/shader/nodes/node_shader_vectMath.c
+++ b/source/blender/nodes/shader/nodes/node_shader_vectMath.c
@@ -78,8 +78,8 @@ static void node_shader_exec_vect_math(void *UNUSED(data),
out[1]->vec[0] = normalize_v3(out[0]->vec);
}
else if (node->custom1 == 5) { /* Normalize */
- if (in[0]->hasinput ||
- !in[1]->hasinput) { /* This one only takes one input, so we've got to choose. */
+ /* This one only takes one input, so we've got to choose. */
+ if (in[0]->hasinput || !in[1]->hasinput) {
out[0]->vec[0] = vec1[0];
out[0]->vec[1] = vec1[1];
out[0]->vec[2] = vec1[2];
diff --git a/source/blender/physics/intern/hair_volume.cpp b/source/blender/physics/intern/hair_volume.cpp
index a4f799974e3..33c65a0cf95 100644
--- a/source/blender/physics/intern/hair_volume.cpp
+++ b/source/blender/physics/intern/hair_volume.cpp
@@ -698,8 +698,8 @@ void BPH_hair_volume_normalize_vertex_grid(HairGrid *grid)
}
}
-static const float density_threshold =
- 0.001f; /* cells with density below this are considered empty */
+/* Cells with density below this are considered empty. */
+static const float density_threshold = 0.001f;
/* Contribution of target density pressure to the laplacian in the pressure poisson equation.
* This is based on the model found in
diff --git a/source/blender/python/generic/imbuf_py_api.c b/source/blender/python/generic/imbuf_py_api.c
index 26e4e5bcf32..22be0429ea5 100644
--- a/source/blender/python/generic/imbuf_py_api.c
+++ b/source/blender/python/generic/imbuf_py_api.c
@@ -24,6 +24,7 @@
#include "BLI_utildefines.h"
#include "BLI_string.h"
+#include "BLI_rect.h"
#include "py_capi_utils.h"
@@ -105,6 +106,43 @@ static PyObject *py_imbuf_resize(Py_ImBuf *self, PyObject *args, PyObject *kw)
Py_RETURN_NONE;
}
+PyDoc_STRVAR(py_imbuf_crop_doc,
+ ".. method:: crop(min, max)\n"
+ "\n"
+ " Crop the image.\n"
+ "\n"
+ " :arg min: X, Y minimum.\n"
+ " :type min: pair of ints\n"
+ " :arg max: X, Y maximum.\n"
+ " :type max: pair of ints\n");
+static PyObject *py_imbuf_crop(Py_ImBuf *self, PyObject *args, PyObject *kw)
+{
+ PY_IMBUF_CHECK_OBJ(self);
+
+ rcti crop;
+
+ static const char *_keywords[] = {"min", "max", NULL};
+ static _PyArg_Parser _parser = {"(II)(II):crop", _keywords, 0};
+ if (!_PyArg_ParseTupleAndKeywordsFast(
+ args, kw, &_parser, &crop.xmin, &crop.ymin, &crop.xmax, &crop.ymax)) {
+ return NULL;
+ }
+
+ if (/* X range. */
+ (!(crop.xmin >= 0 && crop.xmax < self->ibuf->x)) ||
+ /* Y range. */
+ (!(crop.ymin >= 0 && crop.ymax < self->ibuf->y)) ||
+ /* X order. */
+ (!(crop.xmin <= crop.xmax)) ||
+ /* Y order. */
+ (!(crop.ymin <= crop.ymax))) {
+ PyErr_SetString(PyExc_ValueError, "ImBuf crop min/max not in range");
+ return NULL;
+ }
+ IMB_rect_crop(self->ibuf, &crop);
+ Py_RETURN_NONE;
+}
+
PyDoc_STRVAR(py_imbuf_copy_doc,
".. method:: copy()\n"
"\n"
@@ -138,14 +176,12 @@ static PyObject *py_imbuf_free(Py_ImBuf *self)
}
static struct PyMethodDef Py_ImBuf_methods[] = {
- {"resize",
- (PyCFunction)py_imbuf_resize,
- METH_VARARGS | METH_KEYWORDS,
- (char *)py_imbuf_resize_doc},
- {"free", (PyCFunction)py_imbuf_free, METH_NOARGS, (char *)py_imbuf_free_doc},
- {"copy", (PyCFunction)py_imbuf_copy, METH_NOARGS, (char *)py_imbuf_copy_doc},
- {"__copy__", (PyCFunction)py_imbuf_copy, METH_NOARGS, (char *)py_imbuf_copy_doc},
- {"__deepcopy__", (PyCFunction)py_imbuf_deepcopy, METH_VARARGS, (char *)py_imbuf_copy_doc},
+ {"resize", (PyCFunction)py_imbuf_resize, METH_VARARGS | METH_KEYWORDS, py_imbuf_resize_doc},
+ {"crop", (PyCFunction)py_imbuf_crop, METH_VARARGS | METH_KEYWORDS, (char *)py_imbuf_crop_doc},
+ {"free", (PyCFunction)py_imbuf_free, METH_NOARGS, py_imbuf_free_doc},
+ {"copy", (PyCFunction)py_imbuf_copy, METH_NOARGS, py_imbuf_copy_doc},
+ {"__copy__", (PyCFunction)py_imbuf_copy, METH_NOARGS, py_imbuf_copy_doc},
+ {"__deepcopy__", (PyCFunction)py_imbuf_deepcopy, METH_VARARGS, py_imbuf_copy_doc},
{NULL, NULL, 0, NULL},
};
diff --git a/source/blender/python/intern/bpy.c b/source/blender/python/intern/bpy.c
index 92ba7704b19..b8a83d0588d 100644
--- a/source/blender/python/intern/bpy.c
+++ b/source/blender/python/intern/bpy.c
@@ -184,6 +184,49 @@ static PyObject *bpy_user_resource(PyObject *UNUSED(self), PyObject *args, PyObj
return PyC_UnicodeFromByte(path ? path : "");
}
+PyDoc_STRVAR(bpy_system_resource_doc,
+ ".. function:: system_resource(type, path=\"\")\n"
+ "\n"
+ " Return a system resource path.\n"
+ "\n"
+ " :arg type: string in ['DATAFILES', 'SCRIPTS', 'PYTHON'].\n"
+ " :type type: string\n"
+ " :arg path: Optional subdirectory.\n"
+ " :type path: string\n");
+static PyObject *bpy_system_resource(PyObject *UNUSED(self), PyObject *args, PyObject *kw)
+{
+ const char *type;
+ const char *subdir = NULL;
+ int folder_id;
+
+ const char *path;
+
+ static const char *_keywords[] = {"type", "path", NULL};
+ static _PyArg_Parser _parser = {"s|s:system_resource", _keywords, 0};
+ if (!_PyArg_ParseTupleAndKeywordsFast(args, kw, &_parser, &type, &subdir)) {
+ return NULL;
+ }
+
+ /* stupid string compare */
+ if (STREQ(type, "DATAFILES")) {
+ folder_id = BLENDER_SYSTEM_DATAFILES;
+ }
+ else if (STREQ(type, "SCRIPTS")) {
+ folder_id = BLENDER_SYSTEM_SCRIPTS;
+ }
+ else if (STREQ(type, "PYTHON")) {
+ folder_id = BLENDER_SYSTEM_PYTHON;
+ }
+ else {
+ PyErr_SetString(PyExc_ValueError, "invalid resource argument");
+ return NULL;
+ }
+
+ path = BKE_appdir_folder_id(folder_id, subdir);
+
+ return PyC_UnicodeFromByte(path ? path : "");
+}
+
PyDoc_STRVAR(
bpy_resource_path_doc,
".. function:: resource_path(type, major=bpy.app.version[0], minor=bpy.app.version[1])\n"
@@ -292,6 +335,12 @@ static PyMethodDef meth_bpy_user_resource = {
METH_VARARGS | METH_KEYWORDS,
NULL,
};
+static PyMethodDef meth_bpy_system_resource = {
+ "system_resource",
+ (PyCFunction)bpy_system_resource,
+ METH_VARARGS | METH_KEYWORDS,
+ bpy_system_resource_doc,
+};
static PyMethodDef meth_bpy_resource_path = {
"resource_path",
(PyCFunction)bpy_resource_path,
@@ -398,6 +447,9 @@ void BPy_init_modules(void)
meth_bpy_user_resource.ml_name,
(PyObject *)PyCFunction_New(&meth_bpy_user_resource, NULL));
PyModule_AddObject(mod,
+ meth_bpy_system_resource.ml_name,
+ (PyObject *)PyCFunction_New(&meth_bpy_system_resource, NULL));
+ PyModule_AddObject(mod,
meth_bpy_resource_path.ml_name,
(PyObject *)PyCFunction_New(&meth_bpy_resource_path, NULL));
PyModule_AddObject(mod,
diff --git a/source/blender/python/intern/bpy_interface.c b/source/blender/python/intern/bpy_interface.c
index b34a41b5af6..71bc01d6b98 100644
--- a/source/blender/python/intern/bpy_interface.c
+++ b/source/blender/python/intern/bpy_interface.c
@@ -457,7 +457,7 @@ static bool python_script_exec(
fn_dummy_py = PyC_UnicodeFromByte(fn_dummy);
- buf = txt_to_buf(text);
+ buf = txt_to_buf(text, NULL);
text->compiled = Py_CompileStringObject(buf, fn_dummy_py, Py_file_input, NULL, -1);
MEM_freeN(buf);
diff --git a/source/blender/python/mathutils/mathutils_Vector.c b/source/blender/python/mathutils/mathutils_Vector.c
index 29861c56dc0..2c9a25d24bc 100644
--- a/source/blender/python/mathutils/mathutils_Vector.c
+++ b/source/blender/python/mathutils/mathutils_Vector.c
@@ -1386,7 +1386,7 @@ static PyObject *vector_item_internal(VectorObject *self, int i, const bool is_a
if (is_attr) {
PyErr_Format(PyExc_AttributeError,
"Vector.%c: unavailable on %dd vector",
- *(((char *)"xyzw") + i),
+ *(((const char *)"xyzw") + i),
self->size);
}
else {
@@ -1415,8 +1415,8 @@ static int vector_ass_item_internal(VectorObject *self, int i, PyObject *value,
return -1;
}
- if ((scalar = PyFloat_AsDouble(value)) == -1.0f &&
- PyErr_Occurred()) { /* parsed item not a number */
+ if ((scalar = PyFloat_AsDouble(value)) == -1.0f && PyErr_Occurred()) {
+ /* parsed item not a number */
PyErr_SetString(PyExc_TypeError,
"vector[index] = x: "
"assigned value not a number");
@@ -1431,7 +1431,7 @@ static int vector_ass_item_internal(VectorObject *self, int i, PyObject *value,
if (is_attr) {
PyErr_Format(PyExc_AttributeError,
"Vector.%c = x: unavailable on %dd vector",
- *(((char *)"xyzw") + i),
+ *(((const char *)"xyzw") + i),
self->size);
}
else {
@@ -1950,8 +1950,8 @@ static PyObject *Vector_div(PyObject *v1, PyObject *v2)
return NULL;
}
- if ((scalar = PyFloat_AsDouble(v2)) == -1.0f &&
- PyErr_Occurred()) { /* parsed item not a number */
+ if ((scalar = PyFloat_AsDouble(v2)) == -1.0f && PyErr_Occurred()) {
+ /* parsed item not a number */
PyErr_SetString(PyExc_TypeError,
"Vector division: "
"Vector must be divided by a float");
@@ -1989,8 +1989,8 @@ static PyObject *Vector_idiv(PyObject *v1, PyObject *v2)
return NULL;
}
- if ((scalar = PyFloat_AsDouble(v2)) == -1.0f &&
- PyErr_Occurred()) { /* parsed item not a number */
+ if ((scalar = PyFloat_AsDouble(v2)) == -1.0f && PyErr_Occurred()) {
+ /* parsed item not a number */
PyErr_SetString(PyExc_TypeError,
"Vector division: "
"Vector must be divided by a float");
@@ -2392,7 +2392,7 @@ static PyObject *Vector_length_squared_get(VectorObject *self, void *UNUSED(clos
* num = eval(val)
* set_str = 'Vector_swizzle_set' if (len(set(key)) == len(key)) else 'NULL'
* key_args = ', '.join(["'%s'" % c for c in key.upper()])
- * print('\t{(char *)"%s", %s(getter)Vector_swizzle_get, (setter)%s, NULL, SWIZZLE%d(%s)},' %
+ * print('\t{"%s", %s(getter)Vector_swizzle_get, (setter)%s, NULL, SWIZZLE%d(%s)},' %
* (key, (' ' * (4 - len(key))), set_str, len(key), key_args))
* unique.add(num)
*
@@ -2544,570 +2544,366 @@ static int Vector_swizzle_set(VectorObject *self, PyObject *value, void *closure
/* Python attributes get/set structure: */
/*****************************************************************************/
static PyGetSetDef Vector_getseters[] = {
- {(char *)"x", (getter)Vector_axis_get, (setter)Vector_axis_set, Vector_axis_x_doc, (void *)0},
- {(char *)"y", (getter)Vector_axis_get, (setter)Vector_axis_set, Vector_axis_y_doc, (void *)1},
- {(char *)"z", (getter)Vector_axis_get, (setter)Vector_axis_set, Vector_axis_z_doc, (void *)2},
- {(char *)"w", (getter)Vector_axis_get, (setter)Vector_axis_set, Vector_axis_w_doc, (void *)3},
- {(char *)"length",
- (getter)Vector_length_get,
- (setter)Vector_length_set,
- Vector_length_doc,
- NULL},
- {(char *)"length_squared",
+ {"x", (getter)Vector_axis_get, (setter)Vector_axis_set, Vector_axis_x_doc, (void *)0},
+ {"y", (getter)Vector_axis_get, (setter)Vector_axis_set, Vector_axis_y_doc, (void *)1},
+ {"z", (getter)Vector_axis_get, (setter)Vector_axis_set, Vector_axis_z_doc, (void *)2},
+ {"w", (getter)Vector_axis_get, (setter)Vector_axis_set, Vector_axis_w_doc, (void *)3},
+ {"length", (getter)Vector_length_get, (setter)Vector_length_set, Vector_length_doc, NULL},
+ {"length_squared",
(getter)Vector_length_squared_get,
(setter)NULL,
Vector_length_squared_doc,
NULL},
- {(char *)"magnitude",
- (getter)Vector_length_get,
- (setter)Vector_length_set,
- Vector_length_doc,
- NULL},
- {(char *)"is_wrapped",
+ {"magnitude", (getter)Vector_length_get, (setter)Vector_length_set, Vector_length_doc, NULL},
+ {"is_wrapped",
(getter)BaseMathObject_is_wrapped_get,
(setter)NULL,
BaseMathObject_is_wrapped_doc,
NULL},
- {(char *)"is_frozen",
+ {"is_frozen",
(getter)BaseMathObject_is_frozen_get,
(setter)NULL,
BaseMathObject_is_frozen_doc,
NULL},
- {(char *)"owner",
- (getter)BaseMathObject_owner_get,
- (setter)NULL,
- BaseMathObject_owner_doc,
- NULL},
+ {"owner", (getter)BaseMathObject_owner_get, (setter)NULL, BaseMathObject_owner_doc, NULL},
/* autogenerated swizzle attrs, see Python script above */
- {(char *)"xx", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE2(0, 0)},
- {(char *)"xxx", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE3(0, 0, 0)},
- {(char *)"xxxx", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(0, 0, 0, 0)},
- {(char *)"xxxy", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(0, 0, 0, 1)},
- {(char *)"xxxz", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(0, 0, 0, 2)},
- {(char *)"xxxw", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(0, 0, 0, 3)},
- {(char *)"xxy", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE3(0, 0, 1)},
- {(char *)"xxyx", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(0, 0, 1, 0)},
- {(char *)"xxyy", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(0, 0, 1, 1)},
- {(char *)"xxyz", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(0, 0, 1, 2)},
- {(char *)"xxyw", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(0, 0, 1, 3)},
- {(char *)"xxz", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE3(0, 0, 2)},
- {(char *)"xxzx", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(0, 0, 2, 0)},
- {(char *)"xxzy", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(0, 0, 2, 1)},
- {(char *)"xxzz", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(0, 0, 2, 2)},
- {(char *)"xxzw", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(0, 0, 2, 3)},
- {(char *)"xxw", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE3(0, 0, 3)},
- {(char *)"xxwx", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(0, 0, 3, 0)},
- {(char *)"xxwy", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(0, 0, 3, 1)},
- {(char *)"xxwz", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(0, 0, 3, 2)},
- {(char *)"xxww", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(0, 0, 3, 3)},
- {(char *)"xy", (getter)Vector_swizzle_get, (setter)Vector_swizzle_set, NULL, SWIZZLE2(0, 1)},
- {(char *)"xyx", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE3(0, 1, 0)},
- {(char *)"xyxx", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(0, 1, 0, 0)},
- {(char *)"xyxy", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(0, 1, 0, 1)},
- {(char *)"xyxz", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(0, 1, 0, 2)},
- {(char *)"xyxw", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(0, 1, 0, 3)},
- {(char *)"xyy", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE3(0, 1, 1)},
- {(char *)"xyyx", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(0, 1, 1, 0)},
- {(char *)"xyyy", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(0, 1, 1, 1)},
- {(char *)"xyyz", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(0, 1, 1, 2)},
- {(char *)"xyyw", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(0, 1, 1, 3)},
- {(char *)"xyz",
- (getter)Vector_swizzle_get,
- (setter)Vector_swizzle_set,
- NULL,
- SWIZZLE3(0, 1, 2)},
- {(char *)"xyzx", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(0, 1, 2, 0)},
- {(char *)"xyzy", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(0, 1, 2, 1)},
- {(char *)"xyzz", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(0, 1, 2, 2)},
- {(char *)"xyzw",
- (getter)Vector_swizzle_get,
- (setter)Vector_swizzle_set,
- NULL,
- SWIZZLE4(0, 1, 2, 3)},
- {(char *)"xyw",
- (getter)Vector_swizzle_get,
- (setter)Vector_swizzle_set,
- NULL,
- SWIZZLE3(0, 1, 3)},
- {(char *)"xywx", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(0, 1, 3, 0)},
- {(char *)"xywy", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(0, 1, 3, 1)},
- {(char *)"xywz",
- (getter)Vector_swizzle_get,
- (setter)Vector_swizzle_set,
- NULL,
- SWIZZLE4(0, 1, 3, 2)},
- {(char *)"xyww", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(0, 1, 3, 3)},
- {(char *)"xz", (getter)Vector_swizzle_get, (setter)Vector_swizzle_set, NULL, SWIZZLE2(0, 2)},
- {(char *)"xzx", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE3(0, 2, 0)},
- {(char *)"xzxx", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(0, 2, 0, 0)},
- {(char *)"xzxy", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(0, 2, 0, 1)},
- {(char *)"xzxz", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(0, 2, 0, 2)},
- {(char *)"xzxw", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(0, 2, 0, 3)},
- {(char *)"xzy",
- (getter)Vector_swizzle_get,
- (setter)Vector_swizzle_set,
- NULL,
- SWIZZLE3(0, 2, 1)},
- {(char *)"xzyx", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(0, 2, 1, 0)},
- {(char *)"xzyy", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(0, 2, 1, 1)},
- {(char *)"xzyz", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(0, 2, 1, 2)},
- {(char *)"xzyw",
- (getter)Vector_swizzle_get,
- (setter)Vector_swizzle_set,
- NULL,
- SWIZZLE4(0, 2, 1, 3)},
- {(char *)"xzz", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE3(0, 2, 2)},
- {(char *)"xzzx", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(0, 2, 2, 0)},
- {(char *)"xzzy", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(0, 2, 2, 1)},
- {(char *)"xzzz", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(0, 2, 2, 2)},
- {(char *)"xzzw", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(0, 2, 2, 3)},
- {(char *)"xzw",
- (getter)Vector_swizzle_get,
- (setter)Vector_swizzle_set,
- NULL,
- SWIZZLE3(0, 2, 3)},
- {(char *)"xzwx", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(0, 2, 3, 0)},
- {(char *)"xzwy",
- (getter)Vector_swizzle_get,
- (setter)Vector_swizzle_set,
- NULL,
- SWIZZLE4(0, 2, 3, 1)},
- {(char *)"xzwz", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(0, 2, 3, 2)},
- {(char *)"xzww", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(0, 2, 3, 3)},
- {(char *)"xw", (getter)Vector_swizzle_get, (setter)Vector_swizzle_set, NULL, SWIZZLE2(0, 3)},
- {(char *)"xwx", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE3(0, 3, 0)},
- {(char *)"xwxx", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(0, 3, 0, 0)},
- {(char *)"xwxy", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(0, 3, 0, 1)},
- {(char *)"xwxz", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(0, 3, 0, 2)},
- {(char *)"xwxw", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(0, 3, 0, 3)},
- {(char *)"xwy",
- (getter)Vector_swizzle_get,
- (setter)Vector_swizzle_set,
- NULL,
- SWIZZLE3(0, 3, 1)},
- {(char *)"xwyx", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(0, 3, 1, 0)},
- {(char *)"xwyy", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(0, 3, 1, 1)},
- {(char *)"xwyz",
- (getter)Vector_swizzle_get,
- (setter)Vector_swizzle_set,
- NULL,
- SWIZZLE4(0, 3, 1, 2)},
- {(char *)"xwyw", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(0, 3, 1, 3)},
- {(char *)"xwz",
- (getter)Vector_swizzle_get,
- (setter)Vector_swizzle_set,
- NULL,
- SWIZZLE3(0, 3, 2)},
- {(char *)"xwzx", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(0, 3, 2, 0)},
- {(char *)"xwzy",
- (getter)Vector_swizzle_get,
- (setter)Vector_swizzle_set,
- NULL,
- SWIZZLE4(0, 3, 2, 1)},
- {(char *)"xwzz", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(0, 3, 2, 2)},
- {(char *)"xwzw", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(0, 3, 2, 3)},
- {(char *)"xww", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE3(0, 3, 3)},
- {(char *)"xwwx", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(0, 3, 3, 0)},
- {(char *)"xwwy", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(0, 3, 3, 1)},
- {(char *)"xwwz", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(0, 3, 3, 2)},
- {(char *)"xwww", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(0, 3, 3, 3)},
- {(char *)"yx", (getter)Vector_swizzle_get, (setter)Vector_swizzle_set, NULL, SWIZZLE2(1, 0)},
- {(char *)"yxx", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE3(1, 0, 0)},
- {(char *)"yxxx", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(1, 0, 0, 0)},
- {(char *)"yxxy", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(1, 0, 0, 1)},
- {(char *)"yxxz", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(1, 0, 0, 2)},
- {(char *)"yxxw", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(1, 0, 0, 3)},
- {(char *)"yxy", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE3(1, 0, 1)},
- {(char *)"yxyx", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(1, 0, 1, 0)},
- {(char *)"yxyy", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(1, 0, 1, 1)},
- {(char *)"yxyz", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(1, 0, 1, 2)},
- {(char *)"yxyw", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(1, 0, 1, 3)},
- {(char *)"yxz",
- (getter)Vector_swizzle_get,
- (setter)Vector_swizzle_set,
- NULL,
- SWIZZLE3(1, 0, 2)},
- {(char *)"yxzx", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(1, 0, 2, 0)},
- {(char *)"yxzy", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(1, 0, 2, 1)},
- {(char *)"yxzz", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(1, 0, 2, 2)},
- {(char *)"yxzw",
- (getter)Vector_swizzle_get,
- (setter)Vector_swizzle_set,
- NULL,
- SWIZZLE4(1, 0, 2, 3)},
- {(char *)"yxw",
- (getter)Vector_swizzle_get,
- (setter)Vector_swizzle_set,
- NULL,
- SWIZZLE3(1, 0, 3)},
- {(char *)"yxwx", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(1, 0, 3, 0)},
- {(char *)"yxwy", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(1, 0, 3, 1)},
- {(char *)"yxwz",
- (getter)Vector_swizzle_get,
- (setter)Vector_swizzle_set,
- NULL,
- SWIZZLE4(1, 0, 3, 2)},
- {(char *)"yxww", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(1, 0, 3, 3)},
- {(char *)"yy", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE2(1, 1)},
- {(char *)"yyx", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE3(1, 1, 0)},
- {(char *)"yyxx", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(1, 1, 0, 0)},
- {(char *)"yyxy", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(1, 1, 0, 1)},
- {(char *)"yyxz", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(1, 1, 0, 2)},
- {(char *)"yyxw", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(1, 1, 0, 3)},
- {(char *)"yyy", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE3(1, 1, 1)},
- {(char *)"yyyx", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(1, 1, 1, 0)},
- {(char *)"yyyy", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(1, 1, 1, 1)},
- {(char *)"yyyz", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(1, 1, 1, 2)},
- {(char *)"yyyw", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(1, 1, 1, 3)},
- {(char *)"yyz", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE3(1, 1, 2)},
- {(char *)"yyzx", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(1, 1, 2, 0)},
- {(char *)"yyzy", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(1, 1, 2, 1)},
- {(char *)"yyzz", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(1, 1, 2, 2)},
- {(char *)"yyzw", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(1, 1, 2, 3)},
- {(char *)"yyw", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE3(1, 1, 3)},
- {(char *)"yywx", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(1, 1, 3, 0)},
- {(char *)"yywy", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(1, 1, 3, 1)},
- {(char *)"yywz", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(1, 1, 3, 2)},
- {(char *)"yyww", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(1, 1, 3, 3)},
- {(char *)"yz", (getter)Vector_swizzle_get, (setter)Vector_swizzle_set, NULL, SWIZZLE2(1, 2)},
- {(char *)"yzx",
- (getter)Vector_swizzle_get,
- (setter)Vector_swizzle_set,
- NULL,
- SWIZZLE3(1, 2, 0)},
- {(char *)"yzxx", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(1, 2, 0, 0)},
- {(char *)"yzxy", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(1, 2, 0, 1)},
- {(char *)"yzxz", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(1, 2, 0, 2)},
- {(char *)"yzxw",
- (getter)Vector_swizzle_get,
- (setter)Vector_swizzle_set,
- NULL,
- SWIZZLE4(1, 2, 0, 3)},
- {(char *)"yzy", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE3(1, 2, 1)},
- {(char *)"yzyx", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(1, 2, 1, 0)},
- {(char *)"yzyy", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(1, 2, 1, 1)},
- {(char *)"yzyz", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(1, 2, 1, 2)},
- {(char *)"yzyw", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(1, 2, 1, 3)},
- {(char *)"yzz", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE3(1, 2, 2)},
- {(char *)"yzzx", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(1, 2, 2, 0)},
- {(char *)"yzzy", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(1, 2, 2, 1)},
- {(char *)"yzzz", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(1, 2, 2, 2)},
- {(char *)"yzzw", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(1, 2, 2, 3)},
- {(char *)"yzw",
- (getter)Vector_swizzle_get,
- (setter)Vector_swizzle_set,
- NULL,
- SWIZZLE3(1, 2, 3)},
- {(char *)"yzwx",
- (getter)Vector_swizzle_get,
- (setter)Vector_swizzle_set,
- NULL,
- SWIZZLE4(1, 2, 3, 0)},
- {(char *)"yzwy", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(1, 2, 3, 1)},
- {(char *)"yzwz", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(1, 2, 3, 2)},
- {(char *)"yzww", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(1, 2, 3, 3)},
- {(char *)"yw", (getter)Vector_swizzle_get, (setter)Vector_swizzle_set, NULL, SWIZZLE2(1, 3)},
- {(char *)"ywx",
- (getter)Vector_swizzle_get,
- (setter)Vector_swizzle_set,
- NULL,
- SWIZZLE3(1, 3, 0)},
- {(char *)"ywxx", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(1, 3, 0, 0)},
- {(char *)"ywxy", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(1, 3, 0, 1)},
- {(char *)"ywxz",
- (getter)Vector_swizzle_get,
- (setter)Vector_swizzle_set,
- NULL,
- SWIZZLE4(1, 3, 0, 2)},
- {(char *)"ywxw", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(1, 3, 0, 3)},
- {(char *)"ywy", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE3(1, 3, 1)},
- {(char *)"ywyx", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(1, 3, 1, 0)},
- {(char *)"ywyy", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(1, 3, 1, 1)},
- {(char *)"ywyz", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(1, 3, 1, 2)},
- {(char *)"ywyw", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(1, 3, 1, 3)},
- {(char *)"ywz",
- (getter)Vector_swizzle_get,
- (setter)Vector_swizzle_set,
- NULL,
- SWIZZLE3(1, 3, 2)},
- {(char *)"ywzx",
- (getter)Vector_swizzle_get,
- (setter)Vector_swizzle_set,
- NULL,
- SWIZZLE4(1, 3, 2, 0)},
- {(char *)"ywzy", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(1, 3, 2, 1)},
- {(char *)"ywzz", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(1, 3, 2, 2)},
- {(char *)"ywzw", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(1, 3, 2, 3)},
- {(char *)"yww", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE3(1, 3, 3)},
- {(char *)"ywwx", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(1, 3, 3, 0)},
- {(char *)"ywwy", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(1, 3, 3, 1)},
- {(char *)"ywwz", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(1, 3, 3, 2)},
- {(char *)"ywww", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(1, 3, 3, 3)},
- {(char *)"zx", (getter)Vector_swizzle_get, (setter)Vector_swizzle_set, NULL, SWIZZLE2(2, 0)},
- {(char *)"zxx", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE3(2, 0, 0)},
- {(char *)"zxxx", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(2, 0, 0, 0)},
- {(char *)"zxxy", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(2, 0, 0, 1)},
- {(char *)"zxxz", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(2, 0, 0, 2)},
- {(char *)"zxxw", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(2, 0, 0, 3)},
- {(char *)"zxy",
- (getter)Vector_swizzle_get,
- (setter)Vector_swizzle_set,
- NULL,
- SWIZZLE3(2, 0, 1)},
- {(char *)"zxyx", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(2, 0, 1, 0)},
- {(char *)"zxyy", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(2, 0, 1, 1)},
- {(char *)"zxyz", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(2, 0, 1, 2)},
- {(char *)"zxyw",
- (getter)Vector_swizzle_get,
- (setter)Vector_swizzle_set,
- NULL,
- SWIZZLE4(2, 0, 1, 3)},
- {(char *)"zxz", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE3(2, 0, 2)},
- {(char *)"zxzx", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(2, 0, 2, 0)},
- {(char *)"zxzy", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(2, 0, 2, 1)},
- {(char *)"zxzz", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(2, 0, 2, 2)},
- {(char *)"zxzw", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(2, 0, 2, 3)},
- {(char *)"zxw",
- (getter)Vector_swizzle_get,
- (setter)Vector_swizzle_set,
- NULL,
- SWIZZLE3(2, 0, 3)},
- {(char *)"zxwx", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(2, 0, 3, 0)},
- {(char *)"zxwy",
- (getter)Vector_swizzle_get,
- (setter)Vector_swizzle_set,
- NULL,
- SWIZZLE4(2, 0, 3, 1)},
- {(char *)"zxwz", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(2, 0, 3, 2)},
- {(char *)"zxww", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(2, 0, 3, 3)},
- {(char *)"zy", (getter)Vector_swizzle_get, (setter)Vector_swizzle_set, NULL, SWIZZLE2(2, 1)},
- {(char *)"zyx",
- (getter)Vector_swizzle_get,
- (setter)Vector_swizzle_set,
- NULL,
- SWIZZLE3(2, 1, 0)},
- {(char *)"zyxx", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(2, 1, 0, 0)},
- {(char *)"zyxy", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(2, 1, 0, 1)},
- {(char *)"zyxz", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(2, 1, 0, 2)},
- {(char *)"zyxw",
- (getter)Vector_swizzle_get,
- (setter)Vector_swizzle_set,
- NULL,
- SWIZZLE4(2, 1, 0, 3)},
- {(char *)"zyy", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE3(2, 1, 1)},
- {(char *)"zyyx", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(2, 1, 1, 0)},
- {(char *)"zyyy", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(2, 1, 1, 1)},
- {(char *)"zyyz", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(2, 1, 1, 2)},
- {(char *)"zyyw", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(2, 1, 1, 3)},
- {(char *)"zyz", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE3(2, 1, 2)},
- {(char *)"zyzx", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(2, 1, 2, 0)},
- {(char *)"zyzy", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(2, 1, 2, 1)},
- {(char *)"zyzz", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(2, 1, 2, 2)},
- {(char *)"zyzw", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(2, 1, 2, 3)},
- {(char *)"zyw",
- (getter)Vector_swizzle_get,
- (setter)Vector_swizzle_set,
- NULL,
- SWIZZLE3(2, 1, 3)},
- {(char *)"zywx",
- (getter)Vector_swizzle_get,
- (setter)Vector_swizzle_set,
- NULL,
- SWIZZLE4(2, 1, 3, 0)},
- {(char *)"zywy", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(2, 1, 3, 1)},
- {(char *)"zywz", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(2, 1, 3, 2)},
- {(char *)"zyww", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(2, 1, 3, 3)},
- {(char *)"zz", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE2(2, 2)},
- {(char *)"zzx", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE3(2, 2, 0)},
- {(char *)"zzxx", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(2, 2, 0, 0)},
- {(char *)"zzxy", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(2, 2, 0, 1)},
- {(char *)"zzxz", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(2, 2, 0, 2)},
- {(char *)"zzxw", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(2, 2, 0, 3)},
- {(char *)"zzy", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE3(2, 2, 1)},
- {(char *)"zzyx", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(2, 2, 1, 0)},
- {(char *)"zzyy", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(2, 2, 1, 1)},
- {(char *)"zzyz", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(2, 2, 1, 2)},
- {(char *)"zzyw", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(2, 2, 1, 3)},
- {(char *)"zzz", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE3(2, 2, 2)},
- {(char *)"zzzx", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(2, 2, 2, 0)},
- {(char *)"zzzy", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(2, 2, 2, 1)},
- {(char *)"zzzz", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(2, 2, 2, 2)},
- {(char *)"zzzw", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(2, 2, 2, 3)},
- {(char *)"zzw", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE3(2, 2, 3)},
- {(char *)"zzwx", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(2, 2, 3, 0)},
- {(char *)"zzwy", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(2, 2, 3, 1)},
- {(char *)"zzwz", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(2, 2, 3, 2)},
- {(char *)"zzww", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(2, 2, 3, 3)},
- {(char *)"zw", (getter)Vector_swizzle_get, (setter)Vector_swizzle_set, NULL, SWIZZLE2(2, 3)},
- {(char *)"zwx",
- (getter)Vector_swizzle_get,
- (setter)Vector_swizzle_set,
- NULL,
- SWIZZLE3(2, 3, 0)},
- {(char *)"zwxx", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(2, 3, 0, 0)},
- {(char *)"zwxy",
- (getter)Vector_swizzle_get,
- (setter)Vector_swizzle_set,
- NULL,
- SWIZZLE4(2, 3, 0, 1)},
- {(char *)"zwxz", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(2, 3, 0, 2)},
- {(char *)"zwxw", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(2, 3, 0, 3)},
- {(char *)"zwy",
- (getter)Vector_swizzle_get,
- (setter)Vector_swizzle_set,
- NULL,
- SWIZZLE3(2, 3, 1)},
- {(char *)"zwyx",
- (getter)Vector_swizzle_get,
- (setter)Vector_swizzle_set,
- NULL,
- SWIZZLE4(2, 3, 1, 0)},
- {(char *)"zwyy", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(2, 3, 1, 1)},
- {(char *)"zwyz", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(2, 3, 1, 2)},
- {(char *)"zwyw", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(2, 3, 1, 3)},
- {(char *)"zwz", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE3(2, 3, 2)},
- {(char *)"zwzx", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(2, 3, 2, 0)},
- {(char *)"zwzy", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(2, 3, 2, 1)},
- {(char *)"zwzz", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(2, 3, 2, 2)},
- {(char *)"zwzw", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(2, 3, 2, 3)},
- {(char *)"zww", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE3(2, 3, 3)},
- {(char *)"zwwx", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(2, 3, 3, 0)},
- {(char *)"zwwy", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(2, 3, 3, 1)},
- {(char *)"zwwz", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(2, 3, 3, 2)},
- {(char *)"zwww", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(2, 3, 3, 3)},
- {(char *)"wx", (getter)Vector_swizzle_get, (setter)Vector_swizzle_set, NULL, SWIZZLE2(3, 0)},
- {(char *)"wxx", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE3(3, 0, 0)},
- {(char *)"wxxx", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(3, 0, 0, 0)},
- {(char *)"wxxy", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(3, 0, 0, 1)},
- {(char *)"wxxz", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(3, 0, 0, 2)},
- {(char *)"wxxw", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(3, 0, 0, 3)},
- {(char *)"wxy",
- (getter)Vector_swizzle_get,
- (setter)Vector_swizzle_set,
- NULL,
- SWIZZLE3(3, 0, 1)},
- {(char *)"wxyx", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(3, 0, 1, 0)},
- {(char *)"wxyy", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(3, 0, 1, 1)},
- {(char *)"wxyz",
- (getter)Vector_swizzle_get,
- (setter)Vector_swizzle_set,
- NULL,
- SWIZZLE4(3, 0, 1, 2)},
- {(char *)"wxyw", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(3, 0, 1, 3)},
- {(char *)"wxz",
- (getter)Vector_swizzle_get,
- (setter)Vector_swizzle_set,
- NULL,
- SWIZZLE3(3, 0, 2)},
- {(char *)"wxzx", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(3, 0, 2, 0)},
- {(char *)"wxzy",
- (getter)Vector_swizzle_get,
- (setter)Vector_swizzle_set,
- NULL,
- SWIZZLE4(3, 0, 2, 1)},
- {(char *)"wxzz", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(3, 0, 2, 2)},
- {(char *)"wxzw", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(3, 0, 2, 3)},
- {(char *)"wxw", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE3(3, 0, 3)},
- {(char *)"wxwx", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(3, 0, 3, 0)},
- {(char *)"wxwy", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(3, 0, 3, 1)},
- {(char *)"wxwz", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(3, 0, 3, 2)},
- {(char *)"wxww", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(3, 0, 3, 3)},
- {(char *)"wy", (getter)Vector_swizzle_get, (setter)Vector_swizzle_set, NULL, SWIZZLE2(3, 1)},
- {(char *)"wyx",
- (getter)Vector_swizzle_get,
- (setter)Vector_swizzle_set,
- NULL,
- SWIZZLE3(3, 1, 0)},
- {(char *)"wyxx", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(3, 1, 0, 0)},
- {(char *)"wyxy", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(3, 1, 0, 1)},
- {(char *)"wyxz",
- (getter)Vector_swizzle_get,
- (setter)Vector_swizzle_set,
- NULL,
- SWIZZLE4(3, 1, 0, 2)},
- {(char *)"wyxw", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(3, 1, 0, 3)},
- {(char *)"wyy", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE3(3, 1, 1)},
- {(char *)"wyyx", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(3, 1, 1, 0)},
- {(char *)"wyyy", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(3, 1, 1, 1)},
- {(char *)"wyyz", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(3, 1, 1, 2)},
- {(char *)"wyyw", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(3, 1, 1, 3)},
- {(char *)"wyz",
- (getter)Vector_swizzle_get,
- (setter)Vector_swizzle_set,
- NULL,
- SWIZZLE3(3, 1, 2)},
- {(char *)"wyzx",
- (getter)Vector_swizzle_get,
- (setter)Vector_swizzle_set,
- NULL,
- SWIZZLE4(3, 1, 2, 0)},
- {(char *)"wyzy", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(3, 1, 2, 1)},
- {(char *)"wyzz", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(3, 1, 2, 2)},
- {(char *)"wyzw", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(3, 1, 2, 3)},
- {(char *)"wyw", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE3(3, 1, 3)},
- {(char *)"wywx", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(3, 1, 3, 0)},
- {(char *)"wywy", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(3, 1, 3, 1)},
- {(char *)"wywz", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(3, 1, 3, 2)},
- {(char *)"wyww", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(3, 1, 3, 3)},
- {(char *)"wz", (getter)Vector_swizzle_get, (setter)Vector_swizzle_set, NULL, SWIZZLE2(3, 2)},
- {(char *)"wzx",
- (getter)Vector_swizzle_get,
- (setter)Vector_swizzle_set,
- NULL,
- SWIZZLE3(3, 2, 0)},
- {(char *)"wzxx", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(3, 2, 0, 0)},
- {(char *)"wzxy",
- (getter)Vector_swizzle_get,
- (setter)Vector_swizzle_set,
- NULL,
- SWIZZLE4(3, 2, 0, 1)},
- {(char *)"wzxz", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(3, 2, 0, 2)},
- {(char *)"wzxw", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(3, 2, 0, 3)},
- {(char *)"wzy",
- (getter)Vector_swizzle_get,
- (setter)Vector_swizzle_set,
- NULL,
- SWIZZLE3(3, 2, 1)},
- {(char *)"wzyx",
- (getter)Vector_swizzle_get,
- (setter)Vector_swizzle_set,
- NULL,
- SWIZZLE4(3, 2, 1, 0)},
- {(char *)"wzyy", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(3, 2, 1, 1)},
- {(char *)"wzyz", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(3, 2, 1, 2)},
- {(char *)"wzyw", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(3, 2, 1, 3)},
- {(char *)"wzz", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE3(3, 2, 2)},
- {(char *)"wzzx", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(3, 2, 2, 0)},
- {(char *)"wzzy", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(3, 2, 2, 1)},
- {(char *)"wzzz", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(3, 2, 2, 2)},
- {(char *)"wzzw", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(3, 2, 2, 3)},
- {(char *)"wzw", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE3(3, 2, 3)},
- {(char *)"wzwx", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(3, 2, 3, 0)},
- {(char *)"wzwy", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(3, 2, 3, 1)},
- {(char *)"wzwz", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(3, 2, 3, 2)},
- {(char *)"wzww", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(3, 2, 3, 3)},
- {(char *)"ww", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE2(3, 3)},
- {(char *)"wwx", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE3(3, 3, 0)},
- {(char *)"wwxx", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(3, 3, 0, 0)},
- {(char *)"wwxy", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(3, 3, 0, 1)},
- {(char *)"wwxz", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(3, 3, 0, 2)},
- {(char *)"wwxw", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(3, 3, 0, 3)},
- {(char *)"wwy", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE3(3, 3, 1)},
- {(char *)"wwyx", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(3, 3, 1, 0)},
- {(char *)"wwyy", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(3, 3, 1, 1)},
- {(char *)"wwyz", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(3, 3, 1, 2)},
- {(char *)"wwyw", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(3, 3, 1, 3)},
- {(char *)"wwz", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE3(3, 3, 2)},
- {(char *)"wwzx", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(3, 3, 2, 0)},
- {(char *)"wwzy", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(3, 3, 2, 1)},
- {(char *)"wwzz", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(3, 3, 2, 2)},
- {(char *)"wwzw", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(3, 3, 2, 3)},
- {(char *)"www", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE3(3, 3, 3)},
- {(char *)"wwwx", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(3, 3, 3, 0)},
- {(char *)"wwwy", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(3, 3, 3, 1)},
- {(char *)"wwwz", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(3, 3, 3, 2)},
- {(char *)"wwww", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(3, 3, 3, 3)},
+ {"xx", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE2(0, 0)},
+ {"xxx", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE3(0, 0, 0)},
+ {"xxxx", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(0, 0, 0, 0)},
+ {"xxxy", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(0, 0, 0, 1)},
+ {"xxxz", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(0, 0, 0, 2)},
+ {"xxxw", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(0, 0, 0, 3)},
+ {"xxy", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE3(0, 0, 1)},
+ {"xxyx", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(0, 0, 1, 0)},
+ {"xxyy", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(0, 0, 1, 1)},
+ {"xxyz", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(0, 0, 1, 2)},
+ {"xxyw", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(0, 0, 1, 3)},
+ {"xxz", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE3(0, 0, 2)},
+ {"xxzx", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(0, 0, 2, 0)},
+ {"xxzy", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(0, 0, 2, 1)},
+ {"xxzz", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(0, 0, 2, 2)},
+ {"xxzw", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(0, 0, 2, 3)},
+ {"xxw", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE3(0, 0, 3)},
+ {"xxwx", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(0, 0, 3, 0)},
+ {"xxwy", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(0, 0, 3, 1)},
+ {"xxwz", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(0, 0, 3, 2)},
+ {"xxww", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(0, 0, 3, 3)},
+ {"xy", (getter)Vector_swizzle_get, (setter)Vector_swizzle_set, NULL, SWIZZLE2(0, 1)},
+ {"xyx", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE3(0, 1, 0)},
+ {"xyxx", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(0, 1, 0, 0)},
+ {"xyxy", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(0, 1, 0, 1)},
+ {"xyxz", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(0, 1, 0, 2)},
+ {"xyxw", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(0, 1, 0, 3)},
+ {"xyy", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE3(0, 1, 1)},
+ {"xyyx", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(0, 1, 1, 0)},
+ {"xyyy", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(0, 1, 1, 1)},
+ {"xyyz", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(0, 1, 1, 2)},
+ {"xyyw", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(0, 1, 1, 3)},
+ {"xyz", (getter)Vector_swizzle_get, (setter)Vector_swizzle_set, NULL, SWIZZLE3(0, 1, 2)},
+ {"xyzx", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(0, 1, 2, 0)},
+ {"xyzy", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(0, 1, 2, 1)},
+ {"xyzz", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(0, 1, 2, 2)},
+ {"xyzw", (getter)Vector_swizzle_get, (setter)Vector_swizzle_set, NULL, SWIZZLE4(0, 1, 2, 3)},
+ {"xyw", (getter)Vector_swizzle_get, (setter)Vector_swizzle_set, NULL, SWIZZLE3(0, 1, 3)},
+ {"xywx", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(0, 1, 3, 0)},
+ {"xywy", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(0, 1, 3, 1)},
+ {"xywz", (getter)Vector_swizzle_get, (setter)Vector_swizzle_set, NULL, SWIZZLE4(0, 1, 3, 2)},
+ {"xyww", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(0, 1, 3, 3)},
+ {"xz", (getter)Vector_swizzle_get, (setter)Vector_swizzle_set, NULL, SWIZZLE2(0, 2)},
+ {"xzx", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE3(0, 2, 0)},
+ {"xzxx", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(0, 2, 0, 0)},
+ {"xzxy", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(0, 2, 0, 1)},
+ {"xzxz", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(0, 2, 0, 2)},
+ {"xzxw", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(0, 2, 0, 3)},
+ {"xzy", (getter)Vector_swizzle_get, (setter)Vector_swizzle_set, NULL, SWIZZLE3(0, 2, 1)},
+ {"xzyx", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(0, 2, 1, 0)},
+ {"xzyy", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(0, 2, 1, 1)},
+ {"xzyz", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(0, 2, 1, 2)},
+ {"xzyw", (getter)Vector_swizzle_get, (setter)Vector_swizzle_set, NULL, SWIZZLE4(0, 2, 1, 3)},
+ {"xzz", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE3(0, 2, 2)},
+ {"xzzx", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(0, 2, 2, 0)},
+ {"xzzy", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(0, 2, 2, 1)},
+ {"xzzz", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(0, 2, 2, 2)},
+ {"xzzw", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(0, 2, 2, 3)},
+ {"xzw", (getter)Vector_swizzle_get, (setter)Vector_swizzle_set, NULL, SWIZZLE3(0, 2, 3)},
+ {"xzwx", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(0, 2, 3, 0)},
+ {"xzwy", (getter)Vector_swizzle_get, (setter)Vector_swizzle_set, NULL, SWIZZLE4(0, 2, 3, 1)},
+ {"xzwz", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(0, 2, 3, 2)},
+ {"xzww", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(0, 2, 3, 3)},
+ {"xw", (getter)Vector_swizzle_get, (setter)Vector_swizzle_set, NULL, SWIZZLE2(0, 3)},
+ {"xwx", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE3(0, 3, 0)},
+ {"xwxx", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(0, 3, 0, 0)},
+ {"xwxy", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(0, 3, 0, 1)},
+ {"xwxz", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(0, 3, 0, 2)},
+ {"xwxw", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(0, 3, 0, 3)},
+ {"xwy", (getter)Vector_swizzle_get, (setter)Vector_swizzle_set, NULL, SWIZZLE3(0, 3, 1)},
+ {"xwyx", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(0, 3, 1, 0)},
+ {"xwyy", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(0, 3, 1, 1)},
+ {"xwyz", (getter)Vector_swizzle_get, (setter)Vector_swizzle_set, NULL, SWIZZLE4(0, 3, 1, 2)},
+ {"xwyw", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(0, 3, 1, 3)},
+ {"xwz", (getter)Vector_swizzle_get, (setter)Vector_swizzle_set, NULL, SWIZZLE3(0, 3, 2)},
+ {"xwzx", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(0, 3, 2, 0)},
+ {"xwzy", (getter)Vector_swizzle_get, (setter)Vector_swizzle_set, NULL, SWIZZLE4(0, 3, 2, 1)},
+ {"xwzz", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(0, 3, 2, 2)},
+ {"xwzw", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(0, 3, 2, 3)},
+ {"xww", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE3(0, 3, 3)},
+ {"xwwx", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(0, 3, 3, 0)},
+ {"xwwy", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(0, 3, 3, 1)},
+ {"xwwz", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(0, 3, 3, 2)},
+ {"xwww", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(0, 3, 3, 3)},
+ {"yx", (getter)Vector_swizzle_get, (setter)Vector_swizzle_set, NULL, SWIZZLE2(1, 0)},
+ {"yxx", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE3(1, 0, 0)},
+ {"yxxx", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(1, 0, 0, 0)},
+ {"yxxy", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(1, 0, 0, 1)},
+ {"yxxz", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(1, 0, 0, 2)},
+ {"yxxw", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(1, 0, 0, 3)},
+ {"yxy", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE3(1, 0, 1)},
+ {"yxyx", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(1, 0, 1, 0)},
+ {"yxyy", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(1, 0, 1, 1)},
+ {"yxyz", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(1, 0, 1, 2)},
+ {"yxyw", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(1, 0, 1, 3)},
+ {"yxz", (getter)Vector_swizzle_get, (setter)Vector_swizzle_set, NULL, SWIZZLE3(1, 0, 2)},
+ {"yxzx", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(1, 0, 2, 0)},
+ {"yxzy", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(1, 0, 2, 1)},
+ {"yxzz", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(1, 0, 2, 2)},
+ {"yxzw", (getter)Vector_swizzle_get, (setter)Vector_swizzle_set, NULL, SWIZZLE4(1, 0, 2, 3)},
+ {"yxw", (getter)Vector_swizzle_get, (setter)Vector_swizzle_set, NULL, SWIZZLE3(1, 0, 3)},
+ {"yxwx", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(1, 0, 3, 0)},
+ {"yxwy", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(1, 0, 3, 1)},
+ {"yxwz", (getter)Vector_swizzle_get, (setter)Vector_swizzle_set, NULL, SWIZZLE4(1, 0, 3, 2)},
+ {"yxww", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(1, 0, 3, 3)},
+ {"yy", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE2(1, 1)},
+ {"yyx", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE3(1, 1, 0)},
+ {"yyxx", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(1, 1, 0, 0)},
+ {"yyxy", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(1, 1, 0, 1)},
+ {"yyxz", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(1, 1, 0, 2)},
+ {"yyxw", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(1, 1, 0, 3)},
+ {"yyy", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE3(1, 1, 1)},
+ {"yyyx", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(1, 1, 1, 0)},
+ {"yyyy", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(1, 1, 1, 1)},
+ {"yyyz", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(1, 1, 1, 2)},
+ {"yyyw", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(1, 1, 1, 3)},
+ {"yyz", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE3(1, 1, 2)},
+ {"yyzx", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(1, 1, 2, 0)},
+ {"yyzy", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(1, 1, 2, 1)},
+ {"yyzz", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(1, 1, 2, 2)},
+ {"yyzw", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(1, 1, 2, 3)},
+ {"yyw", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE3(1, 1, 3)},
+ {"yywx", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(1, 1, 3, 0)},
+ {"yywy", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(1, 1, 3, 1)},
+ {"yywz", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(1, 1, 3, 2)},
+ {"yyww", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(1, 1, 3, 3)},
+ {"yz", (getter)Vector_swizzle_get, (setter)Vector_swizzle_set, NULL, SWIZZLE2(1, 2)},
+ {"yzx", (getter)Vector_swizzle_get, (setter)Vector_swizzle_set, NULL, SWIZZLE3(1, 2, 0)},
+ {"yzxx", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(1, 2, 0, 0)},
+ {"yzxy", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(1, 2, 0, 1)},
+ {"yzxz", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(1, 2, 0, 2)},
+ {"yzxw", (getter)Vector_swizzle_get, (setter)Vector_swizzle_set, NULL, SWIZZLE4(1, 2, 0, 3)},
+ {"yzy", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE3(1, 2, 1)},
+ {"yzyx", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(1, 2, 1, 0)},
+ {"yzyy", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(1, 2, 1, 1)},
+ {"yzyz", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(1, 2, 1, 2)},
+ {"yzyw", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(1, 2, 1, 3)},
+ {"yzz", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE3(1, 2, 2)},
+ {"yzzx", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(1, 2, 2, 0)},
+ {"yzzy", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(1, 2, 2, 1)},
+ {"yzzz", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(1, 2, 2, 2)},
+ {"yzzw", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(1, 2, 2, 3)},
+ {"yzw", (getter)Vector_swizzle_get, (setter)Vector_swizzle_set, NULL, SWIZZLE3(1, 2, 3)},
+ {"yzwx", (getter)Vector_swizzle_get, (setter)Vector_swizzle_set, NULL, SWIZZLE4(1, 2, 3, 0)},
+ {"yzwy", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(1, 2, 3, 1)},
+ {"yzwz", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(1, 2, 3, 2)},
+ {"yzww", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(1, 2, 3, 3)},
+ {"yw", (getter)Vector_swizzle_get, (setter)Vector_swizzle_set, NULL, SWIZZLE2(1, 3)},
+ {"ywx", (getter)Vector_swizzle_get, (setter)Vector_swizzle_set, NULL, SWIZZLE3(1, 3, 0)},
+ {"ywxx", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(1, 3, 0, 0)},
+ {"ywxy", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(1, 3, 0, 1)},
+ {"ywxz", (getter)Vector_swizzle_get, (setter)Vector_swizzle_set, NULL, SWIZZLE4(1, 3, 0, 2)},
+ {"ywxw", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(1, 3, 0, 3)},
+ {"ywy", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE3(1, 3, 1)},
+ {"ywyx", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(1, 3, 1, 0)},
+ {"ywyy", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(1, 3, 1, 1)},
+ {"ywyz", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(1, 3, 1, 2)},
+ {"ywyw", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(1, 3, 1, 3)},
+ {"ywz", (getter)Vector_swizzle_get, (setter)Vector_swizzle_set, NULL, SWIZZLE3(1, 3, 2)},
+ {"ywzx", (getter)Vector_swizzle_get, (setter)Vector_swizzle_set, NULL, SWIZZLE4(1, 3, 2, 0)},
+ {"ywzy", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(1, 3, 2, 1)},
+ {"ywzz", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(1, 3, 2, 2)},
+ {"ywzw", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(1, 3, 2, 3)},
+ {"yww", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE3(1, 3, 3)},
+ {"ywwx", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(1, 3, 3, 0)},
+ {"ywwy", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(1, 3, 3, 1)},
+ {"ywwz", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(1, 3, 3, 2)},
+ {"ywww", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(1, 3, 3, 3)},
+ {"zx", (getter)Vector_swizzle_get, (setter)Vector_swizzle_set, NULL, SWIZZLE2(2, 0)},
+ {"zxx", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE3(2, 0, 0)},
+ {"zxxx", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(2, 0, 0, 0)},
+ {"zxxy", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(2, 0, 0, 1)},
+ {"zxxz", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(2, 0, 0, 2)},
+ {"zxxw", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(2, 0, 0, 3)},
+ {"zxy", (getter)Vector_swizzle_get, (setter)Vector_swizzle_set, NULL, SWIZZLE3(2, 0, 1)},
+ {"zxyx", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(2, 0, 1, 0)},
+ {"zxyy", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(2, 0, 1, 1)},
+ {"zxyz", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(2, 0, 1, 2)},
+ {"zxyw", (getter)Vector_swizzle_get, (setter)Vector_swizzle_set, NULL, SWIZZLE4(2, 0, 1, 3)},
+ {"zxz", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE3(2, 0, 2)},
+ {"zxzx", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(2, 0, 2, 0)},
+ {"zxzy", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(2, 0, 2, 1)},
+ {"zxzz", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(2, 0, 2, 2)},
+ {"zxzw", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(2, 0, 2, 3)},
+ {"zxw", (getter)Vector_swizzle_get, (setter)Vector_swizzle_set, NULL, SWIZZLE3(2, 0, 3)},
+ {"zxwx", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(2, 0, 3, 0)},
+ {"zxwy", (getter)Vector_swizzle_get, (setter)Vector_swizzle_set, NULL, SWIZZLE4(2, 0, 3, 1)},
+ {"zxwz", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(2, 0, 3, 2)},
+ {"zxww", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(2, 0, 3, 3)},
+ {"zy", (getter)Vector_swizzle_get, (setter)Vector_swizzle_set, NULL, SWIZZLE2(2, 1)},
+ {"zyx", (getter)Vector_swizzle_get, (setter)Vector_swizzle_set, NULL, SWIZZLE3(2, 1, 0)},
+ {"zyxx", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(2, 1, 0, 0)},
+ {"zyxy", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(2, 1, 0, 1)},
+ {"zyxz", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(2, 1, 0, 2)},
+ {"zyxw", (getter)Vector_swizzle_get, (setter)Vector_swizzle_set, NULL, SWIZZLE4(2, 1, 0, 3)},
+ {"zyy", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE3(2, 1, 1)},
+ {"zyyx", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(2, 1, 1, 0)},
+ {"zyyy", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(2, 1, 1, 1)},
+ {"zyyz", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(2, 1, 1, 2)},
+ {"zyyw", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(2, 1, 1, 3)},
+ {"zyz", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE3(2, 1, 2)},
+ {"zyzx", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(2, 1, 2, 0)},
+ {"zyzy", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(2, 1, 2, 1)},
+ {"zyzz", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(2, 1, 2, 2)},
+ {"zyzw", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(2, 1, 2, 3)},
+ {"zyw", (getter)Vector_swizzle_get, (setter)Vector_swizzle_set, NULL, SWIZZLE3(2, 1, 3)},
+ {"zywx", (getter)Vector_swizzle_get, (setter)Vector_swizzle_set, NULL, SWIZZLE4(2, 1, 3, 0)},
+ {"zywy", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(2, 1, 3, 1)},
+ {"zywz", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(2, 1, 3, 2)},
+ {"zyww", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(2, 1, 3, 3)},
+ {"zz", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE2(2, 2)},
+ {"zzx", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE3(2, 2, 0)},
+ {"zzxx", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(2, 2, 0, 0)},
+ {"zzxy", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(2, 2, 0, 1)},
+ {"zzxz", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(2, 2, 0, 2)},
+ {"zzxw", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(2, 2, 0, 3)},
+ {"zzy", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE3(2, 2, 1)},
+ {"zzyx", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(2, 2, 1, 0)},
+ {"zzyy", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(2, 2, 1, 1)},
+ {"zzyz", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(2, 2, 1, 2)},
+ {"zzyw", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(2, 2, 1, 3)},
+ {"zzz", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE3(2, 2, 2)},
+ {"zzzx", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(2, 2, 2, 0)},
+ {"zzzy", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(2, 2, 2, 1)},
+ {"zzzz", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(2, 2, 2, 2)},
+ {"zzzw", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(2, 2, 2, 3)},
+ {"zzw", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE3(2, 2, 3)},
+ {"zzwx", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(2, 2, 3, 0)},
+ {"zzwy", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(2, 2, 3, 1)},
+ {"zzwz", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(2, 2, 3, 2)},
+ {"zzww", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(2, 2, 3, 3)},
+ {"zw", (getter)Vector_swizzle_get, (setter)Vector_swizzle_set, NULL, SWIZZLE2(2, 3)},
+ {"zwx", (getter)Vector_swizzle_get, (setter)Vector_swizzle_set, NULL, SWIZZLE3(2, 3, 0)},
+ {"zwxx", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(2, 3, 0, 0)},
+ {"zwxy", (getter)Vector_swizzle_get, (setter)Vector_swizzle_set, NULL, SWIZZLE4(2, 3, 0, 1)},
+ {"zwxz", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(2, 3, 0, 2)},
+ {"zwxw", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(2, 3, 0, 3)},
+ {"zwy", (getter)Vector_swizzle_get, (setter)Vector_swizzle_set, NULL, SWIZZLE3(2, 3, 1)},
+ {"zwyx", (getter)Vector_swizzle_get, (setter)Vector_swizzle_set, NULL, SWIZZLE4(2, 3, 1, 0)},
+ {"zwyy", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(2, 3, 1, 1)},
+ {"zwyz", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(2, 3, 1, 2)},
+ {"zwyw", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(2, 3, 1, 3)},
+ {"zwz", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE3(2, 3, 2)},
+ {"zwzx", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(2, 3, 2, 0)},
+ {"zwzy", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(2, 3, 2, 1)},
+ {"zwzz", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(2, 3, 2, 2)},
+ {"zwzw", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(2, 3, 2, 3)},
+ {"zww", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE3(2, 3, 3)},
+ {"zwwx", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(2, 3, 3, 0)},
+ {"zwwy", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(2, 3, 3, 1)},
+ {"zwwz", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(2, 3, 3, 2)},
+ {"zwww", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(2, 3, 3, 3)},
+ {"wx", (getter)Vector_swizzle_get, (setter)Vector_swizzle_set, NULL, SWIZZLE2(3, 0)},
+ {"wxx", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE3(3, 0, 0)},
+ {"wxxx", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(3, 0, 0, 0)},
+ {"wxxy", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(3, 0, 0, 1)},
+ {"wxxz", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(3, 0, 0, 2)},
+ {"wxxw", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(3, 0, 0, 3)},
+ {"wxy", (getter)Vector_swizzle_get, (setter)Vector_swizzle_set, NULL, SWIZZLE3(3, 0, 1)},
+ {"wxyx", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(3, 0, 1, 0)},
+ {"wxyy", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(3, 0, 1, 1)},
+ {"wxyz", (getter)Vector_swizzle_get, (setter)Vector_swizzle_set, NULL, SWIZZLE4(3, 0, 1, 2)},
+ {"wxyw", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(3, 0, 1, 3)},
+ {"wxz", (getter)Vector_swizzle_get, (setter)Vector_swizzle_set, NULL, SWIZZLE3(3, 0, 2)},
+ {"wxzx", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(3, 0, 2, 0)},
+ {"wxzy", (getter)Vector_swizzle_get, (setter)Vector_swizzle_set, NULL, SWIZZLE4(3, 0, 2, 1)},
+ {"wxzz", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(3, 0, 2, 2)},
+ {"wxzw", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(3, 0, 2, 3)},
+ {"wxw", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE3(3, 0, 3)},
+ {"wxwx", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(3, 0, 3, 0)},
+ {"wxwy", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(3, 0, 3, 1)},
+ {"wxwz", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(3, 0, 3, 2)},
+ {"wxww", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(3, 0, 3, 3)},
+ {"wy", (getter)Vector_swizzle_get, (setter)Vector_swizzle_set, NULL, SWIZZLE2(3, 1)},
+ {"wyx", (getter)Vector_swizzle_get, (setter)Vector_swizzle_set, NULL, SWIZZLE3(3, 1, 0)},
+ {"wyxx", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(3, 1, 0, 0)},
+ {"wyxy", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(3, 1, 0, 1)},
+ {"wyxz", (getter)Vector_swizzle_get, (setter)Vector_swizzle_set, NULL, SWIZZLE4(3, 1, 0, 2)},
+ {"wyxw", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(3, 1, 0, 3)},
+ {"wyy", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE3(3, 1, 1)},
+ {"wyyx", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(3, 1, 1, 0)},
+ {"wyyy", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(3, 1, 1, 1)},
+ {"wyyz", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(3, 1, 1, 2)},
+ {"wyyw", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(3, 1, 1, 3)},
+ {"wyz", (getter)Vector_swizzle_get, (setter)Vector_swizzle_set, NULL, SWIZZLE3(3, 1, 2)},
+ {"wyzx", (getter)Vector_swizzle_get, (setter)Vector_swizzle_set, NULL, SWIZZLE4(3, 1, 2, 0)},
+ {"wyzy", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(3, 1, 2, 1)},
+ {"wyzz", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(3, 1, 2, 2)},
+ {"wyzw", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(3, 1, 2, 3)},
+ {"wyw", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE3(3, 1, 3)},
+ {"wywx", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(3, 1, 3, 0)},
+ {"wywy", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(3, 1, 3, 1)},
+ {"wywz", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(3, 1, 3, 2)},
+ {"wyww", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(3, 1, 3, 3)},
+ {"wz", (getter)Vector_swizzle_get, (setter)Vector_swizzle_set, NULL, SWIZZLE2(3, 2)},
+ {"wzx", (getter)Vector_swizzle_get, (setter)Vector_swizzle_set, NULL, SWIZZLE3(3, 2, 0)},
+ {"wzxx", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(3, 2, 0, 0)},
+ {"wzxy", (getter)Vector_swizzle_get, (setter)Vector_swizzle_set, NULL, SWIZZLE4(3, 2, 0, 1)},
+ {"wzxz", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(3, 2, 0, 2)},
+ {"wzxw", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(3, 2, 0, 3)},
+ {"wzy", (getter)Vector_swizzle_get, (setter)Vector_swizzle_set, NULL, SWIZZLE3(3, 2, 1)},
+ {"wzyx", (getter)Vector_swizzle_get, (setter)Vector_swizzle_set, NULL, SWIZZLE4(3, 2, 1, 0)},
+ {"wzyy", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(3, 2, 1, 1)},
+ {"wzyz", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(3, 2, 1, 2)},
+ {"wzyw", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(3, 2, 1, 3)},
+ {"wzz", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE3(3, 2, 2)},
+ {"wzzx", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(3, 2, 2, 0)},
+ {"wzzy", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(3, 2, 2, 1)},
+ {"wzzz", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(3, 2, 2, 2)},
+ {"wzzw", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(3, 2, 2, 3)},
+ {"wzw", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE3(3, 2, 3)},
+ {"wzwx", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(3, 2, 3, 0)},
+ {"wzwy", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(3, 2, 3, 1)},
+ {"wzwz", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(3, 2, 3, 2)},
+ {"wzww", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(3, 2, 3, 3)},
+ {"ww", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE2(3, 3)},
+ {"wwx", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE3(3, 3, 0)},
+ {"wwxx", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(3, 3, 0, 0)},
+ {"wwxy", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(3, 3, 0, 1)},
+ {"wwxz", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(3, 3, 0, 2)},
+ {"wwxw", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(3, 3, 0, 3)},
+ {"wwy", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE3(3, 3, 1)},
+ {"wwyx", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(3, 3, 1, 0)},
+ {"wwyy", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(3, 3, 1, 1)},
+ {"wwyz", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(3, 3, 1, 2)},
+ {"wwyw", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(3, 3, 1, 3)},
+ {"wwz", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE3(3, 3, 2)},
+ {"wwzx", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(3, 3, 2, 0)},
+ {"wwzy", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(3, 3, 2, 1)},
+ {"wwzz", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(3, 3, 2, 2)},
+ {"wwzw", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(3, 3, 2, 3)},
+ {"www", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE3(3, 3, 3)},
+ {"wwwx", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(3, 3, 3, 0)},
+ {"wwwy", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(3, 3, 3, 1)},
+ {"wwwz", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(3, 3, 3, 2)},
+ {"wwww", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(3, 3, 3, 3)},
#undef AXIS_FROM_CHAR
#undef SWIZZLE1
diff --git a/source/blender/render/intern/source/render_result.c b/source/blender/render/intern/source/render_result.c
index cf9bfe99474..b5c2db96c47 100644
--- a/source/blender/render/intern/source/render_result.c
+++ b/source/blender/render/intern/source/render_result.c
@@ -335,8 +335,10 @@ RenderResult *render_result_new(Render *re,
BLI_strncpy(rl->name, view_layer->name, sizeof(rl->name));
rl->layflag = view_layer->layflag;
- rl->passflag =
- view_layer->passflag; /* for debugging: view_layer->passflag | SCE_PASS_RAYHITS; */
+
+ /* for debugging: view_layer->passflag | SCE_PASS_RAYHITS; */
+ rl->passflag = view_layer->passflag;
+
rl->rectx = rectx;
rl->recty = recty;
diff --git a/source/blender/windowmanager/WM_api.h b/source/blender/windowmanager/WM_api.h
index d4fbbd1ecff..04e3f7e88dc 100644
--- a/source/blender/windowmanager/WM_api.h
+++ b/source/blender/windowmanager/WM_api.h
@@ -42,6 +42,7 @@ extern "C" {
struct ARegion;
struct GHashIterator;
struct GPUViewport;
+struct ID;
struct IDProperty;
struct ImBuf;
struct ImageFormatData;
@@ -178,6 +179,10 @@ void WM_autosave_init(struct wmWindowManager *wm);
void WM_recover_last_session(struct bContext *C, struct ReportList *reports);
void WM_file_tag_modified(void);
+struct ID *WM_file_append_datablock(struct bContext *C,
+ const char *filepath,
+ const short id_code,
+ const char *id_name);
void WM_lib_reload(struct Library *lib, struct bContext *C, struct ReportList *reports);
/* mouse cursors */
@@ -649,7 +654,6 @@ enum {
WM_JOB_PRIORITY = (1 << 0),
WM_JOB_EXCL_RENDER = (1 << 1),
WM_JOB_PROGRESS = (1 << 2),
- WM_JOB_SUSPEND = (1 << 3),
};
/** Identifying jobs by owner alone is unreliable, this isnt saved,
@@ -700,6 +704,7 @@ bool WM_jobs_is_stopped(wmWindowManager *wm, void *owner);
void *WM_jobs_customdata_get(struct wmJob *);
void WM_jobs_customdata_set(struct wmJob *, void *customdata, void (*free)(void *));
void WM_jobs_timer(struct wmJob *, double timestep, unsigned int note, unsigned int endnote);
+void WM_jobs_delay_start(struct wmJob *, double delay_time);
void WM_jobs_callbacks(struct wmJob *,
void (*startjob)(void *, short *, short *, float *),
void (*initjob)(void *),
diff --git a/source/blender/windowmanager/WM_types.h b/source/blender/windowmanager/WM_types.h
index d2a876dfb5e..a0c7e8ef752 100644
--- a/source/blender/windowmanager/WM_types.h
+++ b/source/blender/windowmanager/WM_types.h
@@ -19,24 +19,35 @@
/** \file
* \ingroup wm
- */
-
-#ifndef __WM_TYPES_H__
-#define __WM_TYPES_H__
-
-/**
+ *
+ *
* Overview of WM structs
* ======================
*
- * <pre>
- * > wmWindowManager (window manager stores a list of windows)
- * > > wmWindow (window has an active screen)
- * > > > bScreen (link to ScrAreas via 'areabase')
- * > > > > ScrArea (stores multiple spaces via space links via 'spacedata')
- * > > > > > SpaceLink (base struct for space data for all different space types)
- * > > > > ScrArea (stores multiple regions via 'regionbase')
- * > > > > > ARegion
- * </pre>
+ * - #wmWindowManager.windows -> #wmWindow <br>
+ * Window manager stores a list of windows.
+ *
+ * - #wmWindow.screen -> #bScreen <br>
+ * Window has an active screen.
+ *
+ * - #bScreen.areabase -> #ScrArea <br>
+ * Link to #ScrArea.
+ *
+ * - #ScrArea.spacedata <br>
+ * Stores multiple spaces via space links.
+ *
+ * - #SpaceLink <br>
+ * Base struct for space data for all different space types.
+ *
+ * - #ScrArea.regionbase -> #ARegion <br>
+ * Stores multiple regions.
+ *
+ * - #bScreen.regionbase -> #ARegion <br>
+ * Global screen level regions, e.g. popups, popovers, menus.
+ *
+ * - #wmWindow.global_areas -> #ScrAreaMap <br>
+ * Global screen via 'areabase', e.g. top-bar & status-bar.
+ *
*
* Window Layout
* =============
@@ -95,6 +106,9 @@
* \endcode
*/
+#ifndef __WM_TYPES_H__
+#define __WM_TYPES_H__
+
#ifdef __cplusplus
extern "C" {
#endif
@@ -141,7 +155,7 @@ enum {
OPTYPE_REGISTER = (1 << 0),
/** Do an undo push after the operator runs. */
OPTYPE_UNDO = (1 << 1),
- /** Let Blender grab all input from the WM (X11) */
+ /** Let Blender grab all input from the WM (X11). */
OPTYPE_BLOCKING = (1 << 2),
OPTYPE_MACRO = (1 << 3),
@@ -178,8 +192,10 @@ enum {
WM_CURSOR_WRAP_XY,
};
-/* context to call operator in for WM_operator_name_call */
-/* rna_ui.c contains EnumPropertyItem's of these, keep in sync */
+/**
+ * Context to call operator in for #WM_operator_name_call.
+ * rna_ui.c contains EnumPropertyItem's of these, keep in sync.
+ */
enum {
/* if there's invoke, call it, otherwise exec */
WM_OP_INVOKE_DEFAULT,
@@ -448,80 +464,106 @@ typedef struct wmNotifier {
#define WM_GESTURE_CIRCLE 5
#define WM_GESTURE_STRAIGHTLINE 6
-/* wmGesture is registered to window listbase, handled by operator callbacks */
-/* tweak gesture is builtin feature */
+/**
+ * wmGesture is registered to #wmWindow.gesture, handled by operator callbacks.
+ * Tweak gesture is builtin feature.
+ */
typedef struct wmGesture {
struct wmGesture *next, *prev;
- int event_type; /* event->type */
- int type; /* gesture type define */
- rcti winrct; /* bounds of region to draw gesture within */
- int points; /* optional, amount of points stored */
- int points_alloc; /* optional, maximum amount of points stored */
+ /** #wmEvent.type */
+ int event_type;
+ /** Gesture type define. */
+ int type;
+ /** bounds of region to draw gesture within. */
+ rcti winrct;
+ /** optional, amount of points stored. */
+ int points;
+ /** optional, maximum amount of points stored. */
+ int points_alloc;
int modal_state;
- /* For modal operators which may be running idle, waiting for an event to activate the gesture.
+ /**
+ * For modal operators which may be running idle, waiting for an event to activate the gesture.
* Typically this is set when the user is click-dragging the gesture
- * (border and circle select for eg). */
+ * (box and circle select for eg).
+ */
uint is_active : 1;
- /* Previous value of is-active (use to detect first run & edge cases). */
+ /** Previous value of is-active (use to detect first run & edge cases). */
uint is_active_prev : 1;
- /* Use for gestures that support both immediate or delayed activation. */
+ /** Use for gestures that support both immediate or delayed activation. */
uint wait_for_input : 1;
+ /**
+ * customdata
+ * - for border is a #rcti.
+ * - for circle is recti, (xmin, ymin) is center, xmax radius.
+ * - for lasso is short array.
+ * - for straight line is a recti: (xmin,ymin) is start, (xmax, ymax) is end.
+ */
void *customdata;
- /* customdata for border is a recti */
- /* customdata for circle is recti, (xmin, ymin) is center, xmax radius */
- /* customdata for lasso is short array */
- /* 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)*/
+ /** Free pointer to use for operator allocs (if set, its freed on exit). */
wmGenericUserData user_data;
} wmGesture;
/* ************** wmEvent ************************ */
-/* each event should have full modifier state */
-/* event comes from eventmanager and from keymap */
+/**
+ * Each event should have full modifier state.
+ * event comes from event manager and from keymap.
+ */
typedef struct wmEvent {
struct wmEvent *next, *prev;
- short type; /* event code itself (short, is also in keymap) */
- short val; /* press, release, scrollvalue */
- int x, y; /* mouse pointer position, screen coord */
- int mval[2]; /* region mouse position, name convention pre 2.5 :) */
- char utf8_buf[6]; /* from, ghost if utf8 is enabled for the platform,
- * BLI_str_utf8_size() must _always_ be valid, check
- * when assigning s we don't need to check on every access after */
- char ascii; /* from ghost, fallback if utf8 isn't set */
+ /** Event code itself (short, is also in keymap). */
+ short type;
+ /** Press, release, scrollvalue. */
+ short val;
+ /** Mouse pointer position, screen coord. */
+ int x, y;
+ /** Region mouse position, name convention pre 2.5 :). */
+ int mval[2];
+ /**
+ * From, ghost if utf8 is enabled for the platform,
+ * #BLI_str_utf8_size() must _always_ be valid, check
+ * when assigning s we don't need to check on every access after.
+ */
+ char utf8_buf[6];
+ /** From ghost, fallback if utf8 isn't set. */
+ char ascii;
char pad;
- /* previous state, used for double click and the 'click' */
+ /** Previous state, used for double click and the 'click'. */
short prevtype;
short prevval;
int prevx, prevy;
double prevclicktime;
int prevclickx, prevclicky;
- /* modifier states */
- short shift, ctrl, alt, oskey; /* oskey is apple or windowskey, value denotes order of pressed */
- short keymodifier; /* rawkey modifier */
+ /** Modifier states. */
+ /** 'oskey' is apple or windows-key, value denotes order of pressed. */
+ short shift, ctrl, alt, oskey;
+ /** rawkey modifier. */
+ short keymodifier;
- /* set in case a KM_PRESS went by unhandled */
+ /** Set in case a #KM_PRESS went by unhandled. */
char check_click;
char check_drag;
char is_motion_absolute;
- /* keymap item, set by handler (weak?) */
+ /** Keymap item, set by handler (weak?). */
const char *keymap_idname;
- /* tablet info, only use when the tablet is active */
+ /** Tablet info, only use when the tablet is active. */
const struct wmTabletData *tablet_data;
/* custom data */
- short custom; /* custom data type, stylus, 6dof, see wm_event_types.h */
+ /** Custom data type, stylus, 6dof, see wm_event_types.h */
+ short custom;
short customdatafree;
int pad2;
- void *customdata; /* ascii, unicode, mouse coords, angles, vectors, dragdrop info */
+ /** Ascii, unicode, mouse coords, angles, vectors, dragdrop info. */
+ void *customdata;
} wmEvent;
@@ -543,32 +585,46 @@ bool WM_event_cursor_click_drag_threshold_met(const wmEvent *event);
/* ************** custom wmEvent data ************** */
typedef struct wmTabletData {
- int Active; /* 0=EVT_TABLET_NONE, 1=EVT_TABLET_STYLUS, 2=EVT_TABLET_ERASER */
- float Pressure; /* range 0.0 (not touching) to 1.0 (full pressure) */
- float Xtilt; /* range 0.0 (upright) to 1.0 (tilted fully against the tablet surface) */
- float Ytilt; /* as above */
+ /** 0=EVT_TABLET_NONE, 1=EVT_TABLET_STYLUS, 2=EVT_TABLET_ERASER. */
+ int Active;
+ /** range 0.0 (not touching) to 1.0 (full pressure). */
+ float Pressure;
+ /** range 0.0 (upright) to 1.0 (tilted fully against the tablet surface). */
+ float Xtilt;
+ /** as above. */
+ float Ytilt;
} wmTabletData;
-typedef enum { /* motion progress, for modal handlers */
- P_NOT_STARTED,
- P_STARTING, /* <-- */
- P_IN_PROGRESS, /* <-- only these are sent for NDOF motion*/
- P_FINISHING, /* <-- */
- P_FINISHED,
+/** Motion progress, for modal handlers. */
+typedef enum {
+ P_NOT_STARTED,
+ P_STARTING, /* <-- */
+ P_IN_PROGRESS, /* <-- only these are sent for NDOF motion. */
+ P_FINISHING, /* <-- */
+ P_FINISHED,
} wmProgress;
#ifdef WITH_INPUT_NDOF
typedef struct wmNDOFMotionData {
/* awfully similar to GHOST_TEventNDOFMotionData... */
- /* Each component normally ranges from -1 to +1, but can exceed that.
+ /**
+ * Each component normally ranges from -1 to +1, but can exceed that.
* These use blender standard view coordinates,
- * with positive rotations being CCW about the axis. */
- float tvec[3]; /* translation */
- float rvec[3]; /* rotation: */
- /* axis = (rx,ry,rz).normalized */
- /* amount = (rx,ry,rz).magnitude [in revolutions, 1.0 = 360 deg] */
- float dt; /* time since previous NDOF Motion event */
- wmProgress progress; /* is this the first event, the last, or one of many in between? */
+ * with positive rotations being CCW about the axis.
+ */
+ /** Translation. */
+ float tvec[3];
+ /** Rotation.
+ * <pre>
+ * axis = (rx,ry,rz).normalized.
+ * amount = (rx,ry,rz).magnitude [in revolutions, 1.0 = 360 deg]
+ * </pre>
+ */
+ float rvec[3];
+ /** Time since previous NDOF Motion event. */
+ float dt;
+ /** Is this the first event, the last, or one of many in between? */
+ wmProgress progress;
} wmNDOFMotionData;
#endif /* WITH_INPUT_NDOF */
@@ -581,82 +637,113 @@ typedef enum {
typedef struct wmTimer {
struct wmTimer *next, *prev;
- struct wmWindow *win; /* window this timer is attached to (optional) */
+ /** Window this timer is attached to (optional). */
+ struct wmWindow *win;
- double timestep; /* set by timer user */
- int event_type; /* set by timer user, goes to event system */
- wmTimerFlags flags; /* Various flags controlling timer options, see below. */
- void *customdata; /* set by timer user, to allow custom values */
-
- double duration; /* total running time in seconds */
- double delta; /* time since previous step in seconds */
+ /** Set by timer user. */
+ double timestep;
+ /** Set by timer user, goes to event system. */
+ int event_type;
+ /** Various flags controlling timer options, see below. */
+ wmTimerFlags flags;
+ /** Set by timer user, to allow custom values. */
+ void *customdata;
- double ltime; /* internal, last time timer was activated */
- double ntime; /* internal, next time we want to activate the timer */
- double stime; /* internal, when the timer started */
- bool sleep; /* internal, put timers to sleep when needed */
+ /** Total running time in seconds. */
+ double duration;
+ /** Time since previous step in seconds. */
+ double delta;
+
+ /** Internal, last time timer was activated. */
+ double ltime;
+ /** Internal, next time we want to activate the timer. */
+ double ntime;
+ /** Internal, when the timer started. */
+ double stime;
+ /** Internal, put timers to sleep when needed. */
+ bool sleep;
} wmTimer;
typedef struct wmOperatorType {
- const char *name; /* text for ui, undo */
- const char *idname; /* unique identifier */
+ /** Text for UI, undo. */
+ const char *name;
+ /** Unique identifier. */
+ const char *idname;
const char *translation_context;
- const char *description; /* tooltips and python docs */
- const char *undo_group; /* identifier to group operators together */
+ /** Use for tool-tips and Python docs. */
+ const char *description;
+ /** Identifier to group operators together. */
+ const char *undo_group;
- /* this callback executes the operator without any interactive input,
+ /**
+ * This callback executes the operator without any interactive input,
* parameters may be provided through operator properties. cannot use
* any interface code or input device state.
- * - see defines below for return values */
+ * See defines below for return values.
+ */
int (*exec)(struct bContext *, struct wmOperator *) ATTR_WARN_UNUSED_RESULT;
- /* this callback executes on a running operator whenever as property
+ /**
+ * This callback executes on a running operator whenever as property
* is changed. It can correct its own properties or report errors for
* invalid settings in exceptional cases.
- * Boolean return value, True denotes a change has been made and to redraw */
+ * Boolean return value, True denotes a change has been made and to redraw.
+ */
bool (*check)(struct bContext *, struct wmOperator *);
- /* for modal temporary operators, initially invoke is called. then
+ /**
+ * For modal temporary operators, initially invoke is called. then
* any further events are handled in modal. if the operation is
* canceled due to some external reason, cancel is called
- * - see defines below for return values */
+ * See defines below for return values.
+ */
int (*invoke)(struct bContext *,
struct wmOperator *,
const struct wmEvent *) ATTR_WARN_UNUSED_RESULT;
- /* Called when a modal operator is canceled (not used often).
- * Internal cleanup can be done here if needed. */
+ /**
+ * Called when a modal operator is canceled (not used often).
+ * Internal cleanup can be done here if needed.
+ */
void (*cancel)(struct bContext *, struct wmOperator *);
- /* Modal is used for operators which continuously run, eg:
+ /**
+ * Modal is used for operators which continuously run, eg:
* fly mode, knife tool, circle select are all examples of modal operators.
* Modal operators can handle events which would normally access other operators,
- * they keep running until they don't return `OPERATOR_RUNNING_MODAL`. */
+ * they keep running until they don't return `OPERATOR_RUNNING_MODAL`.
+ */
int (*modal)(struct bContext *,
struct wmOperator *,
const struct wmEvent *) ATTR_WARN_UNUSED_RESULT;
- /* verify if the operator can be executed in the current context, note
- * that the operator might still fail to execute even if this return true */
+ /**
+ * Verify if the operator can be executed in the current context, note
+ * that the operator might still fail to execute even if this return true.
+ */
bool (*poll)(struct bContext *) ATTR_WARN_UNUSED_RESULT;
- /* Use to check if properties should be displayed in auto-generated UI.
- * Use 'check' callback to enforce refreshing. */
+ /**
+ * 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,
const PropertyRNA *prop) ATTR_WARN_UNUSED_RESULT;
- /* optional panel for redo and repeat, autogenerated if not set */
+ /** Optional panel for redo and repeat, auto-generated if not set. */
void (*ui)(struct bContext *, struct wmOperator *);
- /* Return a different name to use in the user interface, based on property values.
- * The returned string does not need to be freed. */
+ /**
+ * Return a different name to use in the user interface, based on property values.
+ * The returned string does not need to be freed.
+ */
const char *(*get_name)(struct wmOperatorType *, struct PointerRNA *);
- /* rna for properties */
+ /** rna for properties */
struct StructRNA *srna;
- /* previous settings - for initializing on re-use */
+ /** previous settings - for initializing on re-use */
struct IDProperty *last_properties;
/**
@@ -668,36 +755,42 @@ typedef struct wmOperatorType {
*/
PropertyRNA *prop;
- /* struct wmOperatorTypeMacro */
+ /** struct wmOperatorTypeMacro */
ListBase macro;
- /* pointer to modal keymap, do not free! */
+ /** pointer to modal keymap, do not free! */
struct wmKeyMap *modalkeymap;
- /* python needs the operator type as well */
+ /** python needs the operator type as well */
bool (*pyop_poll)(struct bContext *, struct wmOperatorType *ot) ATTR_WARN_UNUSED_RESULT;
- /* RNA integration */
+ /** RNA integration */
ExtensionRNA ext;
- /* Flag last for padding */
+ /** Flag last for padding */
short flag;
} wmOperatorType;
#ifdef WITH_INPUT_IME
/* *********** Input Method Editor (IME) *********** */
-
-/* similar to GHOST_TEventImeData */
+/**
+ * \note similar to #GHOST_TEventImeData.
+ */
typedef struct wmIMEData {
size_t result_len, composite_len;
- char *str_result; /* utf8 encoding */
- char *str_composite; /* utf8 encoding */
+ /** utf8 encoding */
+ char *str_result;
+ /** utf8 encoding */
+ char *str_composite;
- int cursor_pos; /* cursor position in the IME composition. */
- int sel_start; /* beginning of the selection */
- int sel_end; /* end of the selection */
+ /** Cursor position in the IME composition. */
+ int cursor_pos;
+ /** Beginning of the selection. */
+ int sel_start;
+ /** End of the selection. */
+ int sel_end;
bool is_ime_composing;
} wmIMEData;
@@ -732,40 +825,52 @@ typedef struct wmDragID {
typedef struct wmDrag {
struct wmDrag *next, *prev;
- int icon, type; /* type, see WM_DRAG defines above */
+ int icon;
+ /** See 'WM_DRAG_' defines above. */
+ int type;
void *poin;
char path[1024]; /* FILE_MAX */
double value;
- struct ImBuf *imb; /* if no icon but imbuf should be drawn around cursor */
+ /** If no icon but imbuf should be drawn around cursor. */
+ struct ImBuf *imb;
float scale;
int sx, sy;
- char opname[200]; /* if set, draws operator name*/
+ /** If set, draws operator name. */
+ char opname[200];
unsigned int flags;
- ListBase ids; /* List of wmDragIDs, all are guaranteed to have the same ID type. */
+ /** List of wmDragIDs, all are guaranteed to have the same ID type. */
+ ListBase ids;
} wmDrag;
-/* dropboxes are like keymaps, part of the screen/area/region definition */
-/* allocation and free is on startup and exit */
+/**
+ * Dropboxes are like keymaps, part of the screen/area/region definition.
+ * Allocation and free is on startup and exit.
+ */
typedef struct wmDropBox {
struct wmDropBox *next, *prev;
- /* test if the dropbox is active, then can print optype name */
+ /** Test if the dropbox is active, then can print optype name. */
bool (*poll)(struct bContext *, struct wmDrag *, const wmEvent *, const char **);
- /* before exec, this copies drag info to wmDrop properties */
+ /** Before exec, this copies drag info to #wmDrop properties. */
void (*copy)(struct wmDrag *, struct wmDropBox *);
- /* if poll survives, operator is called */
- wmOperatorType *ot; /* not saved in file, so can be pointer */
+ /**
+ * If poll succeeds, operator is called.
+ * Not saved in file, so can be pointer.
+ */
+ wmOperatorType *ot;
- struct IDProperty
- *properties; /* operator properties, assigned to ptr->data and can be written to a file */
- struct PointerRNA *ptr; /* rna pointer to access properties */
+ /** Operator properties, assigned to ptr->data and can be written to a file. */
+ struct IDProperty *properties;
+ /** RNA pointer to access properties. */
+ struct PointerRNA *ptr;
- short opcontext; /* default invoke */
+ /** Default invoke. */
+ short opcontext;
} wmDropBox;
diff --git a/source/blender/windowmanager/gizmo/WM_gizmo_types.h b/source/blender/windowmanager/gizmo/WM_gizmo_types.h
index 68ecdeea936..7bb77375934 100644
--- a/source/blender/windowmanager/gizmo/WM_gizmo_types.h
+++ b/source/blender/windowmanager/gizmo/WM_gizmo_types.h
@@ -248,6 +248,9 @@ struct wmGizmo {
struct IDProperty *properties;
+ /** Redraw tag. */
+ bool do_draw;
+
/** Temporary data (assume dirty). */
union {
float f;
@@ -317,7 +320,7 @@ typedef struct wmGizmoType {
wmGizmoFnDrawSelect draw_select;
/** Determine if the mouse intersects with the gizmo.
- * The calculation should be done in the callback itself, -1 for no seleciton. */
+ * The calculation should be done in the callback itself, -1 for no selection. */
wmGizmoFnTestSelect test_select;
/** Handler used by the gizmo. Usually handles interaction tied to a gizmo type. */
diff --git a/source/blender/windowmanager/gizmo/intern/wm_gizmo_group.c b/source/blender/windowmanager/gizmo/intern/wm_gizmo_group.c
index 40d99ce8ba6..50c98630a16 100644
--- a/source/blender/windowmanager/gizmo/intern/wm_gizmo_group.c
+++ b/source/blender/windowmanager/gizmo/intern/wm_gizmo_group.c
@@ -927,6 +927,15 @@ wmGizmoGroup *WM_gizmomaptype_group_init_runtime_with_region(wmGizmoMapType *gzm
wmGizmoGroup *gzgroup = wm_gizmogroup_new_from_type(gzmap, gzgt);
+ /* Don't allow duplicates when switching modes for e.g. see: T66229. */
+ LISTBASE_FOREACH (wmGizmoGroup *, gzgroup_iter, &gzmap->groups) {
+ if (gzgroup_iter->type == gzgt) {
+ if (gzgroup_iter != gzgroup) {
+ WM_gizmo_group_tag_remove(gzgroup_iter);
+ }
+ }
+ }
+
wm_gizmomap_highlight_set(gzmap, NULL, NULL, 0);
ED_region_tag_redraw(ar);
diff --git a/source/blender/windowmanager/gizmo/intern/wm_gizmo_map.c b/source/blender/windowmanager/gizmo/intern/wm_gizmo_map.c
index be123bee5df..534474a6221 100644
--- a/source/blender/windowmanager/gizmo/intern/wm_gizmo_map.c
+++ b/source/blender/windowmanager/gizmo/intern/wm_gizmo_map.c
@@ -552,6 +552,9 @@ static int gizmo_find_intersected_3d_intern(wmGizmo **visible_gizmos,
bool use_select_bias = false;
+ /* TODO: waiting for the GPU in the middle of the event loop for every
+ * mouse move is bad for performance, we need to find a solution to not
+ * use the GPU or draw something once. (see T61474) */
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, visible_gizmos_len, &use_select_bias);
@@ -644,7 +647,7 @@ static wmGizmo *gizmo_find_intersected_3d(bContext *C,
break;
}
}
- else {
+ else if (gz->type->draw_select != NULL) {
has_3d = true;
}
}
@@ -1239,7 +1242,7 @@ void wm_gizmos_keymap(wmKeyConfig *keyconf)
/** \} */ /* wmGizmoMapType */
/* -------------------------------------------------------------------- */
-/** \name Updates for Dynamic Type Registraion
+/** \name Updates for Dynamic Type Registration
*
* \{ */
@@ -1283,32 +1286,6 @@ void WM_gizmoconfig_update(struct Main *bmain)
return;
}
- if (wm_gzmap_type_update_flag & WM_GIZMOTYPE_GLOBAL_UPDATE_REMOVE) {
- 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) {
- ListBase *regionbase = (sl == sa->spacedata.first) ? &sa->regionbase : &sl->regionbase;
- for (ARegion *ar = regionbase->first; ar; ar = ar->next) {
- wmGizmoMap *gzmap = ar->gizmo_map;
- if (gzmap != NULL && gzmap->tag_remove_group) {
- gzmap->tag_remove_group = false;
-
- for (wmGizmoGroup *gzgroup = gzmap->groups.first, *gzgroup_next; gzgroup;
- gzgroup = gzgroup_next) {
- gzgroup_next = gzgroup->next;
- if (gzgroup->tag_remove) {
- wm_gizmogroup_free(NULL, gzgroup);
- ED_region_tag_redraw(ar);
- }
- }
- }
- }
- }
- }
- }
- wm_gzmap_type_update_flag &= ~WM_GIZMOTYPE_GLOBAL_UPDATE_REMOVE;
- }
-
if (wm_gzmap_type_update_flag & WM_GIZMOMAPTYPE_GLOBAL_UPDATE_REMOVE) {
for (wmGizmoMapType *gzmap_type = gizmomaptypes.first; gzmap_type;
gzmap_type = gzmap_type->next) {
@@ -1352,6 +1329,32 @@ void WM_gizmoconfig_update(struct Main *bmain)
wm_gzmap_type_update_flag &= ~WM_GIZMOMAPTYPE_GLOBAL_UPDATE_INIT;
}
+
+ if (wm_gzmap_type_update_flag & WM_GIZMOTYPE_GLOBAL_UPDATE_REMOVE) {
+ 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) {
+ ListBase *regionbase = (sl == sa->spacedata.first) ? &sa->regionbase : &sl->regionbase;
+ for (ARegion *ar = regionbase->first; ar; ar = ar->next) {
+ wmGizmoMap *gzmap = ar->gizmo_map;
+ if (gzmap != NULL && gzmap->tag_remove_group) {
+ gzmap->tag_remove_group = false;
+
+ for (wmGizmoGroup *gzgroup = gzmap->groups.first, *gzgroup_next; gzgroup;
+ gzgroup = gzgroup_next) {
+ gzgroup_next = gzgroup->next;
+ if (gzgroup->tag_remove) {
+ wm_gizmogroup_free(NULL, gzgroup);
+ ED_region_tag_redraw(ar);
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ wm_gzmap_type_update_flag &= ~WM_GIZMOTYPE_GLOBAL_UPDATE_REMOVE;
+ }
}
/** \} */
diff --git a/source/blender/windowmanager/intern/wm_draw.c b/source/blender/windowmanager/intern/wm_draw.c
index 56fc38160f0..fc669c9543e 100644
--- a/source/blender/windowmanager/intern/wm_draw.c
+++ b/source/blender/windowmanager/intern/wm_draw.c
@@ -188,6 +188,26 @@ static void wm_area_mark_invalid_backbuf(ScrArea *sa)
}
}
+static void wm_region_test_gizmo_do_draw(ARegion *ar, bool tag_redraw)
+{
+ if (ar->gizmo_map == NULL) {
+ return;
+ }
+
+ wmGizmoMap *gzmap = ar->gizmo_map;
+ for (wmGizmoGroup *gzgroup = WM_gizmomap_group_list(gzmap)->first; gzgroup;
+ gzgroup = gzgroup->next) {
+ for (wmGizmo *gz = gzgroup->gizmos.first; gz; gz = gz->next) {
+ if (gz->do_draw) {
+ if (tag_redraw) {
+ ED_region_tag_redraw_no_rebuild(ar);
+ }
+ gz->do_draw = false;
+ }
+ }
+ }
+}
+
static void wm_region_test_render_do_draw(const Scene *scene,
struct Depsgraph *depsgraph,
ScrArea *sa,
@@ -817,6 +837,7 @@ static bool wm_draw_update_test_window(wmWindow *win)
ED_screen_areas_iter(win, screen, sa)
{
for (ar = sa->regionbase.first; ar; ar = ar->next) {
+ wm_region_test_gizmo_do_draw(ar, true);
wm_region_test_render_do_draw(scene, depsgraph, sa, ar);
if (ar->visible && ar->do_draw) {
@@ -848,6 +869,24 @@ static bool wm_draw_update_test_window(wmWindow *win)
return false;
}
+/* Clear drawing flags, after drawing is complete so any draw flags set during
+ * drawing don't cause any additional redraws. */
+static void wm_draw_update_clear_window(wmWindow *win)
+{
+ bScreen *screen = WM_window_get_active_screen(win);
+
+ ED_screen_areas_iter(win, screen, sa)
+ {
+ for (ARegion *ar = sa->regionbase.first; ar; ar = ar->next) {
+ wm_region_test_gizmo_do_draw(ar, false);
+ }
+ }
+
+ screen->do_draw_gesture = false;
+ screen->do_draw_paintcursor = false;
+ screen->do_draw_drag = false;
+}
+
void WM_paint_cursor_tag_redraw(wmWindow *win, ARegion *UNUSED(ar))
{
if (win) {
@@ -893,10 +932,7 @@ void wm_draw_update(bContext *C)
ED_screen_ensure_updated(wm, win, screen);
wm_draw_window(C, win);
-
- screen->do_draw_gesture = false;
- screen->do_draw_paintcursor = false;
- screen->do_draw_drag = false;
+ wm_draw_update_clear_window(win);
wm_window_swap_buffers(win);
diff --git a/source/blender/windowmanager/intern/wm_event_system.c b/source/blender/windowmanager/intern/wm_event_system.c
index 24040568b7b..76cb78b1e04 100644
--- a/source/blender/windowmanager/intern/wm_event_system.c
+++ b/source/blender/windowmanager/intern/wm_event_system.c
@@ -98,7 +98,7 @@
* Without tools using press events which would prevent click/drag events getting to the gizmos.
*
* This is not a fool proof solution since since it's possible the gizmo operators would pass
- * through thse events when called, see: T65479.
+ * through these events when called, see: T65479.
*/
#define USE_GIZMO_MOUSE_PRIORITY_HACK
@@ -3235,18 +3235,34 @@ void wm_event_do_handlers(bContext *C)
if (scene_eval != NULL) {
const int is_playing_sound = BKE_sound_scene_playing(scene_eval);
- if (is_playing_sound != -1) {
+ if (scene_eval->id.recalc & ID_RECALC_AUDIO_SEEK) {
+ /* Ignore seek here, the audio will be updated to the scene frame after jump during next
+ * dependency graph update. */
+ }
+ else if (is_playing_sound != -1) {
bool is_playing_screen;
is_playing_screen = (ED_screen_animation_playing(wm) != NULL);
if (((is_playing_sound == 1) && (is_playing_screen == 0)) ||
((is_playing_sound == 0) && (is_playing_screen == 1))) {
+ wmWindow *context_old_win = CTX_wm_window(C);
+ bScreen *context_screen_win = CTX_wm_screen(C);
+ Scene *context_scene_win = CTX_data_scene(C);
+
+ CTX_wm_window_set(C, win);
+ CTX_wm_screen_set(C, screen);
+ CTX_data_scene_set(C, scene);
+
ED_screen_animation_play(C, -1, 1);
+
+ CTX_data_scene_set(C, context_scene_win);
+ CTX_wm_screen_set(C, context_screen_win);
+ CTX_wm_window_set(C, context_old_win);
}
if (is_playing_sound == 0) {
- const float time = BKE_sound_sync_scene(scene);
+ const float time = BKE_sound_sync_scene(scene_eval);
if (isfinite(time)) {
int ncfra = time * (float)FPS + 0.5f;
if (ncfra != scene->r.cfra) {
diff --git a/source/blender/windowmanager/intern/wm_files.c b/source/blender/windowmanager/intern/wm_files.c
index fe93e39b085..48b09b0d329 100644
--- a/source/blender/windowmanager/intern/wm_files.c
+++ b/source/blender/windowmanager/intern/wm_files.c
@@ -623,8 +623,6 @@ 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;
@@ -634,7 +632,17 @@ bool WM_file_read(bContext *C, const char *filepath, ReportList *reports)
/* confusing this global... */
G.relbase_valid = 1;
- retval = BKE_blendfile_read(C, filepath, &(const struct BlendFileReadParams){0}, reports);
+ retval = BKE_blendfile_read(
+ C,
+ filepath,
+ /* Loading preferences when the user intended to load a regular file is a security risk,
+ * because the excluded path list is also loaded.
+ * Further it's just confusing if a user loads a file and various preferences change. */
+ &(const struct BlendFileReadParams){
+ .is_startup = false,
+ .skip_flags = BLO_READ_SKIP_USERDEF,
+ },
+ reports);
/* BKE_file_read sets new Main into context. */
Main *bmain = CTX_data_main(C);
@@ -660,18 +668,14 @@ bool WM_file_read(bContext *C, const char *filepath, ReportList *reports)
wm_window_match_do(C, &wmbase, &bmain->wm, &bmain->wm);
WM_check(C); /* opens window(s), checks keymaps */
- 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) {
if (do_history) {
wm_history_file_update();
}
}
+ const bool use_data = true;
+ const bool use_userdef = false;
wm_file_read_post(C, false, false, use_data, use_userdef, false);
success = true;
@@ -1376,7 +1380,7 @@ static bool wm_file_write(bContext *C, const char *filepath, int fileflags, Repo
/* operator now handles overwrite checks */
if (G.fileflags & G_FILE_AUTOPACK) {
- packAll(bmain, reports, false);
+ BKE_packedfile_pack_all(bmain, reports, false);
}
/* don't forget not to return without! */
@@ -1861,7 +1865,9 @@ 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->description =
+ "Load factory default preferences. "
+ "To make changes to preferences permanent, use \"Save Preferences\"";
ot->invoke = WM_operator_confirm;
ot->exec = wm_userpref_read_exec;
@@ -2034,7 +2040,9 @@ void WM_OT_read_factory_settings(wmOperatorType *ot)
{
ot->name = "Load Factory Settings";
ot->idname = "WM_OT_read_factory_settings";
- ot->description = "Load default file and preferences";
+ ot->description =
+ "Load factory default startup file and preferences. "
+ "To make changes permanent, use \"Save Startup File\" and \"Save Preferences\"";
ot->invoke = WM_operator_confirm;
ot->exec = wm_homefile_read_exec;
@@ -2949,7 +2957,12 @@ static void wm_block_file_close_save(bContext *C, void *arg_block, void *arg_dat
UI_popup_block_close(C, win, arg_block);
if (save_images_when_file_is_closed) {
- if (!ED_image_should_save_modified(C)) {
+ if (ED_image_should_save_modified(C)) {
+ ReportList *reports = CTX_wm_reports(C);
+ ED_image_save_all_modified(C, reports);
+ WM_report_banner_show();
+ }
+ else {
execute_callback = false;
}
}
diff --git a/source/blender/windowmanager/intern/wm_files_link.c b/source/blender/windowmanager/intern/wm_files_link.c
index 1a46a4550d9..5a6606984ba 100644
--- a/source/blender/windowmanager/intern/wm_files_link.c
+++ b/source/blender/windowmanager/intern/wm_files_link.c
@@ -464,6 +464,8 @@ static int wm_link_append_exec(bContext *C, wmOperator *op)
if (lapp_data->num_items == 0) {
/* Early out in case there is nothing to link. */
wm_link_append_data_free(lapp_data);
+ /* Clear pre existing tag. */
+ BKE_main_id_tag_all(bmain, LIB_TAG_PRE_EXISTING, false);
return OPERATOR_CANCELLED;
}
@@ -616,10 +618,50 @@ void WM_OT_append(wmOperatorType *ot)
"Localize all appended data, including those indirectly linked from other libraries");
}
-/** \name Reload/relocate libraries.
+/** \name Append single datablock and return it.
+ *
+ * Used for appending workspace from startup files.
*
* \{ */
+ID *WM_file_append_datablock(bContext *C,
+ const char *filepath,
+ const short id_code,
+ const char *id_name)
+{
+ Main *bmain = CTX_data_main(C);
+
+ /* Tag everything so we can make local only the new datablock. */
+ BKE_main_id_tag_all(bmain, LIB_TAG_PRE_EXISTING, true);
+
+ /* Define working data, with just the one item we want to append. */
+ WMLinkAppendData *lapp_data = wm_link_append_data_new(0);
+
+ wm_link_append_data_library_add(lapp_data, filepath);
+ WMLinkAppendDataItem *item = wm_link_append_data_item_add(lapp_data, id_name, id_code, NULL);
+ BLI_BITMAP_ENABLE(item->libraries, 0);
+
+ /* Link datablock. */
+ Scene *scene = CTX_data_scene(C);
+ ViewLayer *view_layer = CTX_data_view_layer(C);
+ View3D *v3d = CTX_wm_view3d(C);
+ wm_link_do(lapp_data, NULL, bmain, scene, view_layer, v3d);
+
+ /* Get linked datablock and free working data. */
+ ID *id = item->new_id;
+ wm_link_append_data_free(lapp_data);
+
+ /* Make datablock local. */
+ BKE_library_make_local(bmain, NULL, NULL, true, false);
+
+ /* Clear pre existing tag. */
+ BKE_main_id_tag_all(bmain, LIB_TAG_PRE_EXISTING, false);
+
+ return id;
+}
+
+/** \} */
+
static int wm_lib_relocate_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event))
{
Library *lib;
diff --git a/source/blender/windowmanager/intern/wm_init_exit.c b/source/blender/windowmanager/intern/wm_init_exit.c
index e74b3c1ef07..f3c94162786 100644
--- a/source/blender/windowmanager/intern/wm_init_exit.c
+++ b/source/blender/windowmanager/intern/wm_init_exit.c
@@ -166,7 +166,7 @@ void WM_init_state_start_with_console_set(bool value)
/**
* Since we cannot know in advance if we will require the draw manager
* context when starting blender in background mode (specially true with
- * scripts) we deferre the ghost initialization the most as possible
+ * scripts) we defer the ghost initialization the most as possible
* so that it does not break anything that can run in headless mode (as in
* without display server attached).
*/
diff --git a/source/blender/windowmanager/intern/wm_jobs.c b/source/blender/windowmanager/intern/wm_jobs.c
index a63592f7b60..a417d80a9a9 100644
--- a/source/blender/windowmanager/intern/wm_jobs.c
+++ b/source/blender/windowmanager/intern/wm_jobs.c
@@ -92,6 +92,8 @@ struct wmJob {
/** Running jobs each have own timer */
double timestep;
wmTimer *wt;
+ /** Only start job after specified time delay */
+ double start_delay_time;
/** The notifier event timers should send */
unsigned int note, endnote;
@@ -356,6 +358,11 @@ void WM_jobs_timer(wmJob *wm_job, double timestep, unsigned int note, unsigned i
wm_job->endnote = endnote;
}
+void WM_jobs_delay_start(wmJob *wm_job, double delay_time)
+{
+ wm_job->start_delay_time = delay_time;
+}
+
void WM_jobs_callbacks(wmJob *wm_job,
void (*startjob)(void *, short *, short *, float *),
void (*initjob)(void *),
@@ -386,9 +393,9 @@ static void wm_jobs_test_suspend_stop(wmWindowManager *wm, wmJob *test)
bool suspend = false;
/* job added with suspend flag, we wait 1 timer step before activating it */
- if (test->flag & WM_JOB_SUSPEND) {
+ if (test->start_delay_time > 0.0) {
suspend = true;
- test->flag &= ~WM_JOB_SUSPEND;
+ test->start_delay_time = 0.0;
}
else {
/* check other jobs */
@@ -441,6 +448,8 @@ void WM_jobs_start(wmWindowManager *wm, wmJob *wm_job)
else {
if (wm_job->customdata && wm_job->startjob) {
+ const double timestep = (wm_job->start_delay_time > 0.0) ? wm_job->start_delay_time :
+ wm_job->timestep;
wm_jobs_test_suspend_stop(wm, wm_job);
@@ -467,8 +476,12 @@ void WM_jobs_start(wmWindowManager *wm, wmJob *wm_job)
}
/* restarted job has timer already */
+ if (wm_job->wt && (wm_job->wt->timestep > timestep)) {
+ WM_event_remove_timer(wm, wm_job->win, wm_job->wt);
+ wm_job->wt = WM_event_add_timer(wm, wm_job->win, TIMERJOBS, timestep);
+ }
if (wm_job->wt == NULL) {
- wm_job->wt = WM_event_add_timer(wm, wm_job->win, TIMERJOBS, wm_job->timestep);
+ wm_job->wt = WM_event_add_timer(wm, wm_job->win, TIMERJOBS, timestep);
}
wm_job->start_time = PIL_check_seconds_timer();
diff --git a/source/blender/windowmanager/intern/wm_operators.c b/source/blender/windowmanager/intern/wm_operators.c
index 63ca46e05c6..367a5a81098 100644
--- a/source/blender/windowmanager/intern/wm_operators.c
+++ b/source/blender/windowmanager/intern/wm_operators.c
@@ -1151,38 +1151,27 @@ typedef struct wmOpPopUp {
/* Only invoked by OK button in popups created with wm_block_dialog_create() */
static void dialog_exec_cb(bContext *C, void *arg1, void *arg2)
{
- wmOpPopUp *data = arg1;
- uiBlock *block = arg2;
+ wmOperator *op;
+ {
+ /* Execute will free the operator.
+ * In this case, wm_operator_ui_popup_cancel wont run. */
+ wmOpPopUp *data = arg1;
+ op = data->op;
+ MEM_freeN(data);
+ }
+ uiBlock *block = arg2;
/* Explicitly set UI_RETURN_OK flag, otherwise the menu might be canceled
* in case WM_operator_call_ex exits/reloads the current file (T49199). */
- UI_popup_menu_retval_set(block, UI_RETURN_OK, true);
-
- WM_operator_call_ex(C, data->op, true);
- /* let execute handle freeing it */
- // data->free_op = false;
- // data->op = NULL;
-
- /* in this case, wm_operator_ui_popup_cancel wont run */
- MEM_freeN(data);
+ UI_popup_menu_retval_set(block, UI_RETURN_OK, true);
/* Get context data *after* WM_operator_call_ex
* which might have closed the current file and changed context. */
- wmWindowManager *wm = CTX_wm_manager(C);
wmWindow *win = CTX_wm_window(C);
+ UI_popup_block_close(C, win, block);
- /* check window before 'block->handle' incase the
- * popup execution closed the window and freed the block. see T44688.
- */
- /* Post 2.78 TODO: Check if this fix and others related to T44688 are still
- * needed or can be improved now that requesting context data has been corrected
- * (see above). We're close to release so not a good time for experiments.
- * -- Julian
- */
- if (BLI_findindex(&wm->windows, win) != -1) {
- UI_popup_block_close(C, win, block);
- }
+ WM_operator_call_ex(C, op, true);
}
/* Dialogs are popups that require user verification (click OK) before exec */
@@ -1478,43 +1467,113 @@ static void wm_block_splash_refreshmenu(bContext *C, void *UNUSED(arg_block), vo
ED_region_tag_refresh_ui(ar_menu);
}
-static uiBlock *wm_block_create_splash(bContext *C, ARegion *ar, void *UNUSED(arg))
+static void wm_block_splash_add_label(uiBlock *block, const char *label, int x, int *y)
{
- uiBlock *block;
- uiBut *but;
+ if (!(label && label[0])) {
+ return;
+ }
+
uiStyle *style = UI_style_get();
-#ifndef WITH_HEADLESS
- extern char datatoc_splash_png[];
- extern int datatoc_splash_png_size;
+ BLF_size(style->widgetlabel.uifont_id, style->widgetlabel.points, U.pixelsize * U.dpi);
+ int label_width = BLF_width(style->widgetlabel.uifont_id, label, strlen(label));
+ label_width = label_width + U.widget_unit;
- extern char datatoc_splash_2x_png[];
- extern int datatoc_splash_2x_png_size;
- ImBuf *ibuf;
-#else
- ImBuf *ibuf = NULL;
-#endif
+ UI_block_emboss_set(block, UI_EMBOSS_NONE);
+
+ uiBut *but = uiDefBut(block,
+ UI_BTYPE_LABEL,
+ 0,
+ label,
+ x - label_width,
+ *y,
+ label_width,
+ UI_UNIT_Y,
+ NULL,
+ 0,
+ 0,
+ 0,
+ 0,
+ NULL);
+
+ /* 1 = UI_SELECT, internal flag to draw in white. */
+ UI_but_flag_enable(but, 1);
+ UI_block_emboss_set(block, UI_EMBOSS);
+ *y -= 12 * U.dpi_fac;
+}
+
+static void wm_block_splash_add_labels(uiBlock *block, int x, int y)
+{
+ /* Version number. */
+ const char *version_suffix = NULL;
+ bool show_build_info = true;
+
+ if (STREQ(STRINGIFY(BLENDER_VERSION_CYCLE), "alpha")) {
+ version_suffix = " Alpha";
+ }
+ else if (STREQ(STRINGIFY(BLENDER_VERSION_CYCLE), "beta")) {
+ version_suffix = " Beta";
+ }
+ else if (STREQ(STRINGIFY(BLENDER_VERSION_CYCLE), "rc")) {
+ version_suffix = " Release Candidate";
+ show_build_info = false;
+ }
+ else if (STREQ(STRINGIFY(BLENDER_VERSION_CYCLE), "release")) {
+ version_suffix = STRINGIFY(BLENDER_VERSION_CHAR);
+ show_build_info = false;
+ }
+
+ char version_buf[256] = "\0";
+ BLI_snprintf(version_buf,
+ sizeof(version_buf),
+ "v %d.%d%s",
+ BLENDER_VERSION / 100,
+ BLENDER_VERSION % 100,
+ version_suffix);
+
+ wm_block_splash_add_label(block, version_buf, x, &y);
#ifdef WITH_BUILDINFO
- int label_delta = 0;
- int hash_width, date_width;
- char date_buf[128] = "\0";
- char hash_buf[128] = "\0";
- extern unsigned long build_commit_timestamp;
- extern char build_hash[], build_commit_date[], build_commit_time[], build_branch[];
+ if (show_build_info) {
+ extern unsigned long build_commit_timestamp;
+ extern char build_hash[], build_commit_date[], build_commit_time[], build_branch[];
+
+ /* Date, hidden for builds made from tag. */
+ if (build_commit_timestamp != 0) {
+ char date_buf[256] = "\0";
+ BLI_snprintf(
+ date_buf, sizeof(date_buf), "Date: %s %s", build_commit_date, build_commit_time);
+ wm_block_splash_add_label(block, date_buf, x, &y);
+ }
- /* Builds made from tag only shows tag sha */
- BLI_snprintf(hash_buf, sizeof(hash_buf), "Hash: %s", build_hash);
- BLI_snprintf(date_buf, sizeof(date_buf), "Date: %s %s", build_commit_date, build_commit_time);
+ /* Hash. */
+ char hash_buf[256] = "\0";
+ BLI_snprintf(hash_buf, sizeof(hash_buf), "Hash: %s", build_hash);
+ wm_block_splash_add_label(block, hash_buf, x, &y);
- BLF_size(style->widgetlabel.uifont_id, style->widgetlabel.points, U.pixelsize * U.dpi);
- hash_width = (int)BLF_width(style->widgetlabel.uifont_id, hash_buf, sizeof(hash_buf)) +
- U.widget_unit;
- date_width = (int)BLF_width(style->widgetlabel.uifont_id, date_buf, sizeof(date_buf)) +
- U.widget_unit;
+ /* Branch. */
+ if (!STREQ(build_branch, "master")) {
+ char branch_buf[256] = "\0";
+ BLI_snprintf(branch_buf, sizeof(branch_buf), "Branch: %s", build_branch);
+
+ wm_block_splash_add_label(block, branch_buf, x, &y);
+ }
+ }
+#else
+ UNUSED_VARS(show_build_info);
#endif /* WITH_BUILDINFO */
+}
+static ImBuf *wm_block_splash_image(void)
+{
#ifndef WITH_HEADLESS
+ extern char datatoc_splash_png[];
+ extern int datatoc_splash_png_size;
+ extern char datatoc_splash_2x_png[];
+ extern int datatoc_splash_2x_png_size;
+
+ ImBuf *ibuf = NULL;
+
if (U.dpi_fac > 1.0) {
ibuf = IMB_ibImageFromMemory((const uchar *)datatoc_splash_2x_png,
datatoc_splash_2x_png_size,
@@ -1541,7 +1600,7 @@ static uiBlock *wm_block_create_splash(bContext *C, ARegion *ar, void *UNUSED(ar
BLI_join_dirfile(splash_filepath,
sizeof(splash_filepath),
template_directory,
- (U.pixelsize == 2) ? "splash_2x.png" : "splash.png");
+ (U.dpi_fac > 1.0) ? "splash_2x.png" : "splash.png");
ibuf_template = IMB_loadiffname(splash_filepath, IB_rect, NULL);
if (ibuf_template) {
const int x_expect = ibuf->x;
@@ -1565,7 +1624,17 @@ static uiBlock *wm_block_create_splash(bContext *C, ARegion *ar, void *UNUSED(ar
}
}
}
+ return ibuf;
+#else
+ return NULL;
#endif
+}
+
+static uiBlock *wm_block_create_splash(bContext *C, ARegion *ar, void *UNUSED(arg))
+{
+ uiBlock *block;
+ uiBut *but;
+ uiStyle *style = UI_style_get();
block = UI_block_begin(C, ar, "splash", UI_EMBOSS);
@@ -1575,6 +1644,7 @@ static uiBlock *wm_block_create_splash(bContext *C, ARegion *ar, void *UNUSED(ar
UI_block_flag_enable(block, UI_BLOCK_LOOP | UI_BLOCK_KEEP_OPEN | UI_BLOCK_NO_WIN_CLIP);
UI_block_theme_style_set(block, UI_BLOCK_THEME_STYLE_POPUP);
+ ImBuf *ibuf = wm_block_splash_image();
but = uiDefBut(block,
UI_BTYPE_IMAGE,
0,
@@ -1592,109 +1662,15 @@ static uiBlock *wm_block_create_splash(bContext *C, ARegion *ar, void *UNUSED(ar
UI_but_func_set(but, wm_block_splash_close, block, NULL);
UI_block_func_set(block, wm_block_splash_refreshmenu, block, NULL);
- /* label for 'a' bugfix releases, or 'Release Candidate 1'...
- * avoids recreating splash for version updates */
- const char *version_suffix = NULL;
-
- if (STREQ(STRINGIFY(BLENDER_VERSION_CYCLE), "alpha")) {
- version_suffix = " Alpha";
- }
- else if (STREQ(STRINGIFY(BLENDER_VERSION_CYCLE), "beta")) {
- version_suffix = " Beta";
- }
- else if (STREQ(STRINGIFY(BLENDER_VERSION_CYCLE), "rc")) {
- version_suffix = " Release Candidate";
- }
- else if (STREQ(STRINGIFY(BLENDER_VERSION_CYCLE), "release")) {
- version_suffix = STRINGIFY(BLENDER_VERSION_CHAR);
- }
-
- char *version = BLI_sprintfN(
- "Version %d.%d%s", BLENDER_VERSION / 100, BLENDER_VERSION % 100, version_suffix);
-
- if (version != NULL && version[0]) {
- /* placed after the version number in the image,
- * placing y is tricky to match baseline */
- /* hack to have text draw 'text_sel' */
- UI_block_emboss_set(block, UI_EMBOSS_NONE);
- int x = 202 * U.dpi_fac;
- int y = 130 * U.dpi_fac;
- int w = 240 * U.dpi_fac;
+ int x = U.dpi_fac * 502;
+ int y = U.dpi_fac * 237;
- but = uiDefBut(block, UI_BTYPE_LABEL, 0, version, x, y, w, UI_UNIT_Y, NULL, 0, 0, 0, 0, NULL);
- /* XXX, set internal flag - UI_SELECT */
- UI_but_flag_enable(but, 1);
- UI_block_emboss_set(block, UI_EMBOSS);
- }
-
- MEM_freeN(version);
-
-#ifdef WITH_BUILDINFO
- if (build_commit_timestamp != 0) {
- but = uiDefBut(block,
- UI_BTYPE_LABEL,
- 0,
- date_buf,
- U.dpi_fac * 502 - date_width,
- U.dpi_fac * 237,
- date_width,
- UI_UNIT_Y,
- NULL,
- 0,
- 0,
- 0,
- 0,
- NULL);
- /* XXX, set internal flag - UI_SELECT */
- UI_but_flag_enable(but, 0);
- label_delta = 12;
- }
- but = uiDefBut(block,
- UI_BTYPE_LABEL,
- 0,
- hash_buf,
- U.dpi_fac * 502 - hash_width,
- U.dpi_fac * (237 - label_delta),
- hash_width,
- UI_UNIT_Y,
- NULL,
- 0,
- 0,
- 0,
- 0,
- NULL);
- /* XXX, set internal flag - UI_SELECT */
- UI_but_flag_enable(but, 0);
-
- if (!STREQ(build_branch, "master")) {
- char branch_buf[128] = "\0";
- int branch_width;
- BLI_snprintf(branch_buf, sizeof(branch_buf), "Branch: %s", build_branch);
- branch_width = (int)BLF_width(style->widgetlabel.uifont_id, branch_buf, sizeof(branch_buf)) +
- U.widget_unit;
- but = uiDefBut(block,
- UI_BTYPE_LABEL,
- 0,
- branch_buf,
- U.dpi_fac * 502 - branch_width,
- U.dpi_fac * (225 - label_delta),
- branch_width,
- UI_UNIT_Y,
- NULL,
- 0,
- 0,
- 0,
- 0,
- NULL);
- /* XXX, set internal flag - UI_SELECT */
- UI_but_flag_enable(but, 0);
- }
-#endif /* WITH_BUILDINFO */
+ wm_block_splash_add_labels(block, x, y);
uiLayout *layout = UI_block_layout(block,
UI_LAYOUT_VERTICAL,
UI_LAYOUT_PANEL,
- U.dpi_fac * 40,
+ U.dpi_fac * 26,
0,
U.dpi_fac * 450,
U.dpi_fac * 110,
diff --git a/source/blender/windowmanager/intern/wm_utils.c b/source/blender/windowmanager/intern/wm_utils.c
index c0ee1ec44db..b227065e3cf 100644
--- a/source/blender/windowmanager/intern/wm_utils.c
+++ b/source/blender/windowmanager/intern/wm_utils.c
@@ -17,7 +17,7 @@
/** \file
* \ingroup wm
*
- * Generic helper utilies that aren't assosiated with a particular area.
+ * Generic helper utilities that aren't associated with a particular area.
*/
#include "WM_types.h"
diff --git a/source/blender/windowmanager/intern/wm_window.c b/source/blender/windowmanager/intern/wm_window.c
index ea3596a2143..d17b8817691 100644
--- a/source/blender/windowmanager/intern/wm_window.c
+++ b/source/blender/windowmanager/intern/wm_window.c
@@ -714,8 +714,14 @@ void wm_window_ghostwindows_ensure(wmWindowManager *wm)
wm_window_ghostwindow_add(wm, "Blender", win);
}
- /* happens after fileread */
- wm_window_ensure_eventstate(win);
+
+ if (win->ghostwin != NULL) {
+ /* If we have no ghostwin this is a buggy window that should be removed.
+ * However we still need to initialize it correctly so the screen doesn't hang. */
+
+ /* happens after fileread */
+ wm_window_ensure_eventstate(win);
+ }
/* add keymap handlers (1 handler for all keys in map!) */
keymap = WM_keymap_ensure(wm->defaultconf, "Window", 0, 0);
@@ -1201,8 +1207,8 @@ static int ghost_event_proc(GHOST_EventHandle evt, GHOST_TUserDataPtr C_void_ptr
//# define USE_WIN_ACTIVATE
#endif
- wm->winactive =
- win; /* no context change! c->wm->windrawable is drawable, or for area queues */
+ /* No context change! C->wm->windrawable is drawable, or for area queues. */
+ wm->winactive = win;
win->active = 1;
// window_handle(win, INPUTCHANGE, win->active);
@@ -1454,8 +1460,9 @@ static int ghost_event_proc(GHOST_EventHandle evt, GHOST_TUserDataPtr C_void_ptr
event.prevx = event.x;
event.prevy = event.y;
- wm->winactive =
- win; /* no context change! c->wm->windrawable is drawable, or for area queues */
+ /* No context change! C->wm->windrawable is drawable, or for area queues. */
+ wm->winactive = win;
+
win->active = 1;
wm_event_add(win, &event);